{"id":16307086,"url":"https://github.com/fujiwara/stretcher","last_synced_at":"2025-04-07T06:08:40.588Z","repository":{"id":23266504,"uuid":"26624970","full_name":"fujiwara/stretcher","owner":"fujiwara","description":"Deployment tool with consul/serf event notification.","archived":false,"fork":false,"pushed_at":"2024-06-04T04:43:27.000Z","size":2837,"stargazers_count":245,"open_issues_count":0,"forks_count":22,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-10-11T21:12:41.664Z","etag":null,"topics":["consul","deployment","go","golang","kayac","serf","stretcher"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"LarryMad/recipes","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fujiwara.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"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},"funding":{"github":["fujiwara"]}},"created_at":"2014-11-14T06:08:44.000Z","updated_at":"2024-07-24T09:01:00.000Z","dependencies_parsed_at":"2024-06-04T02:55:59.691Z","dependency_job_id":"ce45f7a0-b23c-4aaa-a2df-c5704278fdbb","html_url":"https://github.com/fujiwara/stretcher","commit_stats":{"total_commits":156,"total_committers":11,"mean_commits":"14.181818181818182","dds":"0.14102564102564108","last_synced_commit":"d520cda7e764ad41562a6f9270a8978c8171b84a"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fujiwara%2Fstretcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fujiwara%2Fstretcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fujiwara%2Fstretcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fujiwara%2Fstretcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fujiwara","download_url":"https://codeload.github.com/fujiwara/stretcher/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601448,"owners_count":20964864,"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":["consul","deployment","go","golang","kayac","serf","stretcher"],"created_at":"2024-10-10T21:12:27.612Z","updated_at":"2025-04-07T06:08:40.372Z","avatar_url":"https://github.com/fujiwara.png","language":"Go","funding_links":["https://github.com/sponsors/fujiwara"],"categories":[],"sub_categories":[],"readme":"Stretcher\n=========\n\nA deployment tool with [Consul](https://consul.io) / [Serf](https://www.serfdom.io/) event.\n\n## Example manifest\n\n```yml\nsrc: s3://example.com/app.tar.gz\nchecksum: e0840daaa97cd2cf2175f9e5d133ffb3324a2b93\ndest: /home/stretcher/app\ncommands:\n  pre:\n    - echo 'staring deploy'\n  post:\n    - echo 'deploy done'\n  success:\n    - echo 'deploy success'\n  failure:\n    - echo 'deploy failed!!'\n    - cat \u003e\u003e /path/to/failure.log\nexcludes:\n  - \"*.pid\"\n  - \"*.socket\"\n```\n\n## Run\n\n### stretcher agent\n\n```\n$ stretcher -h\nUsage of stretcher:\n  -max-bandwidth string\n        max bandwidth for download src archives (Bytes/sec)\n  -random-delay float\n        sleep [0,random-delay) sec on start\n  -retry int\n        retry count for download src archives\n  -retry-wait int\n        wait for retry download src archives (sec) (default 3)\n  -rsync-verbose string\n        rsync verbose option (default -v)\n  -timeout int\n        timeout for download src archives (sec)\n  -v    show version\n  -version\n        show version\n```\n\n#### with Consul\n\nA stretcher agent is designed as running under \"consul watch\" and will be kicked by [Consul](https://consul.io) event.\n\n```\n$ consul watch -type event -name deploy /path/to/stretcher\n```\n\n* `-name`: your deployment identity name.\n\n#### with Serf\n\nA stretcher agent can be running as [Serf](https://www.serfdom.io/) event handler.\n\n```\n$ serf agent -event-handler=\"user:deploy=/path/to/stretcher \u003e\u003e /path/to/stretcher.log 2\u003e\u00261\"\n```\n\n#### Load AWS credentials\n\nWhen you specify a S3 URL in the manifest, requires AWS regions and credentials configuration as the same of aws-sdk-go.\n\nfor regions,\n1. `AWS_REGION` or `AWS_DEFAULT_REGION` environment variable.\n\nfor credentials,\n1. Environment variables.\n1. Shared credentials file.\n1. If your application is running on an Amazon EC2 instance, IAM role for Amazon EC2.\n\nSee also [Configuring the AWS SDK for Go](https://docs.aws.amazon.com/ja_jp/sdk-for-go/v1/developer-guide/configuring-sdk.html).\n\n#### Load GCP credentials\n\nWhen you specify a GS(Google Cloud Storage) URL in the manifest, requires a GCP credential setting one of below.\n\n- ServiceAccount\n  - requires `GOOGLE_APPLICATION_CREDENTIALS=[PATH]` environment variable.\n  - Replace [PATH] with the file path of the JSON file that contains your service account key.\n- DefaultAccount\n  - If the environment variable isn't set, load the default service account that Compute Engine provide, for applications that run on those services.\n\n### Deployment process\n\n#### Preparing\n\nThis process is not included in a stretcher agent.\n\n1. Create a tar(or tar.gz) archive for deployment.\n2. Upload the archive file to remote server (S3 or HTTP(S)).\n3. Create a manifest file (YAML) and upload it to remote server.\n\n#### Executing with Consul\n\nCreate a consul event to kick stretcher agents.\n\n```\n$ consul event -name [event_name] [manifest_url]\n```\n\n```\n$ consul event -name deploy s3://example.com/deploy-20141117-112233.yml\n```\n\n  * `-name`: consul event name (specified by consul watch `-name`)\n\n#### Executing with Serf\n\nCreate a serf user event to kick stretcher agents.\n\n```\n$ serf event [event_name] [manifest_url]\n```\n\n```\n$ serf event deploy s3://example.com/deploy-20141117-112233.yml\n```\n\n  * event_name: user event name (specified by serf event handler).\n\n#### Executing as command\n\nStretcher can read a manifest URL from stdin simply.\n\n```\n$ echo s3://example.com/deploy-20141117-112233.yml | stretcher\n```\n\nYou can execute stretcher via ssh or any other methods.\n\n\n### Deployment process\n\nA stretcher agent executes a following process.\n\n1. Receive a manifest URL as Consul/Serf event's payload.\n2. Get a manifest.\n3. Get src URL and store it to a temporary file, and Check `checksum`.\n4. Invoke `pre` commands.\n5. Extract `src` archive to a temporary directory.\n6. Sync files from extracted archive to `dest` directory.\n  - use `rsync -a --delete` or `mv`\n  - sync strategy is switched by `sync_strategy`\n7. Invoke `post` commands.\n8.\n  - Invoke `success` commands when the deployment process succeeded.\n  - Invoke `failure` commands when the deployment process failed.\n\n## Manifest spec\n\n### `src`\n\nSource archive URL.\n\n* URL schema: 's3', 'http', 'file'\n* Format: 'tar', 'tar.gz'\n\n```yml\nsrc: http://example.com/src/archive.tar.gz\n```\n\n### `checksum`\n\nChecksum of source archive.\n\n* Type: 'md5', 'sha1', 'sha256', 'sha512'\n\n```yml\nchecksum: e0840daaa97cd2cf2175f9e5d133ffb3324a2b93\n```\n\n### `dest`\n\nDestination directory.\n\n```yml\ndest: /home/stretcher/app\n```\n\n### `dest_mode`\n\nDestination directory mode. Default: 0755\n\n```yml\ndest_mode: 0711\n```\n\nDestination directory mode will be set as...\n\n1. `src` archive includes `.` =\u003e same as `.` in the archive.\n2. `src` archive does not include `.` =\u003e `dest_mode`\n\n### `commands`\n\n* `pre`: Commands which will be invoked at before `src` archive extracted.\n* `post`: Commands which will be invoked at after `dest` directory synced.\n* `success`: Commands which will be invoked at deployment process is succeeded.\n* `failure`: Commands which will be invoked at deployment process is failed.\n\n```yml\ncommands:\n  pre:\n    - echo 'staring deploy'\n  post:\n    - echo 'deploy done'\n  success:\n    - echo 'deploy success'\n  failure:\n    - echo 'deploy failed!!'\n    - cat \u003e\u003e /path/to/failure.log\n```\n\nstretcher agent logs will be passed to STDIN of `success` and `failure` commands.\n\n### `excludes`\n\nPass to `rsync --exclude` arguments.\n\n```yml\nexcludes:\n  - \"*.pid\"\n  - \"*.socket\"\n```\n\n### `exclude_from`\n\nPass to `rsync --exclude-from` arguments.\nThe file must be included in `src` archive.\n\n```yml\nexclude_from: exclude.list\n```\n\n### `sync_strategy`\n\nA strategy for syncing src extracted directory to dest directory.\n\n- `rsync`: Default\n  - Use rsync(1) command with option `-av --delete`\n- `mv`\n  - Use `os.Rename()` of Golang.\n  - Deployment will be failed if `dest` directory is already exists.\n\n## Requirements\n\n* tar\n* rsync\n\ntar and rsync must be exist in PATH environment.\n\nIf you use stretcher under systemd, You can see unfinished stdout with journald.\nYou should add `RateLimitBurst=0` into `/etc/systemd/journald.conf` for getting stdout completely.\n\n## Commands execution only mode\n\nIf `src` is not defined in a manifest, Stretcher runs `pre`/`post` and `success`/`failure` commands simply.\n\n## LICENSE\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 FUJIWARA Shunichiro / (c) 2014 KAYAC Inc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffujiwara%2Fstretcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffujiwara%2Fstretcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffujiwara%2Fstretcher/lists"}