diff --git a/Taskfile.yml b/Taskfile.yml index bade351..ec18517 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -38,7 +38,6 @@ tasks: - git add version.txt branch.txt - git commit -m "$(cat version.txt)" || true - git tag -f "v$(cat version.txt)" - trigger: desc: create tag and push triggering a build @@ -52,9 +51,18 @@ tasks: - rm -f ops - task: build + clone-embedded-tasks: + desc: Clone tasks into embedded-tasks for embedding + cmds: + - rm -rf embedded-tasks + - git clone https://github.com/apache/openserverless-task.git embedded-tasks + - cd embedded-tasks && git checkout $(cat ../branch.txt) + build: aliases: [b] desc: build ops locally + deps: + - clone-embedded-tasks cmds: - echo building {{.VERSION}} - go build {{.DEBUG}} ./cmd/ops/ @@ -63,6 +71,7 @@ tasks: - "*/*.go" - version.txt - branch.txt + - embedded-tasks/** generates: - ops @@ -84,7 +93,7 @@ tasks: - cp -v ops $HOME/.local/bin - | if ! which ops | grep $HOME/.local/bin - then + then echo "$HOME/.local/bin is not in the path - adding it" echo 'export PATH="$HOME/.local/bin:$PATH"' >>$HOME/.bashrc echo 'export PATH="$HOME/.local/bin:$PATH"' >>$HOME/.zshrc @@ -109,9 +118,8 @@ tasks: - go clean -testcache -cache - go test -count=1 {{.F}} github.com/apache/openserverless-cli - go test -count=1 {{.F}} github.com/apache/openserverless-cli/config - - go test -count=1 {{.F}} github.com/apache/openserverless-cli/tools + - go test -count=1 {{.F}} github.com/apache/openserverless-cli/tools - go test github.com/apache/openserverless-cli/auth - bats: dir: tests diff --git a/embedded.go b/embedded.go new file mode 100644 index 0000000..c2ce14f --- /dev/null +++ b/embedded.go @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package openserverless + +import ( + "embed" + "io/fs" + "os" + "path/filepath" +) + +//go:embed embedded-tasks +var embeddedTasks embed.FS + +// ExtractEmbeddedTasks extracts the embedded tasks to the specified directory. +// It returns the path to the extracted directory or an error. +func ExtractEmbeddedTasks() (string, error) { + opsHome, err := getOpsHome() + if err != nil { + return "", err + } + + targetDir := filepath.Join(opsHome, ".olaris") + + // Check if already exists + if _, err := os.Stat(targetDir); err == nil { + trace("Embedded tasks already extracted to", targetDir) + return targetDir, nil + } + + trace("Extracting embedded tasks to", targetDir) + + // Walk the embedded filesystem + err = fs.WalkDir(embeddedTasks, "embedded-tasks", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + // Calculate the relative path from the root of the embedded folder + relPath, err := filepath.Rel("embedded-tasks", path) + if err != nil { + return err + } + + // Target path + targetPath := filepath.Join(targetDir, relPath) + + if d.IsDir() { + trace("Creating directory", targetPath) + return os.MkdirAll(targetPath, 0755) + } + + // Read the file from embedded FS + data, err := embeddedTasks.ReadFile(path) + if err != nil { + return err + } + + trace("Writing file", targetPath) + return os.WriteFile(targetPath, data, 0644) + }) + + if err != nil { + return "", err + } + + return targetDir, nil +} + +func getOpsHome() (string, error) { + opsHome := os.Getenv("OPS_HOME") + if opsHome == "" { + // Use default + opsHome = os.ExpandEnv("$HOME/.ops") + } + return opsHome, nil +} diff --git a/main.go b/main.go index 50c1a3d..25d6712 100644 --- a/main.go +++ b/main.go @@ -373,20 +373,32 @@ func Main() { // Check if olaris exists. If not, download tasks olarisDir, err := getOpsRoot() if err != nil { - olarisDir := joinpath(joinpath(opsHome, getOpsBranch()), "olaris") - if !isDir(olarisDir) { - log.Println("Welcome to ops! Setting up...") - olarisDir, err = pullTasks(true, true) - if err != nil { - log.Fatalf("cannot locate or download OPS_ROOT: %s", err.Error()) - } - // if just updated, do not repeat - if len(os.Args) > 1 && os.Args[1] == "-update" { - os.Exit(0) + // Try to extract embedded tasks if available + trace("Tasks not found, attempting to extract embedded tasks...") + embeddedDir, extractErr := ExtractEmbeddedTasks() + if extractErr == nil { + trace("Embedded tasks extracted to", embeddedDir) + // Retry finding ops root, it should now find ~/.ops/.olaris + olarisDir, err = getOpsRoot() + } + + // If still not found or extraction failed, try downloading + if err != nil { + olarisDir = joinpath(joinpath(opsHome, getOpsBranch()), "olaris") + if !isDir(olarisDir) { + log.Println("Welcome to ops! Setting up...") + olarisDir, err = pullTasks(true, true) + if err != nil { + log.Fatalf("cannot locate or download OPS_ROOT: %s", err.Error()) + } + // if just updated, do not repeat + if len(os.Args) > 1 && os.Args[1] == "-update" { + os.Exit(0) + } + } else { + // check if olaris was recently updated + checkUpdated(opsHome, 24*time.Hour) } - } else { - // check if olaris was recently updated - checkUpdated(opsHome, 24*time.Hour) } } if err = setOpsOlarisHash(olarisDir); err != nil { diff --git a/prepare.go b/prepare.go index 489e74a..132abaa 100644 --- a/prepare.go +++ b/prepare.go @@ -191,6 +191,13 @@ func locateOpsRoot(cur string) (string, error) { return olaris, nil } + // is there an embedded olaris folder in ~/.ops/.olaris ? + embeddedOlarisDir, err := homedir.Expand("~/.ops/.olaris") + if err == nil && exists(embeddedOlarisDir, OPSFILE) && exists(embeddedOlarisDir, OPSROOT) { + trace("found embedded", embeddedOlarisDir, ":", olaris) + return embeddedOlarisDir, nil + } + return "", fmt.Errorf("cannot find opsfiles, download them with ops -update") }