{"id":13409703,"url":"https://github.com/taskctl/taskctl","last_synced_at":"2025-03-14T15:30:30.327Z","repository":{"id":37614052,"uuid":"221222446","full_name":"taskctl/taskctl","owner":"taskctl","description":"Concurrent task runner, developer's routine tasks automation toolkit. Simple modern alternative to GNU Make 🧰","archived":false,"fork":false,"pushed_at":"2024-05-13T19:07:55.000Z","size":2196,"stargazers_count":289,"open_issues_count":16,"forks_count":39,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-07-31T20:37:58.533Z","etag":null,"topics":["developer-tools","filesystem-watcher","filewatcher","go","golang","hacktoberfest","task-runner","tasks","watcher","watchers","workflow"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taskctl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-12T13:19:09.000Z","updated_at":"2024-07-29T07:22:54.000Z","dependencies_parsed_at":"2024-01-08T14:31:05.314Z","dependency_job_id":"d5a05d23-75d7-4242-8407-81ef2ec0664f","html_url":"https://github.com/taskctl/taskctl","commit_stats":null,"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskctl%2Ftaskctl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskctl%2Ftaskctl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskctl%2Ftaskctl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskctl%2Ftaskctl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taskctl","download_url":"https://codeload.github.com/taskctl/taskctl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243600470,"owners_count":20317280,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["developer-tools","filesystem-watcher","filewatcher","go","golang","hacktoberfest","task-runner","tasks","watcher","watchers","workflow"],"created_at":"2024-07-30T20:01:02.874Z","updated_at":"2025-03-14T15:30:30.089Z","avatar_url":"https://github.com/taskctl.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n\u003cimg width=\"400\" src=\"https://raw.githubusercontent.com/taskctl/taskctl/master/docs/logo.png\" alt=\"taskctl - developer's routine tasks automation toolkit\" title=\"taskctl - developer's routine tasks automation toolkit\" /\u003e\n\u003c/p\u003e\n\n# taskctl - concurrent task runner, developer's routine tasks automation toolkit\n[![pkg.go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go\u0026logoColor=white\u0026style=flat)](https://pkg.go.dev/github.com/taskctl/taskctl?tab=doc)\n![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/taskctl/taskctl)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/taskctl/taskctl)\n![GitHub closed issues](https://img.shields.io/github/issues-closed/taskctl/taskctl)\n![GitHub issues](https://img.shields.io/github/issues/taskctl/taskctl)\n![Licence](https://img.shields.io/github/license/taskctl/taskctl)\n\n![Tests](https://github.com/taskctl/taskctl/workflows/Test/badge.svg)\n[![Requirements Status](https://requires.io/github/taskctl/taskctl/requirements.svg?branch=master)](https://requires.io/github/taskctl/taskctl/requirements/?branch=master)\n![GitHub top language](https://img.shields.io/github/languages/top/taskctl/taskctl)\n[![Go Report Card](https://goreportcard.com/badge/github.com/taskctl/taskctl)](https://goreportcard.com/report/github.com/taskctl/taskctl)\n[![Test Coverage](https://codecov.io/gh/taskctl/taskctl/branch/master/graph/badge.svg)](https://codecov.io/gh/taskctl/taskctl/tree/master/pkg)\n[![Maintainability](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/codeclimate/codeclimate/maintainability)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](https://github.com/taskctl/taskctl/pulls)\n\n# Stand with Ukraine!\n\n---\n\u003cp align=\"center\"\u003e\n   \u003cimg align=\"center\" src=\"https://github.blog/wp-content/uploads/2022/03/1200x630-GitHub-1.png?resize=320%2C240\"\u003e\n\u003c/p\u003e\n\nWhile Russia is destroying my home and my country, killing my friends and neighbors - any russian company, organization, or citizen, who do nothing about it,\nis prohibited from using this package.\nFor others - please, pray for us, share information about war crimes Russia is conducting in Ukraine, do everything you can\nto urge your governments to be on the right side of history.\nUkraine will prevail! Good triumph over evil! Русский военный корабль, иди нах#й!\n\n---\n\nSimple 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). \nGiven a pipeline (composed of tasks or other pipelines) it builds a graph that outlines the execution plan. Each task my run concurrently or cascade.\nBeside pipelines, each single task can be started manually or triggered by built-in filesystem watcher.\n\n## Features\n- human-readable configuration format (YAML, JSON or TOML)\n- concurrent tasks execution\n- highly customizable execution plan\n- cross platform\n- import local or remote configurations\n- integrated file watcher (live reload)\n- customizable execution contexts\n- different output types\n- embeddable task runner\n- interactive prompt\n- handy autocomplete\n- and many more...\n\n```yaml\ntasks:\n  lint:\n    command:\n      - golint $(go list ./... | grep -v /vendor/)\n      - go vet $(go list ./... | grep -v /vendor/)\n  \n  test:\n    allow_failure: true\n    command: go test ./....\n        \n  build:\n    command: go build -o bin/app ./...\n    env: \n      GOOS: linux\n      GOARCH: amd64\n    before: rm -rf bin/*\n\npipelines:\n  release:\n    - task: lint\n    - task: test\n    - task: build\n      depends_on: [lint, test]\n```\nAccording to this plan `lint` and `test` will run concurrently, `build` will start only when both `lint` and `test` finished.\n\n\n[![asciicast](https://asciinema.org/a/326726.svg)](https://asciinema.org/a/326726)\n\n## Contents  \n- [Getting started](#getting-started)\n  - [Installation](#install)\n  - [Usage](#usage)\n- [Configuration](#configuration)\n    - [Global configuration](#global-configuration)\n    - [Example](#example)\n- [Tasks](#tasks)\n    - [Pass CLI arguments to task](#pass-cli-arguments-to-task)\n    - [Task's variations](#tasks-variations)\n    - [Task's variables](#tasks-variables)\n    - [Storing task's output](#storing-tasks-output) \n    - [Conditional execution](#task-conditional-execution) \n- [Pipelines](#pipelines)\n- [Filesystem watchers](#filesystem-watchers)\n    - [Patterns](#patterns)\n- [Contexts](#contexts)\n- [Output formats](#taskctl-output-formats)\n- [Embeddable task runner](#embeddable-task-runner)\n    - [Runner](#runner)\n    - [Scheduler](#scheduler)\n- [FAQ](#faq)\n  - [How does it differ from go-task/task?](#how-does-it-differ-from-go-tasktask)\n- [Autocomplete](#autocomplete)\n- [Similar projects](#similar-projects)\n- [How to contribute?](#how-to-contribute)\n- [License](#license)\n\n## Getting started\n### Install\n#### MacOS\n```\nbrew tap taskctl/taskctl\nbrew install taskctl\n```\n#### Linux\n```\nsudo wget https://github.com/taskctl/taskctl/releases/latest/download/taskctl_linux_amd64 -O /usr/local/bin/taskctl\nsudo chmod +x /usr/local/bin/taskctl\n```\n#### Ubuntu Linux\n```\nsudo snap install --classic taskctl\n```\n\n#### deb/rpm:\nDownload the .deb or .rpm from the [releases](https://github.com/taskctl/taskctl/releases) page and install with `dpkg -i` \nand `rpm -i` respectively.\n\n#### Windows\n```\nscoop bucket add taskctl https://github.com/taskctl/scoop-taskctl.git\nscoop install taskctl\n```\n#### Installation script\n```\ncurl -sL https://raw.githubusercontent.com/taskctl/taskctl/master/install.sh | sh\n```\n#### From sources\n```\ngit clone https://github.com/taskctl/taskctl\ncd taskctl\ngo build -o taskctl .\n```\n#### Docker images\nDocker images available on [Docker hub](https://hub.docker.com/repository/docker/taskctl/taskctl)\n\n### Usage\n- `taskctl` - run interactive task prompt\n- `taskctl pipeline1` - run single pipeline\n- `taskctl task1` - run single task\n- `taskctl pipeline1 task1` - run one or more pipelines and/or tasks\n- `taskctl watch watcher1 watcher2` - start one or more watchers\n\n## Configuration\n*taskctl* uses config file (`tasks.yaml` or `taskctl.yaml`) where your tasks and pipelines stored. \nConfig file includes following sections:\n- tasks\n- pipelines\n- watchers\n- contexts\n- variables\n\nConfig file may import other config files, directories or URLs.\n```yaml\nimport:\n- .tasks/database.yaml\n- .tasks/lint/\n- https://raw.githubusercontent.com/taskctl/taskctl/master/docs/example.yaml\n```\n\n### Example\nConfig file [example](https://github.com/taskctl/taskctl/blob/master/docs/example.yaml)\n\n### Global configuration\n*taskctl* has global configuration stored in ``$HOME/.taskctl/config.yaml`` file. It is handy to store system-wide tasks, reusable contexts, defaults etc. \n\n## Tasks\nTask is a foundation of *taskctl*. It describes one or more commands to run, their environment, executors and attributes such as working directory, execution timeout, acceptance of failure, etc.\n```yaml\ntasks:\n    lint:\n        allow_failure: true\n        command:\n          - golint $(go list ./... | grep -v /vendor/)\n          - go vet $(go list ./... | grep -v /vendor/)\n          \n    build:\n        command: go build ./...\n        env: \n          GOOS: linux\n          GOARCH: amd64\n        env_file: /data/.env\n        after: rm -rf tmp/*\n        variations:\n          - GOARCH: amd64\n          - GOARCH: arm\n            GOARM: 7\n```\nTask definition takes following parameters:\n- `command` - one or more commands to run\n- `variations` - list of variations (env variables) to apply to command\n- `context` - execution context's name\n- `env` - environment variables. All existing environment variables will be passed automatically\n- `env_file` - env file in `k=v` format to read variables from\n- `dir` - working directory. Current working directory by default\n- `timeout` - command execution timeout (default: none)\n- `allow_failure` - if set to `true` failed commands will not interrupt execution (default: `false`)\n- `after` - command that will be executed after command completes\n- `before` - command that will be executed before task starts\n- `exportAs` - env variable name to store task's output (default: `TASK_NAME_OUTPUT`, where `TASK_NAME` is actual task's name)\n- `condition` - condition to check before running task\n- `variables` - task's variables\n- `interactive` - if `true` provides STDIN to commands (default: `false`)\n\n### Tasks variables\nEach task, stage and context has variables to be used to render task's fields  - `command`, `dir`.\nAlong with globally predefined, variables can be set in a task's definition.\nYou can use those variables according to `text/template` [documentation](https://golang.org/pkg/text/template/).\n\nPredefined variables are:\n- `.Root` - root config file directory\n- `.Dir` - config file directory\n- `.TempDir` - system's temporary directory\n- `.Args` - provided arguments as a string\n- `.ArgsList` - array of provided arguments\n- `.Task.Name` - current task's name\n- `.Context.Name` - current task's execution context's name\n- `.Stage.Name` - current stage's name\n- `.Output` - previous command's output\n- `.Tasks.Task1.Output` - `task1` last command output\n\nVariables can be used inside task definition. For example:\n```yaml\ntasks:\n    task1:\n        dir: \"{{ .Root }}/some-dir\"\n        command:\n          - echo \"My name is {{ .Task.Name }}\"\n          - echo {{ .Output }} # My name is task1\n          - echo \"Sleep for {{ .sleep }} seconds\"\n          - sleep {{ .sleep | default 10 }}\n          - sleep {{ .sleep }}\n        variables:\n          sleep: 3\n```\n\n### Pass CLI arguments to task\nAny command line arguments succeeding `--` are passed to each task via `.Args`, `.ArgsList` variables or `ARGS` environment variable.\n\nGiven this definition:\n```yaml\nlint1:\n  command: go lint {{.Args}}\n\nlint2:\n  command: go lint {{index .ArgsList 1}}\n```\nthe resulting command is:\n```\n$ taskctl lint1 -- package.go\n# go lint package.go\n\n$ taskctl lint2 -- package.go main.go\n# go lint main.go\n```\n\n### Storing task's output\nTask output automatically stored to the variable named like this - ``.Tasks.TaskName.Output``, where `TaskName` is the actual task's name.\nIt is also stored to `TASK_NAME_OUTPUT` environment variable. It's name can be changed by a task's `exportAs` parameter.\nThose variables will be available to all dependent stages.\n\n### Tasks variations\nTask may run in one or more variations. Variations allows to reuse task with different env variables:\n```yaml\ntasks:\n  build:\n    command:\n      - GOOS=${GOOS} GOARCH=amd64 go build -o bin/taskctl_${GOOS} ./cmd/taskctl\n    env:\n      GOFLAGS: -ldflags=-s -ldflags=-w\n    variations:\n      - GOOS: linux\n      - GOOS: darwin\n      - GOOS: windows\n```\nthis config will run build 3 times with different GOOS\n\n### Task conditional execution\nThe following task will run only when there are any changes that are staged but not committed:\n```yaml\ntasks:\n  build:\n    command:\n      - ...build...\n    condition: git diff --exit-code\n```\n\n## Pipelines\nPipeline is a set of stages (tasks or other pipelines) to be executed in a certain order. Stages may be executed in parallel or one-by-one. \nStage may override task's environment, variables etc. \n\nThis pipeline:\n```yaml\npipelines:\n    pipeline1:\n        - task: start task\n        - task: task A\n          depends_on: \"start task\"\n        - task: task B\n          depends_on: \"start task\"\n        - task: task C\n          depends_on: \"start task\"\n        - task: task D\n          depends_on: \"task C\"\n        - task: task E\n          depends_on: [\"task A\", \"task B\", \"task D\"]\n        - task: finish\n          depends_on: [\"task E\"]    \n```\nwill result in an execution plan like this:\n![execution plan](https://raw.githubusercontent.com/taskctl/taskctl/master/docs/pipeline.svg)\n\nStage definition takes following parameters:\n- `name` - stage name. If not set - referenced task or pipeline name will be used.\n- `task` - task to execute on this stage\n- `pipeline` - pipeline to execute on this stage\n- `env` - environment variables. All existing environment variables will be passed automatically\n- `depends_on` - name of stage on which this stage depends on. This stage will be started only after referenced stage is completed.\n- `allow_failure` - if `true` failing stage will not interrupt pipeline execution. ``false`` by default\n- `condition` - condition to check before running stage\n- `variables` - stage's variables\n\n## Taskctl output formats\nTaskctl has several output formats:\n- `raw` - prints raw commands output\n- `prefixed` - strips ANSI escape sequences where possible, prefixes command output with task's name\n- `cockpit` - tasks dashboard\n\n## Filesystem watchers\nWatcher watches for changes in files selected by provided patterns and triggers task anytime an event has occurred.\n```yaml\nwatchers:\n  watcher1:\n    watch: [\"README.*\", \"pkg/**/*.go\"] # Files to watch\n    exclude: [\"pkg/excluded.go\", \"pkg/excluded-dir/*\"] # Exclude patterns\n    events: [create, write, remove, rename, chmod] # Filesystem events to listen to\n    task: task1 # Task to run when event occurs\n```\n### Patterns\nThanks to [doublestar](https://github.com/bmatcuk/doublestar) *taskctl* supports the following special terms within include and exclude patterns:\n\nSpecial Terms | Meaning\n------------- | -------\n`*`           | matches any sequence of non-path-separators\n`**`          | matches any sequence of characters, including path separators\n`?`           | matches any single non-path-separator character\n`[class]`     | matches any single non-path-separator character against a class of characters ([details](https://github.com/bmatcuk/doublestar/blob/master/README.md#character-classes))\n`{alt1,...}`  | matches a sequence of characters if one of the comma-separated alternatives matches\n\nAny character with a special meaning can be escaped with a backslash (`\\`).\n\n## Contexts\nContexts allow you to set up execution environment, variables, binary which will run your task, up/down commands etc.\n```yaml\ncontexts:\n  local:\n    executable:\n      bin: /bin/zsh\n      args:\n        - -c\n    env:\n      VAR_NAME: VAR_VALUE\n    variables:\n      sleep: 10\n    quote: \"'\" # will quote command with provided symbol: \"/bin/zsh -c 'echo 1'\"\n    before: echo \"I'm local context!\"\n    after: echo \"Have a nice day!\"\n```\n\nContext has hooks which may be triggered once before first context usage or every time before task with this context will run.\n```yaml\ncontext:\n    docker-compose:\n      executable:\n        bin: docker-compose\n        args: [\"exec\", \"api\"]\n      up: docker-compose up -d api\n      down: docker-compose down api\n\n    local:\n      after: rm -rf var/*\n```\n\n### Docker context\n```yaml\n  alpine:\n    executable:\n      bin: /usr/local/bin/docker\n      args:\n        - run\n        - --rm\n        - alpine:latest\n    env:\n      DOCKER_HOST: \"tcp://0.0.0.0:2375\"\n    before: echo \"SOME COMMAND TO RUN BEFORE TASK\"\n    after: echo \"SOME COMMAND TO RUN WHEN TASK FINISHED SUCCESSFULLY\"\n\ntasks:\n  mysql-task:\n    context: alpine\n    command: uname -a\n```\n\n## Embeddable task runner\n*taskctl* may be embedded into any go program. \nAdditional information may be found on taskctl's [pkg.go.dev](https://pkg.go.dev/github.com/taskctl/taskctl?tab=overview) page\n\n### Runner\n```go\nt := task.FromCommands(\"go fmt ./...\", \"go build ./..\")\nr, err := NewTaskRunner()\nif err != nil {\n    return\n}\nerr  = r.Run(t)\nif err != nil {\n    fmt.Println(err, t.ExitCode, t.ErrorMessage())\n}\nfmt.Println(t.Output())\n```\n\n### Scheduler\n```go\nformat := task.FromCommands(\"go fmt ./...\")\nbuild := task.FromCommands(\"go build ./..\")\nr, _ := runner.NewTaskRunner()\ns := NewScheduler(r)\n\ngraph, err := NewExecutionGraph(\n    \u0026Stage{Name: \"format\", Task: format},\n    \u0026Stage{Name: \"build\", Task: build, DependsOn: []string{\"format\"}},\n)\nif err != nil {\n    return\n}\n\nerr = s.Schedule(graph)\nif err != nil {\n    fmt.Println(err)\n}\n```\n\n## FAQ\n### How does it differ from go-task/task?\nIt's amazing how solving same problems lead to same solutions. *taskctl* and go-task have a lot of concepts in common but also have some differences. \n1. Main is pipelines. Pipelines and stages allows more precise workflow design because same tasks may have different dependencies (or no dependencies) in different scenarios.\n2. Contexts allow you to set up execution environment and binary which will run your task.\n\n## Autocomplete\n### Bash\nAdd to  ~/.bashrc or ~/.profile\n```\n. \u003c(taskctl completion bash)\n```\n\n### ZSH\nAdd to  ~/.zshrc\n```\n. \u003c(taskctl completion zsh)\n```\n### Similar projects\n- [GNU Make](https://github.com/mirror/make)\n- [go-task/task](https://github.com/go-task/task)\n- [mage](https://github.com/magefile/mage)\n- [tusk](https://github.com/rliebz/tusk)\n- [just](https://github.com/casey/just)\n- [cr](https://github.com/cirocosta/cr)\n- [realize](https://github.com/oxequa/realize)\n\n## How to contribute?\nFeel free to contribute in any way you want. Share ideas, submit issues, create pull requests. \nYou can start by improving this [README.md](https://github.com/taskctl/taskctl/blob/master/README.md) or suggesting new [features](https://github.com/taskctl/taskctl/issues)\nThank you! \n\n## License\nThis project is licensed under the GNU GPLv3 - see the [LICENSE.md](LICENSE.md) file for details\n\n## Authors\n - Yevhen Terentiev - [trntv](https://github.com/trntv)\nSee also the list of [contributors](https://github.com/taskctl/taskctl/contributors) who participated in this project.\n","funding_links":[],"categories":["Build Automation","构建自动化","Repositories","Go","工具库","工具库`可以提升效率的通用代码库和工具`","Uncategorized","Utilities"],"sub_categories":["查询语","Contents","HTTP Clients"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaskctl%2Ftaskctl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaskctl%2Ftaskctl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaskctl%2Ftaskctl/lists"}