{"id":13582495,"url":"https://github.com/lunarway/shuttle","last_synced_at":"2025-03-22T04:07:04.590Z","repository":{"id":33808415,"uuid":"150251577","full_name":"lunarway/shuttle","owner":"lunarway","description":"CLI for handling shared build and deploy tools between projects no matter what technologies the projects are using","archived":false,"fork":false,"pushed_at":"2024-09-16T12:57:35.000Z","size":2602,"stargazers_count":140,"open_issues_count":15,"forks_count":14,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-09-16T14:06:30.570Z","etag":null,"topics":["cli","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lunarway.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":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-25T11:03:16.000Z","updated_at":"2024-09-16T12:39:08.000Z","dependencies_parsed_at":"2024-04-16T19:56:20.428Z","dependency_job_id":"c7f213be-004b-414d-9d6b-52656a1c0c93","html_url":"https://github.com/lunarway/shuttle","commit_stats":null,"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lunarway%2Fshuttle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lunarway%2Fshuttle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lunarway%2Fshuttle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lunarway%2Fshuttle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lunarway","download_url":"https://codeload.github.com/lunarway/shuttle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244902932,"owners_count":20529115,"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":["cli","golang"],"created_at":"2024-08-01T15:02:46.212Z","updated_at":"2025-03-22T04:07:04.572Z","avatar_url":"https://github.com/lunarway.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/lunarway/shuttle\"\u003e\n    \u003cimg src=\"docs/logo.png\" alt=\"Shuttle logo\"\u003e\n  \u003c/a\u003e\n\n\u003cp align=\"center\"\u003e\n    A CLI for handling shared build and deploy tools between many projects no matter what technologies the project is using.\n    \u003cbr\u003e\n    \u003ca href=\"https://github.com/lunarway/shuttle/issues/new?template=bug.md\"\u003eReport bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/lunarway/shuttle/issues/new?template=feature.md\u0026labels=feature\"\u003eRequest feature\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/lunarway/shuttle/releases\"\u003eReleases\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/lunarway/shuttle/releases/latest\"\u003eLatest release\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n## Table of contents\n\n- [What is shuttle?](#what-is-shuttle)\n- [Status](#status)\n- [How?](#how)\n- [Features](#features)\n- [Documentation](#documentation)\n- [Installing](#installing)\n- [Functions](#functions)\n- [Release History](#release-history)\n\n## What is shuttle?\n\n`shuttle` is a CLI for handling shared build and deploy tools between many\nprojects no matter what technologies the project is using.\n\n## Status\n\n_DISCLAIMER: shuttle is in beta, so stuff may change. However we are using\nshuttle heavily at Lunar Way and we use it to deploy to production, so it is\npretty battle proven._\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/lunarway/shuttle)](https://goreportcard.com/report/github.com/lunarway/shuttle)\n\n## How?\n\nProjects that use `shuttle` are always referencing a `shuttle plan`. A plan\ndescribes what can be done with shuttle. Fx:\n\n```yaml\n# plan.yaml file\nscripts:\n  build:\n    description: Build the docker image\n    args:\n      - name: tag\n        required: true\n    actions:\n      - shell: docker -f $plan/Dockerfile build -t $(shuttle get docker.image):$tag\n  test:\n    description: Run test for the project\n    actions:\n      - shell: go test\n```\n\nThe `plan.yaml` is located at the root of the plan directory which is located\nelsewhere of the actual project using it. The plan directory can be locally\nstored or in a git repository. The directory structure could be something like:\n\n```sh\nworkspace\n│\n└───moon-base          # project\n│   │   shuttle.yaml   # project specific shuttle.yaml file\n│   │   main.go\n│\n└───station-plan       # plan to be shared by projects\n    │   plan.yaml\n    │   Dockerfile\n```\n\nTo use a plan a project must specify the `shuttle.yaml` file:\n\n```yaml\nplan: ../the-plan\nvars:\n  docker:\n    image: earth-united/moon-base\n```\n\nWith this in place a docker image can be built:\n\n```sh\n$ cd workspace/moon-base\n$ shuttle run build tag=v1\n```\n\nYou can also put your `plan.yaml` in a different git repository, and then\nreference it from your `shuttle.yaml`:\n\n```\n# shuttle.yaml\nplan: git://git@github.com:lunarway/station-plan.git\n```\n\n## Features\n\n- Fetch shuttle plans from git repositories\n- Create any script you like in the plan\n- Overwrite scripts in local projects when they defer from the plan\n- Write templates in plans and overwrite them in projects when they defer\n- ...\n\n### Golang actions \n\nExecute golang directly from shuttle, replacing shell scripts with a more thoroghly engineered Developer Experience.\n\n```sh\nworkspace\n│\n└───moon-base          # project\n│   │───actions        # golang actions\n│   │   │   go.mod     # shuttle run build script file as golang code\n│   │   │   build.go\n│   │   shuttle.yaml   # project specific shuttle.yaml file\n│   │   main.go\n│\n└───station-plan       # plan to be shared by projects\n│   │───actions        # golang plan actions\n│   │   │   go.mod     \n│   │   │   build.go\n    │   plan.yaml\n    │   Dockerfile\n```\n\nsee [golang actions](./docs/features/golang-actions.md)\n\n### Telemetry\n\nsee [telemetry](./docs/features/telemetry.md)\n\n## Documentation\n\nPlan documentation can be inspected using the `shuttle documentation` command.\n\nWhen writing shuttle plans you can hint as to where to find documentation for\nthe plan. Users of the plan will open the specified URL when requesting\ndocumentation.\n\n```yaml\n# plan.yaml\ndocumentation: https://docs.my-corp.com\n```\n\nIf no specific `documentation` field is set in the plan it will be inferred from\nthe plan reference. In below example shuttle will open\n`https://github.com/lunarway/shuttle-example-go-plan.git`\n\n```yaml\n# shuttle.yaml\nplan: git://git@github.com:lunarway/shuttle-example-go-plan.git\n```\n\n### Git Plan\n\nSpecify the protocol to use for pulling the remote repository using either\n`https://` for HTTPS, or `git://` for SSH:\n\n- `https://github.com/lunarway/shuttle-example-go-plan.git`\n- `git://git@github.com:lunarway/shuttle-example-go-plan.git`\n\nChoose a specific branch to use:\n\n- `https://github.com/lunarway/shuttle-example-go-plan.git#change-build`\n- `git://git@github.com:lunarway/shuttle-example-go-plan.git#change-build`\n\nThe `#change-build` points the plan to a specific branch, which by default would\nbe `master`.\n\nIt can also be used to point to a tag or a git SHA, like this:\n\n- `https://github.com/lunarway/shuttle-example-go-plan.git#v1.2.3`\n- `git://git@github.com:lunarway/shuttle-example-go-plan.git#46ce3cc`\n\n#### Caching\n\nBy default shuttle will pull the upstream plan on every pull. To prevent this\nyou can use\n\n```bash\nexport SHUTTLE_CACHE_DURATION_MIN=60 # Cache a plan for 60 minutes\n```\n\nThis feature caches pr. repo, as such the cache isn't shared between working\nrepositories.\n\n### Overloading the plan\n\nIt is possible to overload the plan specified in `shuttle.yaml` file by using\nthe `--plan` argument or the `SHUTTLE_PLAN_OVERLOAD` environment variable.\nFollowing arguments are supported\n\n- A path to a local plan like `--plan ../local-checkout-of-plan`. Absolute paths\n  is also supported\n- Another git plan like `--plan git://github.com/some-org/some-plan`\n- A git tag to append to the plan like `--plan #some-branch`, `--plan #some-tag`\n  or a SHA `--plan #2b52c21`\n\n## Installing\n\n### Mac OS\n\n```console\ncurl -LO https://github.com/lunarway/shuttle/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/lunarway/shuttle/releases/latest | grep -o '[^/]*$')/shuttle-darwin-amd64\nchmod +x shuttle-darwin-amd64\nsudo mv shuttle-darwin-amd64 /usr/local/bin/shuttle\n```\n\n#### Mac OS Sonoma (broke grep)\n\nUse ripgrep instead (rg)\n\n```console\ncurl -LO https://github.com/lunarway/shuttle/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/lunarway/shuttle/releases/latest | rg -o '[^/]*$')/shuttle-darwin-amd64\nchmod +x shuttle-darwin-amd64\nsudo mv shuttle-darwin-amd64 /usr/local/bin/shuttle\n```\n\n### Linux\n\n```console\ncurl -LO https://github.com/lunarway/shuttle/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/lunarway/shuttle/releases/latest | grep -o '[^/]*$')/shuttle-linux-amd64\nchmod +x shuttle-linux-amd64\nsudo mv shuttle-linux-amd64 /usr/local/bin/shuttle\n```\n\n### GitHub Actions\n\nShuttle can be installed on your GitHub Runner by adding this line to your\nworkflow:\n\n```\n- use: lunarway/shuttle\n```\n\nAfter this point you can use shuttle in the scripts in your workflow job.\n\n## Functions\n\n### `shuttle get \u003cvariable\u003e`\n\nUsed to get a variable defined in shuttle.yaml\n\n```console\n$ shuttle get some.variable\n\u003e some variable content\n\n$ shuttle get does.not.exist\n\u003e # nothing\n```\n\n### `shuttle plan`\n\nInspect the plan in use for a project. Use the `template` flag to customize the\noutput to your needs.\n\n```console\n$ shuttle plan\nhttps://github.com/lunarway/shuttle-example-go-plan.git\n```\n\n### `shuttle has \u003cvariable\u003e`\n\nIt is possible to easily check if a variable or script is defined\n\n```console\nshuttle has some.variable\nshuttle has --script integration\n```\n\nOutput is either statuscode=0 if variable is found or statuscode=1 if variables\nisn't found. The output can also be a stdout boolean like\n\n```console\n$ shuttle has my.docker.image --stdout\n\u003e false\n```\n\n### Template functions\n\nThe `template` command along with commands taking a `--template` flag has\nmultiple templating functions available. The\n[masterminds/sprig](http://masterminds.github.io/sprig) v3.2.2 functions are\navailable along with those described below.\n\nExamples are based on the below `shuttle.yaml` file.\n\n| Function                      | Description                                                                                                                                                             | Example                                                                 | Output                            |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------- |\n| `array \u003cpath\u003e \u003cvalue\u003e`        | Get array from path. If value is a map, the values of the map is returned in deterministic order.                                                                       | `array \"args\" .`                                                        | `helloworld`                      |\n| `fileExists \u003cfile-path\u003e`      | Returns whether a file exists.                                                                                                                                          | `fileExists \".gitignore\"`                                               | `true`                            |\n| `fromYaml \u003cvalue\u003e`            | Unmarshal YAML string to a `map[string]interface{}`. In case of YAML parsing errors the `Error` key in the result contains the error message. See notes below on usage. | `fromYaml \"api: v1\"`                                                    | `map[api:v1]`                     |\n| `get \u003cpath\u003e \u003cvalue\u003e`          | Get a value from a field path. `.` is read as nested nested objects                                                                                                     | `get \"docker.image\" .`                                                  | `earth-united/moon-base`          |\n| `getFileContent \u003cfile-path\u003e`  | Get raw contents of a file.                                                                                                                                             | `getFileContent \".gitignore\"`                                           | `dist/`\u003cbr\u003e `vendor/`\u003cbr\u003e `...`   |\n| `getFiles \u003cdirectory-path\u003e`   | Returns a slice of files in the provided directory as [`os.FileInfo`](https://golang.org/pkg/os/#FileInfo) structs.                                                     | `{{ range $i, $f := (getFiles \"./\") }}{{ .Name }} {{ end }}`            | `.git .gitignore ...`             |\n| `int \u003cpath\u003e \u003cvalue\u003e`          | Get int value without formatting. Note that this is a direct `int` cast ie. value `1.2` will generate an error.                                                         | `int \"replicas\" .`                                                      | `1`                               |\n| `is \u003cvalue-a\u003e \u003cvalue-b\u003e`      | Equality indication by Go's `==` comparison.                                                                                                                            | `is \"foo\" \"bar\"`                                                        | `false`                           |\n| `isnt \u003cvalue-a\u003e \u003cvalue-b\u003e`    | Inequality indication by Go's `!=` comparison.                                                                                                                          | `isnt \"foo\" \"bar\"`                                                      | `true`                            |\n| `objectArray \u003cpath\u003e \u003cvalue\u003e`  | Get object key-value pairs from path. Each key-value is returned in a `{ Key Value}` object.                                                                            | `{{ range objectArray \"docker\" . }}{{ .Key }} -\u003e {{ .Value }}{{ end }}` | `image -\u003e earth-united/moon-base` |\n| `rightPad \u003cstring\u003e \u003cpadding\u003e` | Add space padding to the right of a string.                                                                                                                             | `{{ rightPad \"padded\" 10 }}string`                                      | `padded string`                   |\n| `strConst \u003cvalue\u003e`            | Convert string to upper snake casing converting `.` to `_`.                                                                                                             | `strConst \"a.value\"`                                                    | `A_VALUE`                         |\n| `string \u003cpath\u003e \u003cvalue\u003e`       | Format any value as a string.                                                                                                                                           | `string \"replicas\" .`                                                   | `\"1\"`                             |\n| `toYaml \u003cvalue\u003e`              | Marshal value to YAML. In case of non-parsable string an empty string is returned. See notes below on usage.                                                            | `toYaml (get \"args\" .)`                                                 | `- hello`\u003cbr\u003e `- world`           |\n| `trim \u003cstring\u003e`               | Trim leading and trailing whitespaces. Uses [`strings.TrimSpace`](https://golang.org/pkg/strings/#TrimSpace).                                                           | `trim \" a string \"`                                                     | `a string`                        |\n| `upperFirst \u003cstring\u003e`         | Upper case first character in string.                                                                                                                                   | `upperFirst \"a string\"`                                                 | `A string`                        |\n\n```yaml\nplan: ../the-plan\nvars:\n  docker:\n    image: earth-united/moon-base\n  replicas: 1\n  args:\n    - hello\n    - world\n```\n\n**Notes on YAML parsers**: The `toYaml` and `fromYaml` template functions are\nintented to be used inside file templates (not `template` flags). Because of\nthis they ignore errors and some YAML documents canont be parsed.\n\n## Release History\n\nSee the [releases](https://github.com/lunarway/shuttle/releases) for more\ninformation on changes between releases.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flunarway%2Fshuttle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flunarway%2Fshuttle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flunarway%2Fshuttle/lists"}