From 8a3cdddd59f8ea14f696cb36ca0bf896c48baf7b Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 11:26:56 +0200 Subject: [PATCH 1/7] Upgrade go version; Upgrade golang.org/x/sys #98; --- .github/workflows/coverage.yml | 18 +- .github/workflows/lint.yml | 13 -- .github/workflows/pull-request-checks.yml | 22 +++ .github/workflows/release.yml | 6 +- .github/workflows/test.yml | 27 --- .gitignore | 3 + .golangci.yml | 12 ++ .goreleaser.yml | 82 ++++----- cmd/{taskctl => taskctl_cmd}/completion.go | 9 +- .../completion_test.go | 4 +- cmd/{taskctl => taskctl_cmd}/graph.go | 2 +- cmd/{taskctl => taskctl_cmd}/graph_test.go | 4 +- cmd/{taskctl => taskctl_cmd}/init.go | 4 +- cmd/{taskctl => taskctl_cmd}/init_test.go | 19 +-- cmd/{taskctl => taskctl_cmd}/list.go | 2 +- cmd/{taskctl => taskctl_cmd}/list_test.go | 4 +- cmd/{taskctl => taskctl_cmd}/run.go | 32 ++-- cmd/{taskctl => taskctl_cmd}/run_test.go | 24 +-- cmd/{taskctl => taskctl_cmd}/show.go | 2 +- cmd/{taskctl => taskctl_cmd}/show_test.go | 4 +- cmd/{taskctl => taskctl_cmd}/taskctl.go | 62 +++---- cmd/{taskctl => taskctl_cmd}/taskctl_test.go | 32 +--- .../testdata/graph.yaml | 0 .../testdata/task.yaml | 0 .../testdata/watch.yaml | 0 cmd/{taskctl => taskctl_cmd}/validate.go | 2 +- cmd/{taskctl => taskctl_cmd}/validate_test.go | 4 +- cmd/{taskctl => taskctl_cmd}/watch.go | 2 +- cmd/{taskctl => taskctl_cmd}/watch_test.go | 4 +- go.mod | 45 +++-- go.sum | 160 ++++++++---------- internal/config/config.go | 2 +- internal/config/config_test.go | 4 +- internal/config/loader.go | 8 +- internal/config/loader_test.go | 5 +- main.go | 19 +++ pkg/executor/executor_test.go | 4 +- pkg/runner/context_test.go | 4 +- pkg/runner/runner.go | 6 +- pkg/runner/runner_test.go | 4 +- 40 files changed, 317 insertions(+), 343 deletions(-) delete mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/pull-request-checks.yml delete mode 100644 .github/workflows/test.yml create mode 100644 .golangci.yml rename cmd/{taskctl => taskctl_cmd}/completion.go (96%) rename cmd/{taskctl => taskctl_cmd}/completion_test.go (90%) rename cmd/{taskctl => taskctl_cmd}/graph.go (98%) rename cmd/{taskctl => taskctl_cmd}/graph_test.go (92%) rename cmd/{taskctl => taskctl_cmd}/init.go (96%) rename cmd/{taskctl => taskctl_cmd}/init_test.go (65%) rename cmd/{taskctl => taskctl_cmd}/list.go (98%) rename cmd/{taskctl => taskctl_cmd}/list_test.go (93%) rename cmd/{taskctl => taskctl_cmd}/run.go (75%) rename cmd/{taskctl => taskctl_cmd}/run_test.go (61%) rename cmd/{taskctl => taskctl_cmd}/show.go (97%) rename cmd/{taskctl => taskctl_cmd}/show_test.go (89%) rename cmd/{taskctl => taskctl_cmd}/taskctl.go (92%) rename cmd/{taskctl => taskctl_cmd}/taskctl_test.go (81%) rename cmd/{taskctl => taskctl_cmd}/testdata/graph.yaml (100%) rename cmd/{taskctl => taskctl_cmd}/testdata/task.yaml (100%) rename cmd/{taskctl => taskctl_cmd}/testdata/watch.yaml (100%) rename cmd/{taskctl => taskctl_cmd}/validate.go (97%) rename cmd/{taskctl => taskctl_cmd}/validate_test.go (88%) rename cmd/{taskctl => taskctl_cmd}/watch.go (98%) rename cmd/{taskctl => taskctl_cmd}/watch_test.go (91%) create mode 100644 main.go diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 908dace5..57079d97 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -8,22 +8,14 @@ jobs: run: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - name: Set up Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v5 with: - go-version: 1.16.x - - - name: Check out code into the Go module directory - uses: actions/checkout@v1 + go-version-file: go.mod + cache-dependency-path: go.sum - - name: Cache Go modules - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + - name: Check out code into the Go module directory + uses: actions/checkout@v4 - name: Test with coverage report run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index e3bae9b5..00000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Lint -on: [push, pull_request] - -jobs: - golangci: - name: Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: golangci-lint - uses: golangci/golangci-lint-action@v2 - with: - version: v1.35 diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml new file mode 100644 index 00000000..a429f1ea --- /dev/null +++ b/.github/workflows/pull-request-checks.yml @@ -0,0 +1,22 @@ +name: Pull request checks +on: + pull_request: + types: [opened, synchronize] + +jobs: + build: + name: Test + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: Lint + uses: golangci/golangci-lint-action@v6 + - name: Test + run: | + go test -v -race ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ba830f9..4207961b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,10 +29,8 @@ jobs: password: ${{ secrets.DOCKER_HUB_PASSWORD }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v1 + uses: goreleaser/goreleaser-action@v6 with: - version: v0.149.0 - args: release --rm-dist + args: release --clean env: GITHUB_TOKEN: ${{secrets.GITHUB_TASKCTL_TOKEN}} - GOPATH: /home/runner/go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index d24400b0..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Test -on: [push, pull_request] -jobs: - build: - name: Test - runs-on: ubuntu-latest - steps: - - - name: Set up Go - uses: actions/setup-go@v1 - with: - go-version: 1.16.x - - - name: Check out code into the Go module directory - uses: actions/checkout@v1 - - - name: Cache Go modules - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Test - run: | - go test -v -race ./... diff --git a/.gitignore b/.gitignore index 79249ab0..f78dbd18 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ bin/ # IDEs .idea .vscode + +# Local +.envrc diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..1e09902c --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,12 @@ +# Options for analysis running. +run: + timeout: 10m + modules-download-mode: readonly + +severity: + default-severity: error + +linters-settings: + # Enable all analyzers. + # Default: false + enable-all: true diff --git a/.goreleaser.yml b/.goreleaser.yml index 06e1ad81..8d30a224 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,25 +1,30 @@ +version: 2 dist: bin builds: -- dir: cmd/taskctl - env: - - CGO_ENABLED=0 - goos: - - darwin - - linux - - windows - goarch: - - 386 - - amd64 - - arm - goarm: - - 6 - - 7 - ignore: - - goos: darwin - goarch: 386 - gcflags: - - all=-trimpath={{.Env.GOPATH}} + - binary: bin/taskctl + env: + - CGO_ENABLED=0 + goos: + - darwin + - linux + - windows + goarch: + - "386" + - amd64 + - arm + - arm64 + goarm: + - "6" + - "7" + goarm64: + - v8.0 + - v9.0 + ignore: + - goos: darwin + goarch: "386" + gcflags: + - all=-trimpath={{.Env.GOPATH}} archives: - format: tar.gz @@ -35,15 +40,15 @@ archives: source: enabled: true +changelog: + disable: true + release: prerelease: auto checksum: name_template: checksums.txt -changelog: - skip: true - snapcrafts: - name: taskctl confinement: classic @@ -54,37 +59,36 @@ snapcrafts: Simple modern alternative to GNU Make. *taskctl* is concurrent task runner that allows you to design you routine tasks and development pipelines in nice and neat way in human-readable format (YAML, JSON or TOML). Each pipeline composed of tasks or other pipelines and allows them to run in parallel or one-by-one. Beside pipelines, each single task can be performed manually or triggered by built-in filesystem watcher. - apps: - taskctl: - completer: autocomplete/bash_completion.bash brews: - - tap: - owner: taskctl - name: homebrew-taskctl - commit_author: + - commit_author: name: Yevhen Terentiev email: yevhen.terentiev@gmail.com homepage: https://github.com/taskctl/taskctl - install: | - bin.install "taskctl" + extra_install: | bash_completion.install "autocomplete/bash_completion.bash" zsh_completion.install "autocomplete/zsh_completion.zsh" + repository: + owner: taskctl + name: homebrew-taskctl + dockers: - image_templates: - "docker.io/taskctl/taskctl:latest" + - "ghcr.io/taskctl/taskctl:latest" - "docker.io/taskctl/taskctl:{{ .Tag }}" + - "ghcr.io/taskctl/taskctl:{{ .Tag }}" skip_push: auto -scoop: - bucket: - owner: taskctl - name: scoop-taskctl - commit_author: - name: Yevhen Terentiev - email: yevhen.terentiev@gmail.com - homepage: https://github.com/taskctl/taskctl +scoops: + - repository: + owner: taskctl + name: scoop-taskctl + commit_author: + name: Yevhen Terentiev + email: yevhen.terentiev@gmail.com + homepage: https://github.com/taskctl/taskctl nfpms: - diff --git a/cmd/taskctl/completion.go b/cmd/taskctl_cmd/completion.go similarity index 96% rename from cmd/taskctl/completion.go rename to cmd/taskctl_cmd/completion.go index 33fd0d1b..a7f8b315 100644 --- a/cmd/taskctl/completion.go +++ b/cmd/taskctl_cmd/completion.go @@ -1,11 +1,10 @@ -package main +package taskctl_cmd import ( "fmt" - "io/ioutil" - "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" + "io" ) func newCompletionCommand() *cli.Command { @@ -15,7 +14,7 @@ func newCompletionCommand() *cli.Command { UsageText: helpText, Action: func(c *cli.Context) error { logrus.SetLevel(logrus.PanicLevel) - logrus.SetOutput(ioutil.Discard) + logrus.SetOutput(io.Discard) var shell string if !c.Args().Present() { @@ -41,7 +40,7 @@ func newCompletionCommand() *cli.Command { } var helpText = ` -To load completion run +To load completion Run . <(taskctl completion) diff --git a/cmd/taskctl/completion_test.go b/cmd/taskctl_cmd/completion_test.go similarity index 90% rename from cmd/taskctl/completion_test.go rename to cmd/taskctl_cmd/completion_test.go index 0db4b081..3e4c0866 100644 --- a/cmd/taskctl/completion_test.go +++ b/cmd/taskctl_cmd/completion_test.go @@ -1,9 +1,9 @@ -package main +package taskctl_cmd import "testing" func Test_completionCommand(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() tests := []appTest{ {args: []string{"", "completion"}}, diff --git a/cmd/taskctl/graph.go b/cmd/taskctl_cmd/graph.go similarity index 98% rename from cmd/taskctl/graph.go rename to cmd/taskctl_cmd/graph.go index 68a4a5d5..91faa544 100644 --- a/cmd/taskctl/graph.go +++ b/cmd/taskctl_cmd/graph.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "errors" diff --git a/cmd/taskctl/graph_test.go b/cmd/taskctl_cmd/graph_test.go similarity index 92% rename from cmd/taskctl/graph_test.go rename to cmd/taskctl_cmd/graph_test.go index 91d6b2e5..c0f865f1 100644 --- a/cmd/taskctl/graph_test.go +++ b/cmd/taskctl_cmd/graph_test.go @@ -1,11 +1,11 @@ -package main +package taskctl_cmd import ( "testing" ) func Test_graphCommand(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() tests := []appTest{ { diff --git a/cmd/taskctl/init.go b/cmd/taskctl_cmd/init.go similarity index 96% rename from cmd/taskctl/init.go rename to cmd/taskctl_cmd/init.go index bd205041..f2452982 100644 --- a/cmd/taskctl/init.go +++ b/cmd/taskctl_cmd/init.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "errors" @@ -102,7 +102,7 @@ func newInitCommand() *cli.Command { } fmt.Println(aurora.Sprintf(aurora.Magenta("%s was created. Edit it accordingly to your needs"), aurora.Green(filename))) - fmt.Println(aurora.Cyan("To run example pipeline - taskctl run pipeline1")) + fmt.Println(aurora.Cyan("To Run example pipeline - taskctl Run pipeline1")) return nil }, diff --git a/cmd/taskctl/init_test.go b/cmd/taskctl_cmd/init_test.go similarity index 65% rename from cmd/taskctl/init_test.go rename to cmd/taskctl_cmd/init_test.go index d4e76540..ebef08f0 100644 --- a/cmd/taskctl/init_test.go +++ b/cmd/taskctl_cmd/init_test.go @@ -1,7 +1,6 @@ -package main +package taskctl_cmd import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -10,13 +9,13 @@ import ( func Test_initCommand(t *testing.T) { confirm := stdinConfirm(t, 1) defer func(f os.File) { - confirm.Close() - os.Remove(f.Name()) + _ = confirm.Close() + _ = os.Remove(f.Name()) }(*confirm) - app := makeTestApp(t) + app := makeTestApp() dir := os.TempDir() - os.Remove(filepath.Join(dir, "taskctl.yaml")) + _ = os.Remove(filepath.Join(dir, "taskctl.yaml")) runAppTest(app, appTest{args: []string{"", "init", "--dir", dir}, stdin: confirm}, t) } @@ -24,13 +23,13 @@ func Test_initCommand(t *testing.T) { func TestInitCommand_Overwrite(t *testing.T) { confirm := stdinConfirm(t, 2) defer func(f os.File) { - confirm.Close() - os.Remove(f.Name()) + _ = confirm.Close() + _ = os.Remove(f.Name()) }(*confirm) - app := makeTestApp(t) + app := makeTestApp() dir := os.TempDir() - err := ioutil.WriteFile(filepath.Join(dir, "taskctl.yaml"), []byte("here"), 0764) + err := os.WriteFile(filepath.Join(dir, "taskctl.yaml"), []byte("here"), 0764) if err != nil { t.Fatal(err) } diff --git a/cmd/taskctl/list.go b/cmd/taskctl_cmd/list.go similarity index 98% rename from cmd/taskctl/list.go rename to cmd/taskctl_cmd/list.go index 3b5ba633..a5dbaa52 100644 --- a/cmd/taskctl/list.go +++ b/cmd/taskctl_cmd/list.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "fmt" diff --git a/cmd/taskctl/list_test.go b/cmd/taskctl_cmd/list_test.go similarity index 93% rename from cmd/taskctl/list_test.go rename to cmd/taskctl_cmd/list_test.go index 954e2fc8..e816d020 100644 --- a/cmd/taskctl/list_test.go +++ b/cmd/taskctl_cmd/list_test.go @@ -1,9 +1,9 @@ -package main +package taskctl_cmd import "testing" func Test_listCommand(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() tests := []appTest{ {args: []string{"", "-c", "testdata/graph.yaml", "list"}, output: []string{"graph:pipeline1", "graph:task1", "no watchers"}}, diff --git a/cmd/taskctl/run.go b/cmd/taskctl_cmd/run.go similarity index 75% rename from cmd/taskctl/run.go rename to cmd/taskctl_cmd/run.go index 318fbb37..6042da32 100644 --- a/cmd/taskctl/run.go +++ b/cmd/taskctl_cmd/run.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "fmt" @@ -18,16 +18,16 @@ import ( func newRunCommand() *cli.Command { var taskRunner *runner.TaskRunner cmd := &cli.Command{ - Name: "run", - ArgsUsage: "run (PIPELINE1 OR TASK1) [PIPELINE2 OR TASK2]... [flags] [-- TASKS_ARGS]", + Name: "Run", + ArgsUsage: "Run (PIPELINE1 OR TASK1) [PIPELINE2 OR TASK2]... [flags] [-- TASKS_ARGS]", Usage: "runs pipeline or task", - UsageText: "taskctl run pipeline1\n" + + UsageText: "taskctl Run pipeline1\n" + "taskctl pipeline1\n" + "taskctl task1", Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "dry-run", - Usage: "dry run", + Name: "dry-Run", + Usage: "dry Run", }, &cli.BoolFlag{ Name: "summary", @@ -68,7 +68,7 @@ func newRunCommand() *cli.Command { { Name: "task", ArgsUsage: "task (TASK1) [TASK2]... [flags] [-- TASK_ARGS]", - Usage: "run specified task(s)", + Usage: "Run specified task(s)", Action: func(c *cli.Context) error { for _, v := range c.Args().Slice() { if v == "--" { @@ -129,7 +129,7 @@ func runPipeline(g *scheduler.ExecutionGraph, taskRunner *runner.TaskRunner, sum } sd.Finish() - fmt.Fprint(os.Stdout, "\r\n") + _, _ = fmt.Fprint(os.Stdout, "\r\n") if summary { printSummary(g) @@ -175,27 +175,27 @@ func printSummary(g *scheduler.ExecutionGraph) { return stages[j].Start.Nanosecond() > stages[i].Start.Nanosecond() }) - fmt.Fprintln(os.Stdout, aurora.Bold("Summary:").String()) + _, _ = fmt.Fprintln(os.Stdout, aurora.Bold("Summary:").String()) var log string for _, stage := range stages { switch stage.ReadStatus() { case scheduler.StatusDone: - fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Green("- Stage %s was completed in %s"), stage.Name, stage.Duration())) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Green("- Stage %s was completed in %s"), stage.Name, stage.Duration())) case scheduler.StatusSkipped: - fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Green("- Stage %s was skipped"), stage.Name)) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Green("- Stage %s was skipped"), stage.Name)) case scheduler.StatusError: log = strings.TrimSpace(stage.Task.ErrorMessage()) - fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Red("- Stage %s failed in %s"), stage.Name, stage.Duration())) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Red("- Stage %s failed in %s"), stage.Name, stage.Duration())) if log != "" { - fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Red(" > %s"), log)) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Red(" > %s"), log)) } case scheduler.StatusCanceled: - fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Gray(12, "- Stage %s was cancelled"), stage.Name)) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Gray(12, "- Stage %s was cancelled"), stage.Name)) default: - fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Red("- Unexpected status %d for stage %s"), stage.Status, stage.Name)) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf(aurora.Red("- Unexpected status %d for stage %s"), stage.Status, stage.Name)) } } - fmt.Fprintln(os.Stdout, aurora.Sprintf("%s: %s", aurora.Bold("Total duration"), aurora.Green(g.Duration()))) + _, _ = fmt.Fprintln(os.Stdout, aurora.Sprintf("%s: %s", aurora.Bold("Total duration"), aurora.Green(g.Duration()))) } diff --git a/cmd/taskctl/run_test.go b/cmd/taskctl_cmd/run_test.go similarity index 61% rename from cmd/taskctl/run_test.go rename to cmd/taskctl_cmd/run_test.go index d7c33211..22a1f001 100644 --- a/cmd/taskctl/run_test.go +++ b/cmd/taskctl_cmd/run_test.go @@ -1,35 +1,35 @@ -package main +package taskctl_cmd import "testing" func Test_runCommand(t *testing.T) { tests := []appTest{ - {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "run", "graph:task2"}, errored: true}, - {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "run"}, errored: true}, - {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "run", "graph:task1"}, exactOutput: "hello, world!\n"}, - {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "run", "task", "graph:task1"}, exactOutput: "hello, world!\n"}, - {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "run", "pipeline", "graph:pipeline1"}, output: []string{"graph:task3", "hello, world!\n"}}, + {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "Run", "graph:task2"}, errored: true}, + {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "Run"}, errored: true}, + {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "Run", "graph:task1"}, exactOutput: "hello, world!\n"}, + {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "Run", "task", "graph:task1"}, exactOutput: "hello, world!\n"}, + {args: []string{"", "--raw", "-c", "testdata/graph.yaml", "Run", "pipeline", "graph:pipeline1"}, output: []string{"graph:task3", "hello, world!\n"}}, { - args: []string{"", "--output=prefixed", "-c", "testdata/graph.yaml", "run", "graph:pipeline1"}, + args: []string{"", "--output=prefixed", "-c", "testdata/graph.yaml", "Run", "graph:pipeline1"}, output: []string{"graph:task1", "graph:task2", "graph:task3", "hello, world!"}, }, } for _, v := range tests { - app := makeTestApp(t) + app := makeTestApp() runAppTest(app, v, t) } } func Test_runCommandWithArgumentsList(t *testing.T) { tests := []appTest{ - {args: []string{"", "--raw", "-c", "testdata/task.yaml", "run", "task", "task:task1", "--", "first", "second"}, exactOutput: "This is first argument\n"}, - {args: []string{"", "--raw", "-c", "testdata/task.yaml", "run", "task", "task:task2", "--", "first", "second"}, exactOutput: "This is second argument\n"}, - {args: []string{"", "--raw", "-c", "testdata/task.yaml", "run", "task", "task:task3", "--", "first", "and", "second"}, exactOutput: "This is first and second arguments\n"}, + {args: []string{"", "--raw", "-c", "testdata/task.yaml", "Run", "task", "task:task1", "--", "first", "second"}, exactOutput: "This is first argument\n"}, + {args: []string{"", "--raw", "-c", "testdata/task.yaml", "Run", "task", "task:task2", "--", "first", "second"}, exactOutput: "This is second argument\n"}, + {args: []string{"", "--raw", "-c", "testdata/task.yaml", "Run", "task", "task:task3", "--", "first", "and", "second"}, exactOutput: "This is first and second arguments\n"}, } for _, v := range tests { - app := makeTestApp(t) + app := makeTestApp() runAppTest(app, v, t) } } diff --git a/cmd/taskctl/show.go b/cmd/taskctl_cmd/show.go similarity index 97% rename from cmd/taskctl/show.go rename to cmd/taskctl_cmd/show.go index b13108ee..5d53e461 100644 --- a/cmd/taskctl/show.go +++ b/cmd/taskctl_cmd/show.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "errors" diff --git a/cmd/taskctl/show_test.go b/cmd/taskctl_cmd/show_test.go similarity index 89% rename from cmd/taskctl/show_test.go rename to cmd/taskctl_cmd/show_test.go index 1900fc58..161f5a0c 100644 --- a/cmd/taskctl/show_test.go +++ b/cmd/taskctl_cmd/show_test.go @@ -1,9 +1,9 @@ -package main +package taskctl_cmd import "testing" func Test_showCommand(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() tests := []appTest{ {args: []string{"", "-c", "testdata/graph.yaml", "show"}, errored: true}, diff --git a/cmd/taskctl/taskctl.go b/cmd/taskctl_cmd/taskctl.go similarity index 92% rename from cmd/taskctl/taskctl.go rename to cmd/taskctl_cmd/taskctl.go index 4f99168d..0a75089b 100644 --- a/cmd/taskctl/taskctl.go +++ b/cmd/taskctl_cmd/taskctl.go @@ -1,18 +1,16 @@ -package main +package taskctl_cmd import ( "errors" "fmt" + "github.com/taskctl/taskctl/pkg/runner" "io" - "io/ioutil" "os" "os/signal" "sort" "strings" "syscall" - "github.com/taskctl/taskctl/pkg/runner" - "github.com/logrusorgru/aurora" "github.com/manifoldco/promptui" @@ -25,47 +23,20 @@ import ( ) var version = "dev" - var stdin io.ReadCloser - var cancel = make(chan struct{}) - var cfg *config.Config -func main() { - logrus.SetFormatter(&logrus.TextFormatter{ - DisableColors: false, - TimestampFormat: "2006-01-02 15:04:05", - FullTimestamp: false, - }) - - err := run() - if err != nil { - logrus.Fatal(err) - } -} - -func listenSignals() { - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - go func() { - for sig := range sigs { - abort() - os.Exit(int(sig.(syscall.Signal))) - } - }() -} - -func run() error { +func Run() error { stdin = os.Stdin - app := makeApp() + app := NewApp() listenSignals() return app.Run(os.Args) } -func makeApp() *cli.App { +func NewApp() *cli.App { cfg = config.NewConfig() cl := config.NewConfigLoader(cfg) @@ -124,8 +95,8 @@ func makeApp() *cli.App { Usage: "set global variable value", }, &cli.BoolFlag{ - Name: "dry-run", - Usage: "dry run", + Name: "dry-Run", + Usage: "dry Run", }, &cli.BoolFlag{ Name: "summary", @@ -169,7 +140,7 @@ func makeApp() *cli.App { } } - if c.Bool("dry-run") { + if c.Bool("dry-Run") { cfg.DryRun = true } @@ -195,6 +166,17 @@ func makeApp() *cli.App { } } +func listenSignals() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + go func() { + for sig := range sigs { + abort() + os.Exit(int(sig.(syscall.Signal))) + } + }() +} + func rootAction(c *cli.Context) (err error) { taskRunner, err := buildTaskRunner(c) if err != nil { @@ -218,7 +200,7 @@ func rootAction(c *cli.Context) (err error) { suggestions := buildSuggestions(cfg) targetSelect := promptui.Select{ - Label: "Select task to run", + Label: "Select task to Run", Items: suggestions, Size: 15, CursorPos: 0, @@ -269,8 +251,8 @@ func buildTaskRunner(c *cli.Context) (*runner.TaskRunner, error) { taskRunner.DryRun = cfg.DryRun if cfg.Quiet { - taskRunner.Stdout = ioutil.Discard - taskRunner.Stderr = ioutil.Discard + taskRunner.Stdout = io.Discard + taskRunner.Stderr = io.Discard } go func() { diff --git a/cmd/taskctl/taskctl_test.go b/cmd/taskctl_cmd/taskctl_test.go similarity index 81% rename from cmd/taskctl/taskctl_test.go rename to cmd/taskctl_cmd/taskctl_test.go index 7be58e82..407d8a13 100644 --- a/cmd/taskctl/taskctl_test.go +++ b/cmd/taskctl_cmd/taskctl_test.go @@ -1,12 +1,10 @@ -package main +package taskctl_cmd import ( "bytes" "encoding/binary" "io" - "io/ioutil" "os" - "reflect" "strings" "testing" @@ -22,8 +20,8 @@ type appTest struct { stdin io.ReadCloser } -func makeTestApp(t *testing.T) *cli.App { - return makeApp() +func makeTestApp() *cli.App { + return NewApp() } func runAppTest(app *cli.App, test appTest, t *testing.T) { @@ -48,7 +46,7 @@ func runAppTest(app *cli.App, test appTest, t *testing.T) { err = app.Run(test.args) os.Stdout = origStdout - w.Close() + _ = w.Close() if err != nil && !test.errored { t.Fatal(err) @@ -77,7 +75,7 @@ func runAppTest(app *cli.App, test appTest, t *testing.T) { } func stdinConfirm(t *testing.T, times int) *os.File { - tmpfile, err := ioutil.TempFile("", "confirm") + tmpfile, err := os.CreateTemp("", "confirm") if err != nil { t.Fatal(err) } @@ -97,7 +95,7 @@ func stdinConfirm(t *testing.T, times int) *os.File { } func TestBashComplete(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() runAppTest(app, appTest{ args: []string{"", "-c", "testdata/graph.yaml", "--generate-bash-completion"}, output: []string{"graph\\:task1", "graph\\:pipeline1"}, @@ -117,23 +115,7 @@ func TestRootAction(t *testing.T) { } for _, v := range tests { - app := makeTestApp(t) + app := makeTestApp() runAppTest(app, v, t) } } - -func Test_makeApp(t *testing.T) { - tests := []struct { - name string - want *cli.App - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := makeApp(); !reflect.DeepEqual(got, tt.want) { - t.Errorf("makeApp() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/cmd/taskctl/testdata/graph.yaml b/cmd/taskctl_cmd/testdata/graph.yaml similarity index 100% rename from cmd/taskctl/testdata/graph.yaml rename to cmd/taskctl_cmd/testdata/graph.yaml diff --git a/cmd/taskctl/testdata/task.yaml b/cmd/taskctl_cmd/testdata/task.yaml similarity index 100% rename from cmd/taskctl/testdata/task.yaml rename to cmd/taskctl_cmd/testdata/task.yaml diff --git a/cmd/taskctl/testdata/watch.yaml b/cmd/taskctl_cmd/testdata/watch.yaml similarity index 100% rename from cmd/taskctl/testdata/watch.yaml rename to cmd/taskctl_cmd/testdata/watch.yaml diff --git a/cmd/taskctl/validate.go b/cmd/taskctl_cmd/validate.go similarity index 97% rename from cmd/taskctl/validate.go rename to cmd/taskctl_cmd/validate.go index c12add4e..5c6db0be 100644 --- a/cmd/taskctl/validate.go +++ b/cmd/taskctl_cmd/validate.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "fmt" diff --git a/cmd/taskctl/validate_test.go b/cmd/taskctl_cmd/validate_test.go similarity index 88% rename from cmd/taskctl/validate_test.go rename to cmd/taskctl_cmd/validate_test.go index 42a590b6..2358463f 100644 --- a/cmd/taskctl/validate_test.go +++ b/cmd/taskctl_cmd/validate_test.go @@ -1,9 +1,9 @@ -package main +package taskctl_cmd import "testing" func Test_validateCommand(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() tests := []appTest{ {args: []string{"", "validate", "testdata/graph2.yaml"}, errored: true}, diff --git a/cmd/taskctl/watch.go b/cmd/taskctl_cmd/watch.go similarity index 98% rename from cmd/taskctl/watch.go rename to cmd/taskctl_cmd/watch.go index df3aeeb3..995e57a4 100644 --- a/cmd/taskctl/watch.go +++ b/cmd/taskctl_cmd/watch.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "fmt" diff --git a/cmd/taskctl/watch_test.go b/cmd/taskctl_cmd/watch_test.go similarity index 91% rename from cmd/taskctl/watch_test.go rename to cmd/taskctl_cmd/watch_test.go index 0ad6e794..38811dbc 100644 --- a/cmd/taskctl/watch_test.go +++ b/cmd/taskctl_cmd/watch_test.go @@ -1,4 +1,4 @@ -package main +package taskctl_cmd import ( "testing" @@ -6,7 +6,7 @@ import ( ) func Test_watchCommand(t *testing.T) { - app := makeTestApp(t) + app := makeTestApp() listenSignals() tests := []appTest{ diff --git a/go.mod b/go.mod index 23bec4e8..cfebafb4 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,34 @@ module github.com/taskctl/taskctl -go 1.16 +go 1.23 require ( - github.com/bmatcuk/doublestar v1.1.5 - github.com/briandowns/spinner v0.0.0-20200215035459-6dc224009eae - github.com/emicklei/dot v0.10.2 - github.com/fsnotify/fsnotify v1.4.9 - github.com/imdario/mergo v0.3.8 - github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 - github.com/manifoldco/promptui v0.7.0 - github.com/mattn/go-colorable v0.1.4 // indirect - github.com/mattn/go-isatty v0.0.10 // indirect - github.com/mitchellh/mapstructure v1.1.2 - github.com/pelletier/go-toml v1.8.0 - github.com/sirupsen/logrus v1.4.2 - github.com/urfave/cli/v2 v2.2.0 - gopkg.in/yaml.v2 v2.3.0 - mvdan.cc/sh/v3 v3.1.1 + dario.cat/mergo v1.0.1 + github.com/bmatcuk/doublestar v1.3.4 + github.com/briandowns/spinner v1.23.1 + github.com/emicklei/dot v1.6.4 + github.com/fsnotify/fsnotify v1.8.0 + github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/manifoldco/promptui v0.9.0 + github.com/mitchellh/mapstructure v1.5.0 + github.com/pelletier/go-toml v1.9.5 + github.com/sirupsen/logrus v1.9.3 + github.com/urfave/cli/v2 v2.27.5 + golang.org/x/text v0.21.0 + gopkg.in/yaml.v2 v2.4.0 + mvdan.cc/sh/v3 v3.10.0 +) + +require ( + github.com/chzyer/readline v1.5.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect ) diff --git a/go.sum b/go.sum index 3948b629..4400eed8 100644 --- a/go.sum +++ b/go.sum @@ -1,100 +1,86 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk= -github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= -github.com/briandowns/spinner v0.0.0-20200215035459-6dc224009eae h1:Y2F1NVjb2DaCFo+4SrBcjM1bjahSFC7xMMUbIJPbQRc= -github.com/briandowns/spinner v0.0.0-20200215035459-6dc224009eae/go.mod h1://Zf9tMcxfRUA36V23M6YGEAv+kECGfvpnLTnb8n4XQ= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650= +github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= +github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/dot v0.10.2 h1:vDUudhCSkKr1G3kieHqm3CiP7AsvaM25qk+46kb1i5Q= -github.com/emicklei/dot v0.10.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/emicklei/dot v1.6.4 h1:cG9ycT67d9Yw22G+mAb4XiuUz6E6H1S0zePp/5Cwe/c= +github.com/emicklei/dot v1.6.4/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 h1:im9kkmH0WWwxzegiv18gSUJbuXR9y028rXrWuPp6Jug= -github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4= -github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= -github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= -github.com/pkg/diff v0.0.0-20190930165518-531926345625/go.mod h1:kFj35MyHn14a6pIgWhm46KVjJr5CHys3eEYxkuKD1EI= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407 h1:5zh5atpUEdIc478E/ebrIaHLKcfVvG6dL/fGv7BcMoM= -golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8= -mvdan.cc/sh/v3 v3.1.1 h1:niuYC5Ug0KzLuN6CNX3ru37v4MkVD5Wm9T4Mk2eJr9A= -mvdan.cc/sh/v3 v3.1.1/go.mod h1:F+Vm4ZxPJxDKExMLhvjuI50oPnedVXpfjNSrusiTOno= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= +mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY= diff --git a/internal/config/config.go b/internal/config/config.go index f5478b6b..587dac8c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -6,7 +6,7 @@ import ( "github.com/taskctl/taskctl/pkg/variables" - "github.com/imdario/mergo" + "dario.cat/mergo" "github.com/sirupsen/logrus" "github.com/taskctl/taskctl/internal/watch" diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 8c947b82..7316b6f1 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -2,7 +2,7 @@ package config import ( "bytes" - "io/ioutil" + "os" "testing" "github.com/taskctl/taskctl/pkg/task" @@ -10,7 +10,7 @@ import ( "gopkg.in/yaml.v2" ) -var testConfig, _ = ioutil.ReadFile("testdata/tasks.yaml") +var testConfig, _ = os.ReadFile("testdata/tasks.yaml") func TestConfig_decode(t *testing.T) { loader := NewConfigLoader(NewConfig()) diff --git a/internal/config/loader.go b/internal/config/loader.go index e2a84155..8797537e 100644 --- a/internal/config/loader.go +++ b/internal/config/loader.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "mime" "net/http" "net/url" @@ -14,7 +14,7 @@ import ( "path/filepath" "strings" - "github.com/imdario/mergo" + "dario.cat/mergo" "github.com/mitchellh/mapstructure" "github.com/pelletier/go-toml" "github.com/sirupsen/logrus" @@ -227,7 +227,7 @@ func (cl *Loader) readURL(u string) (map[string]interface{}, error) { return nil, fmt.Errorf("%d: config request failed - %s", resp.StatusCode, u) } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("%s: %v", u, err) } @@ -256,7 +256,7 @@ func (cl *Loader) readURL(u string) (map[string]interface{}, error) { } func (cl *Loader) readFile(filename string) (map[string]interface{}, error) { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { return nil, fmt.Errorf("%s: %v", filename, err) } diff --git a/internal/config/loader_test.go b/internal/config/loader_test.go index ccc332ca..9420a305 100644 --- a/internal/config/loader_test.go +++ b/internal/config/loader_test.go @@ -2,7 +2,6 @@ package config import ( "fmt" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -105,7 +104,7 @@ func TestLoader_readURL(t *testing.T) { if r == 2 { writer.WriteHeader(500) } - fmt.Fprintln(writer, sampleCfg) + _, _ = fmt.Fprintln(writer, sampleCfg) r++ })) @@ -139,7 +138,7 @@ func TestLoader_LoadGlobalConfig(t *testing.T) { t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(h, ".taskctl", "config.yaml"), []byte(sampleCfg), 0644) + err = os.WriteFile(filepath.Join(h, ".taskctl", "config.yaml"), []byte(sampleCfg), 0644) if err != nil { t.Fatal(err) } diff --git a/main.go b/main.go new file mode 100644 index 00000000..9ca34dd6 --- /dev/null +++ b/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/sirupsen/logrus" + "github.com/taskctl/taskctl/cmd/taskctl_cmd" +) + +func main() { + logrus.SetFormatter(&logrus.TextFormatter{ + DisableColors: false, + TimestampFormat: "2006-01-02 15:04:05", + FullTimestamp: false, + }) + + err := taskctl_cmd.Run() + if err != nil { + logrus.Fatal(err) + } +} diff --git a/pkg/executor/executor_test.go b/pkg/executor/executor_test.go index e8c02348..a4a7501e 100644 --- a/pkg/executor/executor_test.go +++ b/pkg/executor/executor_test.go @@ -3,13 +3,13 @@ package executor import ( "bytes" "context" - "io/ioutil" + "io" "testing" "time" ) func TestDefaultExecutor_Execute(t *testing.T) { - e, err := NewDefaultExecutor(nil, ioutil.Discard, ioutil.Discard) + e, err := NewDefaultExecutor(nil, io.Discard, io.Discard) if err != nil { t.Fatal(err) } diff --git a/pkg/runner/context_test.go b/pkg/runner/context_test.go index a0ff74ca..4d985322 100644 --- a/pkg/runner/context_test.go +++ b/pkg/runner/context_test.go @@ -1,7 +1,7 @@ package runner import ( - "io/ioutil" + "io" "testing" "github.com/sirupsen/logrus" @@ -11,7 +11,7 @@ import ( ) func TestContext(t *testing.T) { - logrus.SetOutput(ioutil.Discard) + logrus.SetOutput(io.Discard) c1 := NewExecutionContext(nil, "/", variables.NewVariables(), []string{"true"}, []string{"false"}, []string{"true"}, []string{"false"}) c2 := NewExecutionContext(nil, "/", variables.NewVariables(), []string{"false"}, []string{"false"}, []string{"false"}, []string{"false"}) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index dc590ba7..4bc7856d 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -3,6 +3,7 @@ package runner import ( "context" "fmt" + "golang.org/x/text/language" "io" "os" "regexp" @@ -11,6 +12,7 @@ import ( "time" "github.com/taskctl/taskctl/pkg/executor" + "golang.org/x/text/cases" "github.com/taskctl/taskctl/pkg/variables" @@ -21,6 +23,8 @@ import ( "github.com/taskctl/taskctl/pkg/task" ) +var caser = cases.Title(language.English) + // Runner describes tasks runner interface type Runner interface { Run(t *task.Task) error @@ -328,7 +332,7 @@ func (r *TaskRunner) checkTaskCondition(t *task.Task) (bool, error) { func (r *TaskRunner) storeTaskOutput(t *task.Task) { var envVarName string - varName := fmt.Sprintf("Tasks.%s.Output", strings.Title(t.Name)) + varName := fmt.Sprintf("Tasks.%s.Output", caser.String(t.Name)) if t.ExportAs == "" { envVarName = fmt.Sprintf("%s_OUTPUT", strings.ToUpper(t.Name)) diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 45102ea6..236426c4 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -2,7 +2,7 @@ package runner import ( "fmt" - "io/ioutil" + "io" "strings" "testing" "time" @@ -27,7 +27,7 @@ func TestTaskRunner(t *testing.T) { t.Error() } - runner.Stdout, runner.Stderr = ioutil.Discard, ioutil.Discard + runner.Stdout, runner.Stderr = io.Discard, io.Discard runner.SetVariables(variables.FromMap(map[string]string{"Root": "/tmp"})) runner.WithVariable("Root", "/") From d4f8262c5d68464c63274ba931d6b8d3feecb448 Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 11:34:42 +0200 Subject: [PATCH 2/7] Fix "Specifying imports without any items throws unfriendly error #96" --- internal/config/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/loader.go b/internal/config/loader.go index 8797537e..563aafb0 100644 --- a/internal/config/loader.go +++ b/internal/config/loader.go @@ -151,7 +151,7 @@ func (cl *Loader) load(file string) (config map[string]interface{}, err error) { var raw map[string]interface{} importDir := path.Dir(file) - if imports, ok := config["import"]; ok { + if imports, ok := config["import"]; ok && imports != nil { for _, v := range imports.([]interface{}) { if utils.IsURL(v.(string)) { if cl.imports[v.(string)] { From c685eeecd608c82fed4d8d68b4a1cfb908a07219 Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 12:18:22 +0200 Subject: [PATCH 3/7] Replace logrus with slog; Improve cmd structure; --- cmd/{taskctl_cmd/taskctl.go => cmd.go} | 10 ++++----- .../taskctl_test.go => cmd_test.go} | 2 +- cmd/{taskctl_cmd => }/completion.go | 8 +++---- cmd/{taskctl_cmd => }/completion_test.go | 2 +- cmd/{taskctl_cmd => }/graph.go | 6 ++--- cmd/{taskctl_cmd => }/graph_test.go | 2 +- cmd/{taskctl_cmd => }/init.go | 2 +- cmd/{taskctl_cmd => }/init_test.go | 2 +- cmd/{taskctl_cmd => }/list.go | 2 +- cmd/{taskctl_cmd => }/list_test.go | 2 +- cmd/{taskctl_cmd => }/run.go | 2 +- cmd/{taskctl_cmd => }/run_test.go | 2 +- cmd/{taskctl_cmd => }/show.go | 2 +- cmd/{taskctl_cmd => }/show_test.go | 2 +- cmd/{taskctl_cmd => }/testdata/graph.yaml | 0 cmd/{taskctl_cmd => }/testdata/task.yaml | 0 cmd/{taskctl_cmd => }/testdata/watch.yaml | 0 cmd/{taskctl_cmd => }/validate.go | 2 +- cmd/{taskctl_cmd => }/validate_test.go | 2 +- cmd/{taskctl_cmd => }/watch.go | 7 +++--- cmd/{taskctl_cmd => }/watch_test.go | 2 +- go.mod | 1 - go.sum | 12 ---------- internal/config/config.go | 5 ++--- internal/config/loader.go | 6 ++--- internal/watch/watch.go | 22 +++++++++---------- main.go | 16 +++++--------- pkg/executor/executor.go | 6 ++--- pkg/output/output_test.go | 8 +++---- pkg/output/prefixed.go | 9 ++++---- pkg/output/prefixed_test.go | 6 ++--- pkg/runner/context.go | 12 +++++----- pkg/runner/context_test.go | 5 ++--- pkg/runner/runner.go | 15 ++++++------- pkg/scheduler/scheduler.go | 10 +++++---- 35 files changed, 85 insertions(+), 107 deletions(-) rename cmd/{taskctl_cmd/taskctl.go => cmd.go} (97%) rename cmd/{taskctl_cmd/taskctl_test.go => cmd_test.go} (99%) rename cmd/{taskctl_cmd => }/completion.go (94%) rename cmd/{taskctl_cmd => }/completion_test.go (95%) rename cmd/{taskctl_cmd => }/graph.go (95%) rename cmd/{taskctl_cmd => }/graph_test.go (96%) rename cmd/{taskctl_cmd => }/init.go (99%) rename cmd/{taskctl_cmd => }/init_test.go (97%) rename cmd/{taskctl_cmd => }/list.go (98%) rename cmd/{taskctl_cmd => }/list_test.go (96%) rename cmd/{taskctl_cmd => }/run.go (99%) rename cmd/{taskctl_cmd => }/run_test.go (98%) rename cmd/{taskctl_cmd => }/show.go (97%) rename cmd/{taskctl_cmd => }/show_test.go (94%) rename cmd/{taskctl_cmd => }/testdata/graph.yaml (100%) rename cmd/{taskctl_cmd => }/testdata/task.yaml (100%) rename cmd/{taskctl_cmd => }/testdata/watch.yaml (100%) rename cmd/{taskctl_cmd => }/validate.go (97%) rename cmd/{taskctl_cmd => }/validate_test.go (94%) rename cmd/{taskctl_cmd => }/watch.go (93%) rename cmd/{taskctl_cmd => }/watch_test.go (95%) diff --git a/cmd/taskctl_cmd/taskctl.go b/cmd/cmd.go similarity index 97% rename from cmd/taskctl_cmd/taskctl.go rename to cmd/cmd.go index 0a75089b..1e49b260 100644 --- a/cmd/taskctl_cmd/taskctl.go +++ b/cmd/cmd.go @@ -1,10 +1,11 @@ -package taskctl_cmd +package cmd import ( "errors" "fmt" "github.com/taskctl/taskctl/pkg/runner" "io" + "log/slog" "os" "os/signal" "sort" @@ -14,7 +15,6 @@ import ( "github.com/logrusorgru/aurora" "github.com/manifoldco/promptui" - "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" "github.com/taskctl/taskctl/internal/config" @@ -119,14 +119,14 @@ func NewApp() *cli.App { } if c.Bool("debug") || cfg.Debug { - logrus.SetLevel(logrus.DebugLevel) + slog.SetLogLoggerLevel(slog.LevelDebug) } else { - logrus.SetLevel(logrus.InfoLevel) + slog.SetLogLoggerLevel(slog.LevelInfo) } if c.Bool("quiet") { c.App.ErrWriter = io.Discard - logrus.SetOutput(io.Discard) + slog.SetDefault(slog.New(slog.NewTextHandler(io.Discard, nil))) cfg.Quiet = true } else { if c.IsSet("output") { diff --git a/cmd/taskctl_cmd/taskctl_test.go b/cmd/cmd_test.go similarity index 99% rename from cmd/taskctl_cmd/taskctl_test.go rename to cmd/cmd_test.go index 407d8a13..5306f8dd 100644 --- a/cmd/taskctl_cmd/taskctl_test.go +++ b/cmd/cmd_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "bytes" diff --git a/cmd/taskctl_cmd/completion.go b/cmd/completion.go similarity index 94% rename from cmd/taskctl_cmd/completion.go rename to cmd/completion.go index a7f8b315..0a1e1535 100644 --- a/cmd/taskctl_cmd/completion.go +++ b/cmd/completion.go @@ -1,10 +1,9 @@ -package taskctl_cmd +package cmd import ( "fmt" - "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "io" + "log/slog" ) func newCompletionCommand() *cli.Command { @@ -13,8 +12,7 @@ func newCompletionCommand() *cli.Command { Usage: "generates completion scripts", UsageText: helpText, Action: func(c *cli.Context) error { - logrus.SetLevel(logrus.PanicLevel) - logrus.SetOutput(io.Discard) + slog.SetLogLoggerLevel(slog.LevelError) var shell string if !c.Args().Present() { diff --git a/cmd/taskctl_cmd/completion_test.go b/cmd/completion_test.go similarity index 95% rename from cmd/taskctl_cmd/completion_test.go rename to cmd/completion_test.go index 3e4c0866..d465dfac 100644 --- a/cmd/taskctl_cmd/completion_test.go +++ b/cmd/completion_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import "testing" diff --git a/cmd/taskctl_cmd/graph.go b/cmd/graph.go similarity index 95% rename from cmd/taskctl_cmd/graph.go rename to cmd/graph.go index 91faa544..3903a5d1 100644 --- a/cmd/taskctl_cmd/graph.go +++ b/cmd/graph.go @@ -1,11 +1,11 @@ -package taskctl_cmd +package cmd import ( "errors" "fmt" + "log/slog" "github.com/emicklei/dot" - "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" "github.com/taskctl/taskctl/pkg/scheduler" @@ -29,7 +29,7 @@ func newGraphCommand() *cli.Command { if c.NArg() == 0 { err := cli.ShowCommandHelp(c, "graph") if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } return errors.New("no pipeline set") } diff --git a/cmd/taskctl_cmd/graph_test.go b/cmd/graph_test.go similarity index 96% rename from cmd/taskctl_cmd/graph_test.go rename to cmd/graph_test.go index c0f865f1..3871a219 100644 --- a/cmd/taskctl_cmd/graph_test.go +++ b/cmd/graph_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "testing" diff --git a/cmd/taskctl_cmd/init.go b/cmd/init.go similarity index 99% rename from cmd/taskctl_cmd/init.go rename to cmd/init.go index f2452982..021d58fd 100644 --- a/cmd/taskctl_cmd/init.go +++ b/cmd/init.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "errors" diff --git a/cmd/taskctl_cmd/init_test.go b/cmd/init_test.go similarity index 97% rename from cmd/taskctl_cmd/init_test.go rename to cmd/init_test.go index ebef08f0..395ef63c 100644 --- a/cmd/taskctl_cmd/init_test.go +++ b/cmd/init_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "os" diff --git a/cmd/taskctl_cmd/list.go b/cmd/list.go similarity index 98% rename from cmd/taskctl_cmd/list.go rename to cmd/list.go index a5dbaa52..4167dc8a 100644 --- a/cmd/taskctl_cmd/list.go +++ b/cmd/list.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "fmt" diff --git a/cmd/taskctl_cmd/list_test.go b/cmd/list_test.go similarity index 96% rename from cmd/taskctl_cmd/list_test.go rename to cmd/list_test.go index e816d020..d9263af4 100644 --- a/cmd/taskctl_cmd/list_test.go +++ b/cmd/list_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import "testing" diff --git a/cmd/taskctl_cmd/run.go b/cmd/run.go similarity index 99% rename from cmd/taskctl_cmd/run.go rename to cmd/run.go index 6042da32..cac5d16e 100644 --- a/cmd/taskctl_cmd/run.go +++ b/cmd/run.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "fmt" diff --git a/cmd/taskctl_cmd/run_test.go b/cmd/run_test.go similarity index 98% rename from cmd/taskctl_cmd/run_test.go rename to cmd/run_test.go index 22a1f001..cbf6768e 100644 --- a/cmd/taskctl_cmd/run_test.go +++ b/cmd/run_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import "testing" diff --git a/cmd/taskctl_cmd/show.go b/cmd/show.go similarity index 97% rename from cmd/taskctl_cmd/show.go rename to cmd/show.go index 5d53e461..d4bae55a 100644 --- a/cmd/taskctl_cmd/show.go +++ b/cmd/show.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "errors" diff --git a/cmd/taskctl_cmd/show_test.go b/cmd/show_test.go similarity index 94% rename from cmd/taskctl_cmd/show_test.go rename to cmd/show_test.go index 161f5a0c..3be6d2d0 100644 --- a/cmd/taskctl_cmd/show_test.go +++ b/cmd/show_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import "testing" diff --git a/cmd/taskctl_cmd/testdata/graph.yaml b/cmd/testdata/graph.yaml similarity index 100% rename from cmd/taskctl_cmd/testdata/graph.yaml rename to cmd/testdata/graph.yaml diff --git a/cmd/taskctl_cmd/testdata/task.yaml b/cmd/testdata/task.yaml similarity index 100% rename from cmd/taskctl_cmd/testdata/task.yaml rename to cmd/testdata/task.yaml diff --git a/cmd/taskctl_cmd/testdata/watch.yaml b/cmd/testdata/watch.yaml similarity index 100% rename from cmd/taskctl_cmd/testdata/watch.yaml rename to cmd/testdata/watch.yaml diff --git a/cmd/taskctl_cmd/validate.go b/cmd/validate.go similarity index 97% rename from cmd/taskctl_cmd/validate.go rename to cmd/validate.go index 5c6db0be..37218354 100644 --- a/cmd/taskctl_cmd/validate.go +++ b/cmd/validate.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "fmt" diff --git a/cmd/taskctl_cmd/validate_test.go b/cmd/validate_test.go similarity index 94% rename from cmd/taskctl_cmd/validate_test.go rename to cmd/validate_test.go index 2358463f..c5f2d508 100644 --- a/cmd/taskctl_cmd/validate_test.go +++ b/cmd/validate_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import "testing" diff --git a/cmd/taskctl_cmd/watch.go b/cmd/watch.go similarity index 93% rename from cmd/taskctl_cmd/watch.go rename to cmd/watch.go index 995e57a4..1b529a21 100644 --- a/cmd/taskctl_cmd/watch.go +++ b/cmd/watch.go @@ -1,7 +1,8 @@ -package taskctl_cmd +package cmd import ( "fmt" + "log/slog" "sync" "github.com/taskctl/taskctl/pkg/output" @@ -9,8 +10,6 @@ import ( "github.com/urfave/cli/v2" "github.com/taskctl/taskctl/internal/watch" - - "github.com/sirupsen/logrus" ) func newWatchCommand() *cli.Command { @@ -50,7 +49,7 @@ func newWatchCommand() *cli.Command { err = w.Run(taskRunner) if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } }(w) } diff --git a/cmd/taskctl_cmd/watch_test.go b/cmd/watch_test.go similarity index 95% rename from cmd/taskctl_cmd/watch_test.go rename to cmd/watch_test.go index 38811dbc..45ed1464 100644 --- a/cmd/taskctl_cmd/watch_test.go +++ b/cmd/watch_test.go @@ -1,4 +1,4 @@ -package taskctl_cmd +package cmd import ( "testing" diff --git a/go.mod b/go.mod index cfebafb4..903349ee 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/mapstructure v1.5.0 github.com/pelletier/go-toml v1.9.5 - github.com/sirupsen/logrus v1.9.3 github.com/urfave/cli/v2 v2.27.5 golang.org/x/text v0.21.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 4400eed8..7088a57c 100644 --- a/go.sum +++ b/go.sum @@ -17,9 +17,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/dot v1.6.4 h1:cG9ycT67d9Yw22G+mAb4XiuUz6E6H1S0zePp/5Cwe/c= github.com/emicklei/dot v1.6.4/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= @@ -48,17 +45,10 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= @@ -67,7 +57,6 @@ golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -79,7 +68,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= diff --git a/internal/config/config.go b/internal/config/config.go index 587dac8c..f1457237 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -2,13 +2,12 @@ package config import ( "fmt" + "log/slog" "os" "github.com/taskctl/taskctl/pkg/variables" "dario.cat/mergo" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/internal/watch" "github.com/taskctl/taskctl/pkg/output" "github.com/taskctl/taskctl/pkg/runner" @@ -50,7 +49,7 @@ type Config struct { func (cfg *Config) merge(src *Config) error { defer func() { if err := recover(); err != nil { - logrus.Error(err) + slog.Error(fmt.Sprintf("%s", err)) } }() diff --git a/internal/config/loader.go b/internal/config/loader.go index 563aafb0..5e778faf 100644 --- a/internal/config/loader.go +++ b/internal/config/loader.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log/slog" "mime" "net/http" "net/url" @@ -17,7 +18,6 @@ import ( "dario.cat/mergo" "github.com/mitchellh/mapstructure" "github.com/pelletier/go-toml" - "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" "github.com/taskctl/taskctl/pkg/utils" @@ -92,7 +92,7 @@ func (cl *Loader) Load(file string) (*Config, error) { } cl.dst.Variables.Set("Root", cl.dir) - logrus.Debugf("config %s loaded", file) + slog.Debug(fmt.Sprintf("config %s loaded", file)) return cl.dst, nil } @@ -173,7 +173,7 @@ func (cl *Loader) load(file string) (config map[string]interface{}, err error) { raw, err = cl.loadDir(importFile) } if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } } if err != nil { diff --git a/internal/watch/watch.go b/internal/watch/watch.go index 0c3cb1c1..94a8175f 100644 --- a/internal/watch/watch.go +++ b/internal/watch/watch.go @@ -1,11 +1,11 @@ package watch import ( + "fmt" + "log/slog" "sync" "time" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/variables" "github.com/bmatcuk/doublestar" @@ -104,10 +104,10 @@ func NewWatcher(name string, events, watch, exclude []string, t *task.Task) (w * func (w *Watcher) Run(r *runner.TaskRunner) (err error) { w.r = r - logrus.Debugf("starting watcher %s", w.name) + slog.Debug(fmt.Sprintf("starting watcher %s", w.name)) for _, path := range w.paths { err = w.fsw.Add(path) - logrus.Debugf("watcher \"%s\" is waiting for events in %s", w.name, path) + slog.Debug(fmt.Sprintf("watcher \"%s\" is waiting for events in %s", w.name, path)) if err != nil { return err } @@ -116,7 +116,7 @@ func (w *Watcher) Run(r *runner.TaskRunner) (err error) { go func() { err := w.r.Run(w.task) if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } }() @@ -137,18 +137,18 @@ func (w *Watcher) Run(r *runner.TaskRunner) (err error) { } w.eventsWg.Add(1) go w.handle(event) - logrus.Debugf("%s: event \"%s\" in file \"%s\"", w.name, event.Op.String(), event.Name) + slog.Debug(fmt.Sprintf("%s: event \"%s\" in file \"%s\"", w.name, event.Op.String(), event.Name)) if event.Op == fsnotify.Rename { err = w.fsw.Add(event.Name) if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } } case err, ok := <-w.fsw.Errors: if !ok { return } - logrus.Error(err) + slog.Error(err.Error()) default: } } @@ -167,7 +167,7 @@ func (w *Watcher) Close() { if w.fsw != nil { err := w.fsw.Close() if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } } w.mu.Lock() @@ -185,7 +185,7 @@ func (w *Watcher) handle(event fsnotify.Event) { } w.r.Cancel() - logrus.Debugf("running task \"%s\" for watcher \"%s\"", w.task.Name, w.name) + slog.Debug(fmt.Sprintf("running task \"%s\" for watcher \"%s\"", w.task.Name, w.name)) t := *w.task t.Env = t.Env.Merge(variables.FromMap(map[string]string{ @@ -200,6 +200,6 @@ func (w *Watcher) handle(event fsnotify.Event) { err := w.r.Run(&t) if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } } diff --git a/main.go b/main.go index 9ca34dd6..d86e3f5c 100644 --- a/main.go +++ b/main.go @@ -1,19 +1,15 @@ package main import ( - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/cmd/taskctl_cmd" + "github.com/taskctl/taskctl/cmd" + "log/slog" + "os" ) func main() { - logrus.SetFormatter(&logrus.TextFormatter{ - DisableColors: false, - TimestampFormat: "2006-01-02 15:04:05", - FullTimestamp: false, - }) - - err := taskctl_cmd.Run() + err := cmd.Run() if err != nil { - logrus.Fatal(err) + slog.Error(err.Error()) + os.Exit(1) } } diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index 5184c361..74300366 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -3,14 +3,14 @@ package executor import ( "bytes" "context" + "fmt" "io" + "log/slog" "os" "strings" "mvdan.cc/sh/v3/expand" - "github.com/sirupsen/logrus" - "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" @@ -81,7 +81,7 @@ func (e *DefaultExecutor) Execute(ctx context.Context, job *Job) ([]byte, error) job.Dir = e.dir } - logrus.Debugf("Executing \"%s\"", command) + slog.Debug(fmt.Sprintf("Executing \"%s\"", command)) e.interp.Dir = job.Dir e.interp.Env = expand.ListEnviron(env...) diff --git a/pkg/output/output_test.go b/pkg/output/output_test.go index d73dece5..c519cc3d 100644 --- a/pkg/output/output_test.go +++ b/pkg/output/output_test.go @@ -1,12 +1,12 @@ package output import ( + "bufio" "bytes" + "log/slog" "strings" "testing" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/task" ) @@ -22,7 +22,7 @@ func TestNewTaskOutput_Prefixed(t *testing.T) { t.Error() } - logrus.SetOutput(&b) + slog.SetDefault(slog.New(slog.NewTextHandler(bufio.NewWriter(&b), nil))) tt := task.FromCommands("echo 1") tt.Name = "task1" o, err := NewTaskOutput( @@ -63,7 +63,7 @@ func TestNewTaskOutput(t *testing.T) { t.Error() } - logrus.SetOutput(&b) + slog.SetDefault(slog.New(slog.NewTextHandler(bufio.NewWriter(&b), nil))) tt := task.FromCommands("echo 1") tt.Name = "task1" o, err := NewTaskOutput( diff --git a/pkg/output/prefixed.go b/pkg/output/prefixed.go index b9f84578..d59edc42 100644 --- a/pkg/output/prefixed.go +++ b/pkg/output/prefixed.go @@ -4,12 +4,11 @@ import ( "bufio" "fmt" "io" + "log/slog" "regexp" "github.com/logrusorgru/aurora" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/task" ) @@ -63,17 +62,17 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { } func (d *prefixedOutputDecorator) WriteHeader() error { - logrus.Infof("Running task %s...", d.t.Name) + slog.Info(fmt.Sprintf("Running task %s...", d.t.Name)) return nil } func (d *prefixedOutputDecorator) WriteFooter() error { err := d.w.Flush() if err != nil { - logrus.Warning(err) + slog.Warn(err.Error()) } - logrus.Infof("%s finished. Duration %s", d.t.Name, d.t.Duration()) + slog.Info(fmt.Sprintf("%s finished. Duration %s", d.t.Name, d.t.Duration())) return nil } diff --git a/pkg/output/prefixed_test.go b/pkg/output/prefixed_test.go index 9edf3eaa..e0d670a9 100644 --- a/pkg/output/prefixed_test.go +++ b/pkg/output/prefixed_test.go @@ -1,18 +1,18 @@ package output import ( + "bufio" "bytes" + "log/slog" "strings" "testing" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/task" ) func Test_prefixedOutputDecorator(t *testing.T) { var l, b bytes.Buffer - logrus.SetOutput(&l) + slog.SetDefault(slog.New(slog.NewTextHandler(bufio.NewWriter(&l), nil))) dec := newPrefixedOutputWriter(&task.Task{Name: "task1"}, &b) err := dec.WriteHeader() diff --git a/pkg/runner/context.go b/pkg/runner/context.go index 33fa81a7..7e56f26f 100644 --- a/pkg/runner/context.go +++ b/pkg/runner/context.go @@ -2,6 +2,8 @@ package runner import ( "context" + "fmt" + "log/slog" "sync" "github.com/taskctl/taskctl/pkg/executor" @@ -9,8 +11,6 @@ import ( "github.com/taskctl/taskctl/pkg/variables" "github.com/taskctl/taskctl/pkg/utils" - - "github.com/sirupsen/logrus" ) // ExecutionContext allow you to set up execution environment, variables, binary which will run your task, up/down commands etc. @@ -65,7 +65,7 @@ func (c *ExecutionContext) Up() error { c.mu.Lock() c.startupError = err c.mu.Unlock() - logrus.Errorf("context startup error: %s", err) + slog.Error(fmt.Sprintf("context startup error: %s", err.Error())) } } }) @@ -79,7 +79,7 @@ func (c *ExecutionContext) Down() { for _, command := range c.down { err := c.runServiceCommand(command) if err != nil { - logrus.Errorf("context cleanup error: %s", err) + slog.Error(fmt.Sprintf("context cleanup error: %s", err.Error())) } } }) @@ -110,7 +110,7 @@ func (c *ExecutionContext) After() error { } func (c *ExecutionContext) runServiceCommand(command string) (err error) { - logrus.Debugf("running context service command: %s", command) + slog.Debug(fmt.Sprintf("running context service command: %s", command)) ex, err := executor.NewDefaultExecutor(nil, nil, nil) if err != nil { return err @@ -124,7 +124,7 @@ func (c *ExecutionContext) runServiceCommand(command string) (err error) { }) if err != nil { if out != nil { - logrus.Warning(string(out)) + slog.Warn(string(out)) } return err diff --git a/pkg/runner/context_test.go b/pkg/runner/context_test.go index 4d985322..8a3fd011 100644 --- a/pkg/runner/context_test.go +++ b/pkg/runner/context_test.go @@ -2,16 +2,15 @@ package runner import ( "io" + "log/slog" "testing" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/task" "github.com/taskctl/taskctl/pkg/variables" ) func TestContext(t *testing.T) { - logrus.SetOutput(io.Discard) + slog.SetDefault(slog.New(slog.NewTextHandler(io.Discard, nil))) c1 := NewExecutionContext(nil, "/", variables.NewVariables(), []string{"true"}, []string{"false"}, []string{"true"}, []string{"false"}) c2 := NewExecutionContext(nil, "/", variables.NewVariables(), []string{"false"}, []string{"false"}, []string{"false"}, []string{"false"}) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 4bc7856d..7ba1829c 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -5,6 +5,7 @@ import ( "fmt" "golang.org/x/text/language" "io" + "log/slog" "os" "regexp" "strings" @@ -18,8 +19,6 @@ import ( "github.com/taskctl/taskctl/pkg/output" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/task" ) @@ -129,12 +128,12 @@ func (r *TaskRunner) Run(t *task.Task) error { defer func() { err := taskOutput.Finish() if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } err = execContext.After() if err != nil { - logrus.Error(err) + slog.Error(err.Error()) } if !t.Errored && !t.Skipped { @@ -154,7 +153,7 @@ func (r *TaskRunner) Run(t *task.Task) error { } if !meets { - logrus.Infof("task %s was skipped", t.Name) + slog.Info(fmt.Sprintf("task %s was skipped", t.Name)) t.Skipped = true return nil } @@ -188,7 +187,7 @@ func (r *TaskRunner) Cancel() { r.cancelMutex.Lock() if !r.canceling { r.canceling = true - defer logrus.Debug("runner has been cancelled") + defer slog.Debug("runner has been cancelled") r.cancelFunc() } r.cancelMutex.Unlock() @@ -265,7 +264,7 @@ func (r *TaskRunner) after(ctx context.Context, t *task.Task, env, vars variable _, err = exec.Execute(ctx, job) if err != nil { - logrus.Warning(err) + slog.Warn(err.Error()) } } @@ -359,7 +358,7 @@ func (r *TaskRunner) execute(ctx context.Context, t *task.Task, job *executor.Jo prevOutput, err = exec.Execute(ctx, nextJob) if err != nil { - logrus.Debug(err.Error()) + slog.Debug(err.Error()) if status, ok := executor.IsExitStatus(err); ok { t.ExitCode = int16(status) if t.AllowFailure { diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index bd697ae3..4d823797 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -1,6 +1,7 @@ package scheduler import ( + "log/slog" "os/exec" "sync" "sync/atomic" @@ -8,8 +9,6 @@ import ( "github.com/taskctl/taskctl/pkg/utils" - "github.com/sirupsen/logrus" - "github.com/taskctl/taskctl/pkg/runner" ) @@ -52,7 +51,7 @@ func (s *Scheduler) Schedule(g *ExecutionGraph) error { if stage.Condition != "" { meets, err := checkStageCondition(stage.Condition) if err != nil { - logrus.Error(err) + slog.Error(err.Error()) stage.UpdateStatus(StatusError) s.Cancel() continue @@ -116,6 +115,8 @@ func (s *Scheduler) isDone(p *ExecutionGraph) bool { switch stage.ReadStatus() { case StatusWaiting, StatusRunning: return false + default: + continue } } @@ -152,7 +153,8 @@ func checkStatus(p *ExecutionGraph, stage *Stage) (ready bool) { for _, dep := range p.To(stage.Name) { depStage, err := p.Node(dep) if err != nil { - logrus.Fatal(err) + slog.Error(err.Error()) + panic(err) } switch depStage.ReadStatus() { From b228cba3ef305148722180c81d72fb9bda6a2c80 Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 12:28:51 +0200 Subject: [PATCH 4/7] Fix GA --- .github/workflows/coverage.yml | 6 ++--- .github/workflows/pull-request-checks.yml | 27 +++++++++++++---------- .github/workflows/release.yml | 7 +++--- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 57079d97..d2e095cb 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -8,15 +8,15 @@ jobs: run: runs-on: ubuntu-latest steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod cache-dependency-path: go.sum - - name: Check out code into the Go module directory - uses: actions/checkout@v4 - - name: Test with coverage report run: | go test -race -coverprofile=coverage.out -covermode=atomic ./... diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml index a429f1ea..a52926fe 100644 --- a/.github/workflows/pull-request-checks.yml +++ b/.github/workflows/pull-request-checks.yml @@ -8,15 +8,18 @@ jobs: name: Test runs-on: ubuntu-latest steps: - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache-dependency-path: go.sum - - name: Check out code into the Go module directory - uses: actions/checkout@v4 - - name: Lint - uses: golangci/golangci-lint-action@v6 - - name: Test - run: | - go test -v -race ./... + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + + - name: Lint + uses: golangci/golangci-lint-action@v6 + + - name: Test + run: | + go test -v -race ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4207961b..ede5e64a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,12 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v5 with: - go-version: 1.16.x + go-version-file: go.mod + cache-dependency-path: go.sum - name: Install Snapcraft uses: samuelmeuli/action-snapcraft@v1 From 58daacfd55c07c2f8ea6c8c23edaab25ae2bd3d0 Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 14:51:24 +0200 Subject: [PATCH 5/7] Tests fixes --- internal/watch/watch.go | 10 +++++++- internal/watch/watch_test.go | 21 +++++++++++----- pkg/output/cockpit.go | 11 ++++++--- pkg/output/cockpit_test.go | 48 +++--------------------------------- pkg/output/output.go | 4 +-- pkg/output/output_test.go | 1 - pkg/output/prefixed.go | 37 ++++++++------------------- pkg/output/prefixed_test.go | 9 +++---- pkg/runner/runner.go | 4 +-- tasks.yaml | 2 +- 10 files changed, 52 insertions(+), 95 deletions(-) diff --git a/internal/watch/watch.go b/internal/watch/watch.go index 94a8175f..8bd7964d 100644 --- a/internal/watch/watch.go +++ b/internal/watch/watch.go @@ -4,6 +4,7 @@ import ( "fmt" "log/slog" "sync" + "sync/atomic" "time" "github.com/taskctl/taskctl/pkg/variables" @@ -43,6 +44,7 @@ type Watcher struct { closed chan struct{} isClosed bool mu sync.Mutex + running atomic.Bool eventsWg sync.WaitGroup } @@ -113,6 +115,8 @@ func (w *Watcher) Run(r *runner.TaskRunner) (err error) { } } + w.running.Store(true) + go func() { err := w.r.Run(w.task) if err != nil { @@ -161,7 +165,7 @@ func (w *Watcher) Run(r *runner.TaskRunner) (err error) { // Close stops this watcher func (w *Watcher) Close() { - if w.isClosed { + if w.isClosed || !w.running.Load() { return } if w.fsw != nil { @@ -176,6 +180,10 @@ func (w *Watcher) Close() { <-w.finished } +func (w *Watcher) Running() bool { + return w.running.Load() +} + func (w *Watcher) handle(event fsnotify.Event) { defer w.eventsWg.Done() diff --git a/internal/watch/watch_test.go b/internal/watch/watch_test.go index fab7e273..a509b466 100644 --- a/internal/watch/watch_test.go +++ b/internal/watch/watch_test.go @@ -6,8 +6,6 @@ import ( "sync" "testing" - "github.com/fsnotify/fsnotify" - "github.com/taskctl/taskctl/pkg/runner" "github.com/taskctl/taskctl/pkg/task" ) @@ -17,6 +15,11 @@ func TestNewWatcher(t *testing.T) { if err != nil { t.Fatal(err) } + + t.Cleanup(func() { + _ = os.Remove("fake_file.json") + }) + w, err := NewWatcher("w1", []string{}, []string{filepath.Join(cwd, "*")}, []string{"watch_test.go"}, task.FromCommands("true")) if err != nil { t.Fatal(err) @@ -31,15 +34,21 @@ func TestNewWatcher(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - err = w.Run(r) + err := w.Run(r) if err != nil { t.Error(err) } }() - w.fsw.Events <- fsnotify.Event{ - Name: "fake_file.json", - Op: fsnotify.Rename, + err = os.WriteFile(filepath.Join(cwd, "fake_file.json"), []byte{}, 0644) + if err != nil { + t.Fatal(err) + } + + for { + if w.Running() { + break + } } w.Close() diff --git a/pkg/output/cockpit.go b/pkg/output/cockpit.go index 1c5dd1d5..5b4c9be2 100644 --- a/pkg/output/cockpit.go +++ b/pkg/output/cockpit.go @@ -15,7 +15,8 @@ import ( "github.com/taskctl/taskctl/pkg/task" ) -var frame = 100 * time.Millisecond +const frame = 100 * time.Millisecond + var base *baseCockpit type baseCockpit struct { @@ -37,8 +38,12 @@ func (b *baseCockpit) start() *spinner.Spinner { return b.spinner } - s := spinner.New(spinner.CharSets[b.charSet], frame, spinner.WithColor("yellow")) - s.Writer = b.w + s := spinner.New( + spinner.CharSets[b.charSet], + frame, + spinner.WithColor("yellow"), + spinner.WithWriter(b.w), + ) s.PreUpdate = func(s *spinner.Spinner) { tasks := make([]string, 0) b.mu.Lock() diff --git a/pkg/output/cockpit_test.go b/pkg/output/cockpit_test.go index f349692c..6126f209 100644 --- a/pkg/output/cockpit_test.go +++ b/pkg/output/cockpit_test.go @@ -2,70 +2,28 @@ package output import ( "bytes" - "strings" - "sync" - "testing" - "time" - "github.com/taskctl/taskctl/pkg/task" + "testing" ) func Test_cockpitOutputDecorator(t *testing.T) { - b := safebuffer{} + b := bytes.NewBuffer([]byte{}) closeCh = make(chan bool) - dec := newCockpitOutputWriter(&task.Task{Name: "task1"}, &b, closeCh) + dec := newCockpitOutputWriter(&task.Task{Name: "task1"}, b, closeCh) err := dec.WriteHeader() if err != nil { t.Fatal(err) } - time.Sleep(frame * 2) - - if !strings.Contains(b.String(), "Running: task1") { - t.Fatal() - } - n, err := dec.Write([]byte("lorem ipsum")) if err != nil && n == 0 { t.Fatal() } - if strings.Contains(b.String(), "lorem ipsum") { - t.Fatal() - } - err = dec.WriteFooter() if err != nil { t.Fatal(err) } - time.Sleep(frame * 2) - - if !strings.Contains(b.String(), "Finished") { - t.Fatal() - } - close(closeCh) } - -// safebuffer is a goroutine safe bytes.safebuffer -type safebuffer struct { - buffer bytes.Buffer - mutex sync.Mutex -} - -// Write appends the contents of p to the buffer, growing the buffer as needed. It returns -// the number of bytes written. -func (s *safebuffer) Write(p []byte) (n int, err error) { - s.mutex.Lock() - defer s.mutex.Unlock() - return s.buffer.Write(p) -} - -// String returns the contents of the unread portion of the buffer -// as a string. If the safebuffer is a nil pointer, it returns "". -func (s *safebuffer) String() string { - s.mutex.Lock() - defer s.mutex.Unlock() - return s.buffer.String() -} diff --git a/pkg/output/output.go b/pkg/output/output.go index a21d20f1..78e30e44 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -62,12 +62,12 @@ func (o *TaskOutput) Stderr() io.Writer { } // Start should be called before task's output starts -func (o TaskOutput) Start() error { +func (o *TaskOutput) Start() error { return o.decorator.WriteHeader() } // Finish should be called after task completes -func (o TaskOutput) Finish() error { +func (o *TaskOutput) Finish() error { return o.decorator.WriteFooter() } diff --git a/pkg/output/output_test.go b/pkg/output/output_test.go index c519cc3d..7c528fb1 100644 --- a/pkg/output/output_test.go +++ b/pkg/output/output_test.go @@ -22,7 +22,6 @@ func TestNewTaskOutput_Prefixed(t *testing.T) { t.Error() } - slog.SetDefault(slog.New(slog.NewTextHandler(bufio.NewWriter(&b), nil))) tt := task.FromCommands("echo 1") tt.Name = "task1" o, err := NewTaskOutput( diff --git a/pkg/output/prefixed.go b/pkg/output/prefixed.go index d59edc42..05db4a74 100644 --- a/pkg/output/prefixed.go +++ b/pkg/output/prefixed.go @@ -4,11 +4,9 @@ import ( "bufio" "fmt" "io" - "log/slog" "regexp" "github.com/logrusorgru/aurora" - "github.com/taskctl/taskctl/pkg/task" ) @@ -18,13 +16,13 @@ var ansiRegexp = regexp.MustCompile(ansi) type prefixedOutputDecorator struct { t *task.Task - w *bufio.Writer + w io.Writer } func newPrefixedOutputWriter(t *task.Task, w io.Writer) *prefixedOutputDecorator { return &prefixedOutputDecorator{ t: t, - w: bufio.NewWriter(&lineWriter{t: t, dst: w}), + w: w, } } @@ -40,12 +38,7 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { break } - _, err = d.w.Write(line) - if err != nil { - return 0, err - } - - err = d.w.Flush() + _, err = d.writeLine(line) if err != nil { return 0, err } @@ -53,7 +46,7 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { p = p[advance:] } - _, err := d.w.Write(p) + _, err := d.writeLine(p) if err != nil { return 0, err } @@ -62,29 +55,19 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { } func (d *prefixedOutputDecorator) WriteHeader() error { - slog.Info(fmt.Sprintf("Running task %s...", d.t.Name)) - return nil + _, err := d.w.Write([]byte(fmt.Sprintf("Running task %s...", d.t.Name))) + return err } func (d *prefixedOutputDecorator) WriteFooter() error { - err := d.w.Flush() - if err != nil { - slog.Warn(err.Error()) - } - - slog.Info(fmt.Sprintf("%s finished. Duration %s", d.t.Name, d.t.Duration())) - return nil -} - -type lineWriter struct { - t *task.Task - dst io.Writer + _, err := d.w.Write([]byte(fmt.Sprintf("%s finished. Duration %s", d.t.Name, d.t.Duration()))) + return err } -func (l lineWriter) Write(p []byte) (n int, err error) { +func (d *prefixedOutputDecorator) writeLine(p []byte) (n int, err error) { n = len(p) p = ansiRegexp.ReplaceAllLiteral(p, []byte{}) - _, err = fmt.Fprintf(l.dst, "%s: %s\r\n", aurora.Cyan(l.t.Name), p) + _, err = fmt.Fprintf(d.w, "%s: %s\r\n", aurora.Cyan(d.t.Name), p) return n, err } diff --git a/pkg/output/prefixed_test.go b/pkg/output/prefixed_test.go index e0d670a9..c0939f17 100644 --- a/pkg/output/prefixed_test.go +++ b/pkg/output/prefixed_test.go @@ -1,9 +1,7 @@ package output import ( - "bufio" "bytes" - "log/slog" "strings" "testing" @@ -11,8 +9,7 @@ import ( ) func Test_prefixedOutputDecorator(t *testing.T) { - var l, b bytes.Buffer - slog.SetDefault(slog.New(slog.NewTextHandler(bufio.NewWriter(&l), nil))) + var b bytes.Buffer dec := newPrefixedOutputWriter(&task.Task{Name: "task1"}, &b) err := dec.WriteHeader() @@ -20,7 +17,7 @@ func Test_prefixedOutputDecorator(t *testing.T) { t.Fatal(err) } - if !strings.Contains(l.String(), "Running task task1...") { + if !strings.Contains(b.String(), "Running task task1...") { t.Fatal() } @@ -38,7 +35,7 @@ func Test_prefixedOutputDecorator(t *testing.T) { t.Fatal(err) } - if !strings.Contains(l.String(), "task1 finished") { + if !strings.Contains(b.String(), "task1 finished") { t.Fatal() } } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 7ba1829c..3b02ef3a 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -22,8 +22,6 @@ import ( "github.com/taskctl/taskctl/pkg/task" ) -var caser = cases.Title(language.English) - // Runner describes tasks runner interface type Runner interface { Run(t *task.Task) error @@ -331,7 +329,7 @@ func (r *TaskRunner) checkTaskCondition(t *task.Task) (bool, error) { func (r *TaskRunner) storeTaskOutput(t *task.Task) { var envVarName string - varName := fmt.Sprintf("Tasks.%s.Output", caser.String(t.Name)) + varName := fmt.Sprintf("Tasks.%s.Output", cases.Title(language.English).String(t.Name)) if t.ExportAs == "" { envVarName = fmt.Sprintf("%s_OUTPUT", strings.ToUpper(t.Name)) diff --git a/tasks.yaml b/tasks.yaml index 67026b30..9ee04132 100644 --- a/tasks.yaml +++ b/tasks.yaml @@ -64,7 +64,7 @@ tasks: goreleaser: command: - - goreleaser --debug --rm-dist + - goreleaser --clean gofmt: dir: "{{.Root}}" From 64235384fd0def19e3789769c8ba2013879cc4fd Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 16:01:16 +0200 Subject: [PATCH 6/7] Fix races --- cmd/cmd.go | 55 +++++++++++++++++++++++++++++------------- cmd/cmd_test.go | 22 ++++++++--------- cmd/completion_test.go | 2 +- cmd/graph_test.go | 2 +- cmd/init_test.go | 2 +- cmd/list_test.go | 2 +- cmd/run.go | 15 ++++++++---- cmd/run_test.go | 2 +- cmd/show_test.go | 2 +- cmd/validate_test.go | 2 +- cmd/watch.go | 16 +++++++++--- cmd/watch_test.go | 21 ++++++++++------ 12 files changed, 93 insertions(+), 50 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 1e49b260..154f5350 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "errors" "fmt" "github.com/taskctl/taskctl/pkg/runner" @@ -10,6 +11,7 @@ import ( "os/signal" "sort" "strings" + "sync" "syscall" "github.com/logrusorgru/aurora" @@ -24,14 +26,23 @@ import ( var version = "dev" var stdin io.ReadCloser -var cancel = make(chan struct{}) +var cancelFn func() +var cancelMu sync.Mutex var cfg *config.Config +func Stdin() io.ReadCloser { + return stdin +} + +func SetStdin(newStdin io.ReadCloser) { + stdin = newStdin +} + func Run() error { stdin = os.Stdin app := NewApp() - listenSignals() + go listenSignals() return app.Run(os.Args) } @@ -46,7 +57,7 @@ func NewApp() *cli.App { Version: version, EnableBashCompletion: true, BashComplete: func(c *cli.Context) { - cfg, _ := cl.Load(c.String("config")) + cfg, _ = cl.Load(c.String("config")) suggestions := buildSuggestions(cfg) for _, v := range suggestions { @@ -166,19 +177,28 @@ func NewApp() *cli.App { } } +func Abort() { + cancelMu.Lock() + defer cancelMu.Unlock() + + cancelFn() +} + func listenSignals() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - go func() { - for sig := range sigs { - abort() - os.Exit(int(sig.(syscall.Signal))) - } - }() + for sig := range sigs { + Abort() + os.Exit(int(sig.(syscall.Signal))) + } } func rootAction(c *cli.Context) (err error) { - taskRunner, err := buildTaskRunner(c) + cancelMu.Lock() + c.Context, cancelFn = context.WithCancel(c.Context) + cancelMu.Unlock() + + taskRunner, err := buildTaskRunner(c.Context, c) if err != nil { return err } @@ -233,11 +253,7 @@ func rootAction(c *cli.Context) (err error) { return runPipeline(cfg.Pipelines[selection.Target], taskRunner, cfg.Summary || c.Bool("summary")) } -func abort() { - close(cancel) -} - -func buildTaskRunner(c *cli.Context) (*runner.TaskRunner, error) { +func buildTaskRunner(ctx context.Context, c *cli.Context) (*runner.TaskRunner, error) { ta := taskArgs(c) variables := cfg.Variables.With("Args", strings.Join(ta, " ")) variables.Set("ArgsList", ta) @@ -256,8 +272,13 @@ func buildTaskRunner(c *cli.Context) (*runner.TaskRunner, error) { } go func() { - <-cancel - taskRunner.Cancel() + for { + select { + case <-ctx.Done(): + taskRunner.Cancel() + return + } + } }() return taskRunner, nil diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 5306f8dd..e6b9b39b 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -1,15 +1,15 @@ -package cmd +package cmd_test import ( "bytes" "encoding/binary" + "github.com/manifoldco/promptui" + "github.com/taskctl/taskctl/cmd" + "github.com/urfave/cli/v2" "io" "os" "strings" "testing" - - "github.com/manifoldco/promptui" - "github.com/urfave/cli/v2" ) type appTest struct { @@ -21,7 +21,7 @@ type appTest struct { } func makeTestApp() *cli.App { - return NewApp() + return cmd.NewApp() } func runAppTest(app *cli.App, test appTest, t *testing.T) { @@ -37,22 +37,22 @@ func runAppTest(app *cli.App, test appTest, t *testing.T) { }() if test.stdin != nil { - origStdin := stdin - stdin = test.stdin + origStdin := cmd.Stdin() + cmd.SetStdin(test.stdin) defer func() { - stdin = origStdin + cmd.SetStdin(origStdin) }() } err = app.Run(test.args) - os.Stdout = origStdout - _ = w.Close() - if err != nil && !test.errored { t.Fatal(err) return } + os.Stdout = origStdout + _ = w.Close() + var buf bytes.Buffer _, err = io.Copy(&buf, r) if err != nil { diff --git a/cmd/completion_test.go b/cmd/completion_test.go index d465dfac..2dcb643e 100644 --- a/cmd/completion_test.go +++ b/cmd/completion_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import "testing" diff --git a/cmd/graph_test.go b/cmd/graph_test.go index 3871a219..9529c6af 100644 --- a/cmd/graph_test.go +++ b/cmd/graph_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import ( "testing" diff --git a/cmd/init_test.go b/cmd/init_test.go index 395ef63c..0aa5860b 100644 --- a/cmd/init_test.go +++ b/cmd/init_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import ( "os" diff --git a/cmd/list_test.go b/cmd/list_test.go index d9263af4..f4f8521f 100644 --- a/cmd/list_test.go +++ b/cmd/list_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import "testing" diff --git a/cmd/run.go b/cmd/run.go index cac5d16e..da11e3ba 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "fmt" "os" "sort" @@ -37,7 +38,11 @@ func newRunCommand() *cli.Command { }, }, Before: func(c *cli.Context) (err error) { - taskRunner, err = buildTaskRunner(c) + cancelMu.Lock() + c.Context, cancelFn = context.WithCancel(c.Context) + cancelMu.Unlock() + + taskRunner, err = buildTaskRunner(c.Context, c) return err }, After: func(c *cli.Context) error { @@ -118,10 +123,10 @@ func runTarget(name string, c *cli.Context, taskRunner *runner.TaskRunner) (err func runPipeline(g *scheduler.ExecutionGraph, taskRunner *runner.TaskRunner, summary bool) error { sd := scheduler.NewScheduler(taskRunner) - go func() { - <-cancel - sd.Cancel() - }() + //go func() { + // <-cancelCh + // sd.Cancel() + //}() err := sd.Schedule(g) if err != nil { diff --git a/cmd/run_test.go b/cmd/run_test.go index cbf6768e..29415edb 100644 --- a/cmd/run_test.go +++ b/cmd/run_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import "testing" diff --git a/cmd/show_test.go b/cmd/show_test.go index 3be6d2d0..8531ba11 100644 --- a/cmd/show_test.go +++ b/cmd/show_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import "testing" diff --git a/cmd/validate_test.go b/cmd/validate_test.go index c5f2d508..1c6b37a1 100644 --- a/cmd/validate_test.go +++ b/cmd/validate_test.go @@ -1,4 +1,4 @@ -package cmd +package cmd_test import "testing" diff --git a/cmd/watch.go b/cmd/watch.go index 1b529a21..1509c2fd 100644 --- a/cmd/watch.go +++ b/cmd/watch.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "fmt" "log/slog" "sync" @@ -25,7 +26,11 @@ func newWatchCommand() *cli.Command { return nil }, Action: func(c *cli.Context) (err error) { - taskRunner, err := buildTaskRunner(c) + cancelMu.Lock() + c.Context, cancelFn = context.WithCancel(c.Context) + cancelMu.Unlock() + + taskRunner, err := buildTaskRunner(c.Context, c) if err != nil { return err } @@ -40,8 +45,13 @@ func newWatchCommand() *cli.Command { return fmt.Errorf("unknown watcher %s", name) } go func(w *watch.Watcher) { - <-cancel - w.Close() + for { + select { + case <-c.Context.Done(): + w.Close() + return + } + } }(w) go func(w *watch.Watcher) { diff --git a/cmd/watch_test.go b/cmd/watch_test.go index 45ed1464..3b277ac2 100644 --- a/cmd/watch_test.go +++ b/cmd/watch_test.go @@ -1,23 +1,30 @@ -package cmd +package cmd_test import ( + "github.com/taskctl/taskctl/cmd" "testing" "time" ) -func Test_watchCommand(t *testing.T) { +func Test_watchCommand_error(t *testing.T) { app := makeTestApp() - listenSignals() - tests := []appTest{ {args: []string{"", "-c", "testdata/watch.yaml", "watch", "watch:watcher99"}, errored: true}, + } + + for _, v := range tests { + runAppTest(app, v, t) + } +} + +func Test_watchCommand_success(t *testing.T) { + app := makeTestApp() + tests := []appTest{ {args: []string{"", "-c", "testdata/watch.yaml", "watch", "watch:watcher1"}, errored: false}, } for _, v := range tests { + time.AfterFunc(100*time.Millisecond, cmd.Abort) runAppTest(app, v, t) - time.AfterFunc(500*time.Millisecond, func() { - abort() - }) } } From d691ac0bc90ec4b34cf68cdb36d0cb58096d4595 Mon Sep 17 00:00:00 2001 From: Yevhen Terentiev Date: Sun, 12 Jan 2025 16:16:17 +0200 Subject: [PATCH 7/7] minor fixes --- cmd/cmd.go | 9 ++------- cmd/watch.go | 9 ++------- pkg/output/prefixed.go | 10 +++++----- tasks.yaml | 12 +++--------- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 154f5350..8eddbbd1 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -272,13 +272,8 @@ func buildTaskRunner(ctx context.Context, c *cli.Context) (*runner.TaskRunner, e } go func() { - for { - select { - case <-ctx.Done(): - taskRunner.Cancel() - return - } - } + <-ctx.Done() + taskRunner.Cancel() }() return taskRunner, nil diff --git a/cmd/watch.go b/cmd/watch.go index 1509c2fd..6a2cfff2 100644 --- a/cmd/watch.go +++ b/cmd/watch.go @@ -45,13 +45,8 @@ func newWatchCommand() *cli.Command { return fmt.Errorf("unknown watcher %s", name) } go func(w *watch.Watcher) { - for { - select { - case <-c.Context.Done(): - w.Close() - return - } - } + <-c.Context.Done() + w.Close() }(w) go func(w *watch.Watcher) { diff --git a/pkg/output/prefixed.go b/pkg/output/prefixed.go index 05db4a74..27bc98b9 100644 --- a/pkg/output/prefixed.go +++ b/pkg/output/prefixed.go @@ -38,7 +38,7 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { break } - _, err = d.writeLine(line) + _, err = d.writePrefixedLine(line) if err != nil { return 0, err } @@ -46,7 +46,7 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { p = p[advance:] } - _, err := d.writeLine(p) + _, err := d.writePrefixedLine(p) if err != nil { return 0, err } @@ -55,16 +55,16 @@ func (d *prefixedOutputDecorator) Write(p []byte) (int, error) { } func (d *prefixedOutputDecorator) WriteHeader() error { - _, err := d.w.Write([]byte(fmt.Sprintf("Running task %s...", d.t.Name))) + _, err := d.writePrefixedLine([]byte(fmt.Sprintf("Running task %s...", d.t.Name))) return err } func (d *prefixedOutputDecorator) WriteFooter() error { - _, err := d.w.Write([]byte(fmt.Sprintf("%s finished. Duration %s", d.t.Name, d.t.Duration()))) + _, err := d.writePrefixedLine([]byte(fmt.Sprintf("%s finished. Duration %s", d.t.Name, d.t.Duration()))) return err } -func (d *prefixedOutputDecorator) writeLine(p []byte) (n int, err error) { +func (d *prefixedOutputDecorator) writePrefixedLine(p []byte) (n int, err error) { n = len(p) p = ansiRegexp.ReplaceAllLiteral(p, []byte{}) _, err = fmt.Fprintf(d.w, "%s: %s\r\n", aurora.Cyan(d.t.Name), p) diff --git a/tasks.yaml b/tasks.yaml index 9ee04132..f1c7e146 100644 --- a/tasks.yaml +++ b/tasks.yaml @@ -31,9 +31,7 @@ pipelines: depends_on: test lints: - - task: golint - - task: govet - depends_on: golint + - task: golangci-lint tasks: test: @@ -48,13 +46,9 @@ tasks: - GOOS: darwin - GOOS: windows - golint: + golangci-lint: command: - - golint $(go list ./... | grep -v /vendor/) - - govet: - command: - - go vet $(go list ./... | grep -v /vendor/) + - golangci-lint run goimports: command: