{"id":13453158,"url":"https://github.com/wagoodman/bashful","last_synced_at":"2025-05-15T21:08:12.957Z","repository":{"id":25389985,"uuid":"103874950","full_name":"wagoodman/bashful","owner":"wagoodman","description":"Use a yaml file to stitch together commands and bash snippits and run them with a bit of style.  Why? Because your bash script should be quiet and shy-like (...and not such a loud mouth). ","archived":false,"fork":false,"pushed_at":"2022-03-20T17:08:43.000Z","size":4178,"stargazers_count":1163,"open_issues_count":25,"forks_count":47,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-08T13:43:13.072Z","etag":null,"topics":["bash","build-tool","golang","installer","parallel-processing","pretty","progress-bar","yaml"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wagoodman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-18T01:04:55.000Z","updated_at":"2025-05-07T10:18:02.000Z","dependencies_parsed_at":"2022-08-07T11:15:38.793Z","dependency_job_id":null,"html_url":"https://github.com/wagoodman/bashful","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbashful","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbashful/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbashful/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbashful/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wagoodman","download_url":"https://codeload.github.com/wagoodman/bashful/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254422790,"owners_count":22068679,"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":["bash","build-tool","golang","installer","parallel-processing","pretty","progress-bar","yaml"],"created_at":"2024-07-31T08:00:33.853Z","updated_at":"2025-05-15T21:08:12.389Z","avatar_url":"https://github.com/wagoodman.png","language":"Go","readme":"# bashful\n\n[![Travis CI](https://api.travis-ci.org/wagoodman/bashful.svg?branch=master)](https://travis-ci.org/wagoodman/bashful) [![Go Report Card](https://goreportcard.com/badge/github.com/wagoodman/bashful)](https://goreportcard.com/report/github.com/wagoodman/bashful)\n\n**This is beta quality!** Use at your own risk.\n\nUse a yaml file to stitch together commands and bash snippets and run them with a bit of style. \nWhy? Because your bash script should be quiet and shy-like (...and not such a loud mouth). \n\n![Image](.data/demo.gif)\n\n*\"But why would you make this monstrosity?\"* you ask... because ` \u0026\u003e/dev/null` and ` | tee -a some.log` and `set -e; do something; set +e` and other similar things is getting annoying. And besides... why shouldn't your bash script output look pretty?\n\n**Features:**\n- [x] Run bash snippits ('tasks') in series or parallel\n- [x] A nice vertical progress bar to show current task status (with inline realtime stdout/stderr)\n- [x] Download url references to bash scripts and executables\n- [x] Bundle set of scripts and listed resources into a single simi-portable executable\n- [x] Log all task stdout/stderr to a log file\n- [x] ETA for running tasks (that have already been run before)\n- [x] Configuration yaml block to control the behavior/look \u0026 feel\n- [x] Detailed error reports when commands fail\n- [x] Control which failing command should halt execution\n\n## Installation\n\n**Ubuntu/Debian**\n```bash\nwget https://github.com/wagoodman/bashful/releases/download/v0.0.10/bashful_0.0.10_linux_amd64.deb\nsudo apt install ./bashful_0.0.10_linux_amd64.deb\n```\n\n**RHEL/Centos**\n```bash\nwget https://github.com/wagoodman/bashful/releases/download/v0.0.10/bashful_0.0.10_linux_amd64.rpm\nrpm -i bashful_0.0.10_linux_amd64.rpm\n```\n\n**Mac**\n```bash\nbrew tap wagoodman/bashful\nbrew install bashful\n```\nor download a Darwin build from the releases page.\n\n**Go tools**\n```bash\ngo get github.com/wagoodman/bashful\n```\n\n## Getting Started\n**There are a ton of examples in the [`example/`](https://github.com/wagoodman/bashful/tree/master/example) dir**, but here are a few:\n\n**1. The simplest of examples:**\n```yaml\ntasks:\n    - cmd: echo \"Hello, World!\"\n```\nTo run it:\n```bash\nbashful run hello.yaml\n```\n\n**2. A more realistic example: a build and deployment description**\n```yaml\n# ci.yaml\ntasks:\n    - name: Building app\n      cmd: go build -ldflags '-linkmode external -extldflags -static -s'\n      tags: build\n\n    - name: Packaging app\n      cmd: docker build -t my-awesome-app:v1 .\n      tags: build\n\n    - name: Publishing image\n      cmd: docker push my-awesome-app:v1\n      tags: deploy\n\n    - name: Deploying app\n      cmd: kubectl run my-awesome-app --image=docker.io/wagoodman/my-awesome-app:v1 --pt=80\n      tags: deploy\n```\n\nRun all of the tasks...\n```bash\nbashful run ci.yaml\n```\n\n...Or run just the build steps:\n```bash\nbashful run ci.yaml --tags build\n```\n\n**3. Have an installer run things in parallel...**\n```yaml\n# install.yaml\ntasks:\n    - name: Installing bridgy\n      parallel-tasks: \n        - cmd: sudo apt-get install -y tmux sshfs\n        - cmd: pip install --user bridgy\n```\n\n...Or make an installer that downloads and runs everything it needs:\n```yaml\n# install.yaml\ntasks:\n    # The given url gets executed by default\n    - name: Installing Cuda and Bazel\n      url: https://raw.githubusercontent.com/jasimpson/tensorflow-on-aws/master/toa_part_1of2.sh\n\n    # Or you can control how the url asset (\u003cexec\u003e) gets used\n    - name: Installing Tensorflow\n      url: https://raw.githubusercontent.com/jasimpson/tensorflow-on-aws/master/toa_part_2of2.sh\n      cmd: source ~/.bashrc \u0026\u0026 \u003cexec\u003e\n```\n\nPackage up the installed into a single executable and give it to someone else to run (must be the same architecture and OS type):\n```bash\nbashful bundle install.yaml\n# now you have a new executable called \"install.bundle\", which can simply be executed\n./install.bundle\n```\n*Note: the bundle feature is pretty experimental right now.*\n\nYou can even persist environment variables across tasks:\n```yaml\ntasks:\n  - cmd: export VAR1=isnowset\n  - cmd: eval \"export VAR2=isnowreallyset\"\n  - cmd: echo ${VAR1} ${VAR2}\n```\n*Note: you cannot persist environment variables from a parallel step.*\n\n\n**4. Include other yaml files in your bashful run.yaml.**\nThis way you can centralize your common yaml snippets for reusability:\n\n```yaml\n# run.yaml\n\n$include: example/common-config.yml\n\nx-reference-data:\n  all-apps: \u0026app-names\n    - $include example/common-apps.yml\n\ntasks:\n\n  - name: Cloning Repos\n    parallel-tasks:\n      - name: \"Cloning \u003creplace\u003e\"\n        cmd: example/scripts/random-worker.sh 2 \u003creplace\u003e\n        ignore-failure: true\n        for-each: *app-names\n\n  - name: Building Repos\n    parallel-tasks:\n      - name: \"Building \u003creplace\u003e\"\n        cmd: example/scripts/random-worker.sh 1 \u003creplace\u003e\n        ignore-failure: true\n        for-each: *app-names\n\n```\n\n```yaml\n# example/common-config.yml\n\nconfig:\n  show-failure-report: false\n  show-summary-errors: true\n  max-parallel-commands: 6\n  show-task-times: true\n```\n\n```yaml\n# example/common-apps.yml\n\n- some-lib-4\n- utilities-lib\n- important-lib\n- some-app1\n- some-app3\n```\n\nWill generate:\n```yaml\nconfig:\n    show-failure-report: false\n    show-summary-errors: true\n    max-parallel-commands: 6\n    show-task-times: true\n\nx-reference-data:\n  all-apps: \u0026app-names\n    - some-lib-4\n    - utilities-lib\n    - important-lib\n    - some-app1\n    - some-app3\n\ntasks:\n\n  - name: Cloning Repos\n    parallel-tasks:\n      - name: \"Cloning \u003creplace\u003e\"\n        cmd: example/scripts/random-worker.sh 2 \u003creplace\u003e\n        ignore-failure: true\n        for-each: *app-names\n\n  - name: Building Repos\n    parallel-tasks:\n      - name: \"Building \u003creplace\u003e\"\n        cmd: example/scripts/random-worker.sh 1 \u003creplace\u003e\n        ignore-failure: true\n        for-each: *app-names\n```\n\n**5. Pass arbitrary arguments to jobs.**\n\n```\n$ bashful run some.yaml first-argument 20\n```\n\nWhich can be used as bash `$#` parameters (in this case `$1` and `$2`):\n```yaml\ntasks:\n    - name: Show some stuff!\n      cmd: echo $1\n    - name: Show some other stuff!\n      cmd: echo $2\n```\n\n**There are a ton of examples in the [`example/`](https://github.com/wagoodman/bashful/tree/master/example) dir.** Go check them out!\n\n## Configuration Options\nHere is an exhaustive list of all of the config options (in the `config` yaml block). These options\nare global options that apply to all tasks within the yaml file:\n```yaml\n\n# this block is used to configure the look, feel, and behavior of all tasks\nconfig:\n    # which character used to delimintate the task list\n    bullet-char: \"-\"\n\n    # hide all child tasks after task section completion\n    collapse-on-completion: false\n\n    # change the colors of the vertical progress bar for a task in a particular state.\n    # this should be a number from the 256 color palette.\n    success-status-color: 10\n    running-status-color: 22\n    pending-status-color: 22\n    error-status-color: 160\n\n    # by default the screen is updated when an event occurs (when stdout from\n    # a running process is read). This can be changed to only allow the \n    # screen to be updated on an interval (to accomodate slower devices).\n    event-driven: false\n\n    # This is the character/string that is replaced in the cmd section of a task to reference a downloaded url\n    exec-replace-pattern: '\u003cexec\u003e'\n\n    # the number of tasks that can run simultaneously\n    max-parallel-commands: 4\n\n    # log all task output and events to the given logfile\n    log-path: path/to/file.log\n\n    # show/hide the detailed summary of all task failures after completion\n    show-failure-report: true\n\n    # show/hide the last summary line (showing % complete, number of tasks ran, eta, etc)\n    show-summary-footer: true\n\n    # show/hide the number of tasks that have failed in the summary footer line\n    show-summary-errors: false\n\n    # show/hide the number of tasks completed thus far on the summary footer line\n    show-summary-steps: true\n\n    # show/hide the eta and runtime figures on the summary footer line\n    show-summary-times: false\n\n    # globally enable/disable showing the stdout/stderr of each task\n    show-task-output: true\n\n    # Show an eta for each task on the screen (being shown on every line with a command running)\n    show-task-times: true\n\n    # Show only one line of output to the screen (instead of a line per task + a summary line)\n    single-line: true\n\n    # globally enable/disable haulting further execution when any one task fails\n    stop-on-failure: true\n\n    # This is the character/string that is replaced with items listed in the 'for-each' block\n    replica-replace-pattern: '\u003creplace\u003e'\n\n    # time in milliseconds to update each task on the screen (polling interval)\n    update-interval: 250\n```\n\nThe `tasks` block is an ordered list of processes to run. Each task has several options that can be configured:\n```yaml\ntasks:\n    - name: my awesome command      # a title for the task\n      cmd: echo \"woot\"              # the command to be ran (required)\n      \n      collapse-on-completion: false # hide all defined 'parallel-tasks' after completion\n      event-driven: true            # use a event driven or polling mechanism for displaying task stdout\n      ignore-failure: false         # do not register any non-zero return code as a failure (this task will appear to never fail)\n      show-output: true             # show task stdout to the screen\n      stop-on-failure: true         # indicate if the application should continue if this cmd fails \n      \n      parallel-tasks: ...           # a list of tasks that should be performed concurrently\n      \n      for-each: ...                 # a list of parameters used to duplicate this task\n      \n      url: http://github.com/somescript.sh # download this url and execute it\n      md5: ae8abe98aeb389ae8b39e3434bbc    # an expected md5 checksum of the url provided\n\n      tags: something               # one or more 'tags' that can be used to execute a sub-selection of tasks within a run yaml\n      tags:                         # e.g. 'bashful run some.yaml --tags      something' \n        - something                 #      'bashful run some.yaml --tags      something,else'\n        - else                      #      'bashful run some.yaml --only-tags something'\n```\n\n**There are a ton of examples in the [`example/`](https://github.com/wagoodman/bashful/tree/master/example) dir.** Go check them out!\n\n## Runtime Options\n```\nUSAGE:\n   bashful run [options] \u003cpath-to-yaml-file\u003e\n   bashful bundle \u003cpath-to-yaml-file\u003e\n\nCOMMANDS:\n     bundle   Bundle yaml and referenced url resources into a single executable\n     run      Execute the given yaml\n\nBUNDLE OPTIONS:\n    None\n\nRUN OPTIONS:\n   --tags value       A comma delimited list of matching task tags. \n                      If a task's tag matches *or if it is not tagged* then it will be executed (also see --only-tags).\n   --only-tags value  A comma delimited list of matching task tags. A task will only be executed if it has a matching tag.\n\nGLOBAL OPTIONS:\n   --help, -h     show help\n   --version, -v  print the version\n```\n\n## Wish list\nAll feature requests are welcome! \n- [ ] at least 70% test coverage\n- [ ] truly cross platform (windows)\n- [ ] Multiple (serial) commands for a single task (`cmd: [run something, run another thing]`)\n- [ ] Multiple url references for a single task (`url: [https://someurl.com/some-script.sh, https://anotherurl.com/another-script.sh]`)\n- [ ] Allow parallel tasks within parallel tasks (really just allow deeper nesting of any kind of task)\n- [ ] Interact with the mouse to see more/less tasks (https://godoc.org/github.com/nsf/termbox-go#Event)\n","funding_links":[],"categories":["Go","bash"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwagoodman%2Fbashful","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwagoodman%2Fbashful","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwagoodman%2Fbashful/lists"}