{"id":13430943,"url":"https://github.com/kayac/ecspresso","last_synced_at":"2026-04-28T15:00:57.980Z","repository":{"id":37664161,"uuid":"109662309","full_name":"kayac/ecspresso","owner":"kayac","description":"ecspresso is a deployment tool for Amazon ECS","archived":false,"fork":false,"pushed_at":"2026-04-25T07:51:32.000Z","size":2219,"stargazers_count":1075,"open_issues_count":14,"forks_count":105,"subscribers_count":23,"default_branch":"v2","last_synced_at":"2026-04-25T08:33:25.950Z","etag":null,"topics":["aws","deployment","docker","ecs","go"],"latest_commit_sha":null,"homepage":null,"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/kayac.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["fujiwara"]}},"created_at":"2017-11-06T07:34:51.000Z","updated_at":"2026-04-25T07:51:23.000Z","dependencies_parsed_at":"2026-03-14T10:06:51.675Z","dependency_job_id":null,"html_url":"https://github.com/kayac/ecspresso","commit_stats":null,"previous_names":[],"tags_count":361,"template":false,"template_full_name":null,"purl":"pkg:github/kayac/ecspresso","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2Fecspresso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2Fecspresso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2Fecspresso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2Fecspresso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kayac","download_url":"https://codeload.github.com/kayac/ecspresso/tar.gz/refs/heads/v2","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2Fecspresso/sbom","scorecard":{"id":552099,"data":{"date":"2025-08-11","repo":{"name":"github.com/kayac/ecspresso","commit":"27449f2a275ed8cd46a6420dc74bc88a81ebb9ef"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":1,"reason":"Found 1/10 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 8 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/action.yml:1","Warn: no topLevel permission defined: .github/workflows/nightly.yml:1","Warn: topLevel 'packages' permission set to 'write': .github/workflows/tagpr-release.yml:14","Warn: topLevel 'contents' permission set to 'write': .github/workflows/tagpr-release.yml:15","Warn: topLevel 'actions' permission set to 'write': .github/workflows/tagpr-release.yml:16","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:74: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:79: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/action.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/kayac/ecspresso/action.yml/v2?enable=pin","Info:   8 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   3 out of  15 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.6.0 not signed: https://api.github.com/repos/kayac/ecspresso/releases/234913675","Warn: release artifact v2.6.0-nightly-27449f2 not signed: https://api.github.com/repos/kayac/ecspresso/releases/235043924","Warn: release artifact v2.5.0-nightly-caa2d56 not signed: https://api.github.com/repos/kayac/ecspresso/releases/234725677","Warn: release artifact v2.5.0-nightly-fe4710b not signed: https://api.github.com/repos/kayac/ecspresso/releases/234401573","Warn: release artifact v2.5.0-nightly-a5faa83 not signed: https://api.github.com/repos/kayac/ecspresso/releases/233785182","Warn: release artifact v2.6.0 does not have provenance: https://api.github.com/repos/kayac/ecspresso/releases/234913675","Warn: release artifact v2.6.0-nightly-27449f2 does not have provenance: https://api.github.com/repos/kayac/ecspresso/releases/235043924","Warn: release artifact v2.5.0-nightly-caa2d56 does not have provenance: https://api.github.com/repos/kayac/ecspresso/releases/234725677","Warn: release artifact v2.5.0-nightly-fe4710b does not have provenance: https://api.github.com/repos/kayac/ecspresso/releases/234401573","Warn: release artifact v2.5.0-nightly-a5faa83 does not have provenance: https://api.github.com/repos/kayac/ecspresso/releases/233785182"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'v2'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/nightly.yml:8"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T11:09:30.094Z","repository_id":37664161,"created_at":"2025-08-20T11:09:30.094Z","updated_at":"2025-08-20T11:09:30.094Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32385943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["aws","deployment","docker","ecs","go"],"created_at":"2024-07-31T02:00:59.180Z","updated_at":"2026-04-28T15:00:57.970Z","avatar_url":"https://github.com/kayac.png","language":"Go","funding_links":["https://github.com/sponsors/fujiwara"],"categories":["Go","Repositories","Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# ecspresso\n\necspresso is a deployment tool for Amazon ECS.\n\n(pronounced the same as \"espresso\" :coffee:)\n\necspresso allows you to manage ECS services and task definitions as code in JSON, YAML, or Jsonnet files, enabling version control and infrastructure as code practices. You can generate configuration files from existing ECS services using `ecspresso init`, making it easy to start managing your infrastructure.\n\nDefinition files support template syntax and Jsonnet native functions to embed environment variables, Terraform state values, SSM parameters, and Secrets Manager ARNs. ecspresso supports multiple deployment strategies including rolling updates and Blue/Green deployments with both ECS native and CodeDeploy controllers. Before deploying, you can preview changes with `diff` and validate configurations with `verify`. If something goes wrong, `rollback` helps you safely revert to a previous state.\n\necspresso also supports ECS Express mode for simplified deployments and provides a plugin system for extending functionality.\n\n## Table of Contents\n\n- [Documents](#documents)\n- [Install](#install)\n- [Usage](#usage)\n- [Quick Start](#quick-start)\n- [Configuration file](#configuration-file)\n- [Template syntax](#template-syntax)\n- [Deployment](#example-of-deployment)\n  - [Rolling deployment](#rolling-deployment)\n  - [Blue/Green deployment (ECS)](#bluegreen-deployment-with-ecs-deployment-controller)\n  - [Blue/Green deployment (CodeDeploy)](#bluegreen-deployment-with-aws-codedeploy)\n- [Scale out/in](#scale-outin)\n- [Rollback](#rollback)\n- [Run task](#example-of-run-task)\n- [Notes](#notes)\n  - [Version constraint](#version-constraint)\n  - [Manage Application Auto Scaling](#manage-application-auto-scaling)\n  - [Jsonnet support](#use-jsonnet-instead-of-json-and-yaml)\n  - [Deploy to Fargate](#deploy-to-fargate)\n  - [Fargate Spot support](#fargate-spot-support)\n  - [ECS Service Connect support](#ecs-service-connect-support)\n  - [EBS Volume support](#ebs-volume-support)\n  - [S3 Files volume support](#s3-files-volume-support)\n  - [VPC Lattice support](#vpc-lattice-support)\n  - [ECS Express mode support](#ecs-express-mode-support)\n  - [Diff and Verify](#how-to-check-diff-and-verify-servicetask-definitions-before-deploy)\n  - [Manipulate ECS tasks](#manipulate-ecs-tasks)\n  - [Show documentation](#show-documentation)\n  - [LLM agent integration](#llm-agent-integration)\n- [Plugins](#plugins)\n  - [tfstate](#tfstate)\n  - [CloudFormation](#cloudformation)\n  - [SSM Parameter Store](#ssm-parameter-store-lookups)\n  - [Secrets Manager](#resolve-secretsmanager-secret-arn)\n  - [External commands](#execute-external-commands)\n- [LICENSE](#license)\n\n## Documents\n\n- [Differences between v1 and v2](docs/v1-v2.md).\n- [ecspresso Advent Calendar 2020](https://adventar.org/calendars/5916) (Japanese)\n- [ecspresso handbook](https://zenn.dev/fujiwara/books/ecspresso-handbook-v2) (Japanese)\n- [Command Reference](https://zenn.dev/fujiwara/books/ecspresso-handbook-v2/viewer/reference) (Japanese)\n\n## Install\n\n### Homebrew (macOS and Linux)\n\n```console\n$ brew install kayac/tap/ecspresso\n```\n\n### asdf (macOS and Linux)\n\n```console\n$ asdf plugin add ecspresso\n# or\n$ asdf plugin add ecspresso https://github.com/kayac/asdf-ecspresso.git\n\n$ asdf install ecspresso 2.3.0\n$ asdf set -u ecspresso 2.3.0\n```\n\n### aqua (macOS and Linux)\n\n[aqua](https://aquaproj.github.io/) is a CLI version manager.\n\n```console\n$ aqua g -i kayac/ecspresso\n```\n\n### Binary packages\n\n[Releases](https://github.com/kayac/ecspresso/releases)\n\n### Docker image\n\nDocker images are available on GitHub Container Registry.\n\n```console\n$ docker pull ghcr.io/kayac/ecspresso:v2.7.0\n```\n\nThe image is based on `gcr.io/distroless/static-debian12` and supports both `linux/amd64` and `linux/arm64` architectures.\n\n```console\n$ docker run --rm \\\n    -v ~/.aws:/root/.aws:ro \\\n    -v $(pwd):/work \\\n    -w /work \\\n    ghcr.io/kayac/ecspresso:v2.7.0 deploy --config ecspresso.yml\n```\n\n### CircleCI Orbs\n\nhttps://circleci.com/orbs/registry/orb/fujiwara/ecspresso\n\n```yaml\nversion: 2.1\norbs:\n  ecspresso: fujiwara/ecspresso@2.0.4\njobs:\n  install:\n    steps:\n      - checkout\n      - ecspresso/install:\n          version: v2.3.0 # or latest\n          # version-file: .ecspresso-version\n          os: linux # or windows or darwin\n          arch: amd64 # or arm64\n      - run:\n          command: |\n            ecspresso version\n```\n\n`version: latest` installs different versions of ecspresso for each Orb version.\n- fujiwara/ecspresso@0.0.15\n  - The latest release version (v2 and later)\n- fujiwara/ecspresso@1.0.0\n  - The latest version of v1.x\n- fujiwara/ecspresso@2.0.3\n  - The latest version of v2.x\n\nNote: `version: latest` is not recommended as it may cause unexpected behavior when a new version of ecspresso is released.\n\nOrb `fujiwara/ecspresso@2.0.2` supports `version-file: path/to/file`, which installs the ecspresso version specified in the file. This version number does not have a `v` prefix, For example, `2.0.0`.\n\n### GitHub Actions\n\nAction kayac/ecspresso@v2 installs an ecspresso binary for Linux(x86_64) into /usr/local/bin. This action installs ecspresso. When `args` input is provided, it runs `ecspresso` with the specified arguments after installation.\n\n```yml\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: kayac/ecspresso@v2\n        with:\n          version: v2.3.0 # or latest\n          # version-file: .ecspresso-version\n      - run: |\n          ecspresso deploy --config ecspresso.yml\n```\n\nTo use the latest version of ecspresso, pass the parameter \"latest\".\n\n```yaml\n      - uses: kayac/ecspresso@v2\n        with:\n          version: latest\n```\n\n`version: latest` installs different versions of ecspresso for each Action version.\n- kayac/ecspresso@v1\n  - The latest version of v1.x\n- kayac/ecspresso@v2\n  - The latest version of v2.x\n\nNote: `version: latest` is not recommended as it may cause unexpected behavior when a new version of ecspresso is released.\n\nAction `kayac/ecspresso@v2` supports `version-file: path/to/file`, which installs the ecspresso version specified in the file. This version number does not have a `v` prefix, For example `2.3.0`.\n\n### Run ecspresso after installation\n\nWhen the `args` input is provided, the action runs `ecspresso` with the specified arguments after installation.\n\n```yaml\n      - uses: kayac/ecspresso@v2\n        with:\n          version: latest\n          args: deploy\n        env:\n          ECSPRESSO_CONFIG: ecspresso.yml\n```\n\n## Usage\n\n```console\nUsage: ecspresso \u003ccommand\u003e\n\nFlags:\n  -h, --help                      Show context-sensitive help.\n      --envfile=ENVFILE,...       environment files ($ECSPRESSO_ENVFILE)\n      --debug                     enable debug log ($ECSPRESSO_DEBUG)\n      --ext-str=KEY=VALUE;...     external string values for Jsonnet ($ECSPRESSO_EXT_STR)\n      --ext-code=KEY=VALUE;...    external code values for Jsonnet ($ECSPRESSO_EXT_CODE)\n      --config=\"ecspresso.yml\"    config file ($ECSPRESSO_CONFIG)\n      --assume-role-arn=\"\"        the ARN of the role to assume ($ECSPRESSO_ASSUME_ROLE_ARN)\n      --timeout=TIMEOUT           timeout. Override in a configuration file ($ECSPRESSO_TIMEOUT).\n      --filter-command=STRING     filter command ($ECSPRESSO_FILTER_COMMAND)\n      --[no-]color                enable colorized output ($ECSPRESSO_COLOR)\n      --log-format=\"text\"         log format (text, json) ($ECSPRESSO_LOG_FORMAT)\n\nCommands:\n  appspec\n    output AppSpec YAML for CodeDeploy to STDOUT\n\n  delete\n    delete service\n\n  deploy\n    deploy service\n\n  deregister\n    deregister task definition\n\n  diff\n    show diff between task definition, service definition with current running\n    service and task definition\n\n  docs\n    show documentation for ecspresso\n\n  exec\n    execute command on task\n\n  init --service=SERVICE\n    create configuration files from existing ECS service\n\n  refresh\n    refresh service. equivalent to deploy --skip-task-definition\n    --force-new-deployment --no-update-service\n\n  register\n    register task definition\n\n  render \u003ctargets\u003e\n    render config, service definition or task definition file to STDOUT\n\n  revisions\n    show revisions of task definitions\n\n  rollback\n    rollback service\n\n  run\n    run task\n\n  scale\n    scale service. equivalent to deploy --skip-task-definition\n    --no-update-service\n\n  status\n    show status of service\n\n  tasks\n    list tasks that are in a service or having the same family\n\n  verify\n    verify resources in configurations\n\n  wait\n    wait until service stable\n\n  version\n    show version\n```\n\nFor more options for sub-commands, See `ecspresso sub-command --help`.\n\n### Log format\n\n`--log-format` option controls the log output format. The default is `text`.\n\n**text** format outputs human-readable logs. Attributes from `slog.With` (e.g. service/cluster) appear before the message, and per-call attributes appear after the message in `[key:value]` format.\n\n```\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] deployment created on CodeDeploy [deployment_id:d-XXXXXXXXX] [url:https://...]\n```\n\n**json** format outputs structured JSON logs suitable for machine parsing. All attributes are output as individual JSON fields.\n\n```json\n{\"time\":\"2024-01-01T00:00:00.000+09:00\",\"level\":\"INFO\",\"msg\":\"deployment created on CodeDeploy\",\"cluster\":\"default\",\"service\":\"myService\",\"deployment_id\":\"d-XXXXXXXXX\",\"url\":\"https://...\"}\n```\n\n## Quick Start\n\necspresso allows you to easily manage your existing/running ECS services by code.\n\nTry `ecspresso init` for your ECS service with option `--region`, `--cluster` and `--service`.\n\n```console\n$ ecspresso init --region ap-northeast-1 --cluster default --service myservice --config ecspresso.yml\n2024-01-01T00:00:00.000+09:00 [INFO] [myservice/default] saving service definition [path:ecs-service-def.json]\n2024-01-01T00:00:00.000+09:00 [INFO] [myservice/default] saving task definition [path:ecs-task-def.json]\n2024-01-01T00:00:00.000+09:00 [INFO] [myservice/default] saving config [path:ecspresso.yml]\n```\n\nReview the generated files: `ecspresso.yml`, `ecs-service-def.json`, and `ecs-task-def.json`.\n\nNow you can deploy the service using ecspresso!\n\n```console\n$ ecspresso deploy --config ecspresso.yml\n```\n\n### Next step\n\necspresso can read service and task definition files as a template. A typical use case is to replace the image's tag in the task definition file.\n\nModify ecs-task-def.json as below.\n\n```diff\n-  \"image\": \"nginx:latest\",\n+  \"image\": \"nginx:{{ must_env `IMAGE_TAG` }}\",\n```\n\nThen, deploy the service with environment variable `IMAGE_TAG`.\n\n```console\n$ IMAGE_TAG=stable ecspresso deploy --config ecspresso.yml\n```\n\nFor more information, refer to the [Configuration file](#configuration-file) and [Template syntax](#template-syntax) sections.\n\n## Configuration file\n\nA configuration file for ecspresso (YAML, JSON, or Jsonnet format).\n\n```yaml\nregion: ap-northeast-1 # or AWS_REGION environment variable\ncluster: default\nservice: myservice\ntask_definition: taskdef.json\ntimeout: 5m # default 10m\nignore:\n  tags:\n    - ecspresso:ignore # ignore tags of service and task definition\n```\n\n`ecspresso deploy` works as below.\n\n- Register a new task definition from `task-definition` file (JSON or Jsonnet).\n  - Replace ```{{ env `FOO` `bar` }}``` syntax in the JSON file with environment variable \"FOO\".\n    - If \"FOO\" is not defined, replaced by \"bar\"\n  - Replace ```{{ must_env `FOO` }}``` syntax in the JSON file wth environment variable \"FOO\".\n    - If \"FOO\" is not defined, abort immediately.\n- Update service tasks by the `service_definition` file (JSON or Jsonnet).\n- Wait for the service to be stable.\n\nConfiguration files and task/service definition files are read by [go-config](https://github.com/kayac/go-config) which provides template functions `env`, `must_env` and `json_escape`.\n\n## Template syntax\n\necspresso uses the [text/template standard package in Go](https://pkg.go.dev/text/template) to render template files, and parses them as YAML or JSON.\n\nWhen using Jsonnet, ecspresso first renders the Jsonnet files and then parses them as text/template. As a result, template functions can only render string values using \"{{ ... }}\", since the template function syntax {{ }} conflicts with Jsonnet syntax. To render non-string values, consider using [Jsonnet functions](#jsonnet-functions) instead.\n\nBy default, ecspresso provides the following as template functions.\n\n### `env`\n\n```go-template\n\"{{ env `NAME` `default value` }}\"\n```\n\nThis replaces the placeholder with the value of the environment variable NAME. If not set, it defaults to \"default value\".\n\n### `must_env`\n\n```go-template\n\"{{ must_env `NAME` }}\"\n```\n\nThis replaces the placeholder with the value of environment variable NAME. If not set, ecspresso will panic and stop forcefully.\n\nDefining critical values with `must_env` helps prevent unintended deployments by ensuring these values are set before execution.\n\n### `json_escape`\n\n```go-template\n\"{{ must_env `JSON_VALUE` | json_escape }}\"\n```\n\nThis escapes values as JSON strings, which is useful for embedding values as strings that require escaping, such as quotes.\n\n### Plugin provided template functions\n\necspresso also adds some template functions via plugins. See the [Plugins](#plugins) section.\n\n## Example of deployment\n\n### Rolling deployment\n\n`ecspresso deploy` performs rolling deployment by default.\n\n```console\n$ ecspresso deploy --config ecspresso.yml\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] Starting deploy\nService: myService\nCluster: default\nTaskDefinition: myService:3\nDeployments:\n    PRIMARY myService:3 desired:1 pending:0 running:1\nEvents:\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] creating a new task definition [path:myTask.json]\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] registering a new task definition\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] task definition is registered [task_definition:myService:4]\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] updating service\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] Waiting for service stable...(it will take a few minutes)\n2024-01-01T00:03:10.000+09:00 [INFO] [myService/default]  PRIMARY myService:4 desired:1 pending:0 running:1\n2024-01-01T00:03:16.000+09:00 [INFO] [myService/default] Service is stable now. Completed!\n```\n\n`deploy` commands has many options to customize the deployment behavior. See `ecspresso deploy --help` for more details.\n\n```\n  --dry-run                              dry run\n  --tasks=-1                             desired count of tasks\n  --skip-task-definition                 skip register a new task definition\n  --revision=0                           revision of the task definition to run when --skip-task-definition\n  --force-new-deployment                 force a new deployment of the service\n  --[no-]wait                            wait for service stable\n  --wait-until=\"deployed\"                Choose whether to wait for service stable or the deployment finishes. For\n                                         ECS deployment controller: \"(stable|deployed)\"; For CodeDeploy deployment\n                                         controller: \"codedeploy:*\", this accepts CodeDeploy lifecycle event (e.g.,\n                                         \"codedeploy:AfterAllowTraffic\")\n  --suspend-auto-scaling                 suspend application auto-scaling attached with the ECS service\n  --resume-auto-scaling                  resume application auto-scaling attached with the ECS service\n  --auto-scaling-min=AUTO-SCALING-MIN    set minimum capacity of application auto-scaling attached with the ECS service\n  --auto-scaling-max=AUTO-SCALING-MAX    set maximum capacity of application auto-scaling attached with the ECS service\n  --rollback-events=\"\"                   roll back when specified events happened\n                                         (DEPLOYMENT_FAILURE,DEPLOYMENT_STOP_ON_ALARM,DEPLOYMENT_STOP_ON_REQUEST,...)\n                                         CodeDeploy only.\n  --[no-]update-service                  update service attributes by service definition\n  --latest-task-definition               deploy with the latest task definition without registering a new task definition\n```\n\n### Blue/Green deployment (with ECS deployment controller)\n\n`ecspresso deploy` supports blue/green deployment using the ECS deployment controller. Configure ecs-service-def.json as follows. For minimal settings, you can set `deploymentController.type` and `deploymentConfiguration.strategy` as shown below.\n\n```jsonnet\n{\n  \"deploymentController\": {\n    \"type\": \"ECS\"\n  },\n  \"deploymentConfiguration\": {\n    \"strategy\": \"BLUE_GREEN\"\n  },\n  // ...\n```\n\nFor more advanced settings, you can define `deploymentConfiguration`, `loadBalancers` and `serviceConnectConfiguration` in ecs-service-def.json. For example, using an application load balancer and set lifecycle hooks, you can use the following configuration:\n\n```jsonnet\n{\n  \"deploymentController\": {\n    \"type\": \"ECS\"\n  },\n  \"deploymentConfiguration\": {\n    \"bakeTimeInMinutes\": 1,\n    \"deploymentCircuitBreaker\": {\n      \"enable\": false,\n      \"rollback\": false\n    },\n    \"lifecycleHooks\": [\n      {\n        \"hookTargetArn\": \"arn:aws:lambda:ap-northeast-1:123456789012:function:bg-hook\",\n        \"lifecycleStages\": [\n          \"PRE_SCALE_UP\",\n          \"POST_SCALE_UP\",\n          \"TEST_TRAFFIC_SHIFT\",\n          \"POST_TEST_TRAFFIC_SHIFT\",\n          \"PRODUCTION_TRAFFIC_SHIFT\",\n          \"POST_PRODUCTION_TRAFFIC_SHIFT\"\n        ],\n        \"roleArn\": \"arn:aws:iam::123456789012:role/ECSServiceRole\"\n      }\n    ],\n    \"maximumPercent\": 200,\n    \"minimumHealthyPercent\": 100,\n    \"strategy\": \"BLUE_GREEN\"\n  },\n  \"loadBalancers\": [\n    {\n      \"containerName\": \"app\",\n      \"containerPort\": 80,\n      \"targetGroupArn\": \"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/my-target-group/1234567890abcdef\"\n      \"advancedConfiguration\": {\n        \"alternateTargetGroupArn\": \"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/my-alternate-target-group/1234567890abcdef\",\n        \"productionListenerRule\": \"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener-rule/my-production-listener-rule/1234567890abcdef\",\n        \"roleArn\": \"arn:aws:iam::123456789012:role/ECSServiceRole\"\n      }\n    }\n  ],\n  // ...\n```\n\nFor more details, See [Amazon ECS blue/green deployments\n](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-blue-green.html).\n\n\n### Blue/Green deployment (with AWS CodeDeploy)\n\n`ecspresso deploy` can deploy services using the CODE_DEPLOY deployment controller. Configure ecs-service-def.json as follows.\n\n```jsonnet\n{\n  \"deploymentController\": {\n    \"type\": \"CODE_DEPLOY\"\n  },\n  // ...\n}\n```\n\nImportant notes:\n\n- ecspresso does not create or modify any CodeDeploy resources. You must separately create an application and deployment group for your ECS service in CodeDeploy.\n- ecspresso automatically detects CodeDeploy deployment settings for the ECS service.\n- If there are numerous CodeDeploy applications, the API calls during this detection process may cause throttling. To mitigate this, specify the CodeDeploy application_name and deployment_group_name in the config file:\n\n```yaml\n# ecspresso.yml\ncodedeploy:\n  application_name: myapp\n  deployment_group_name: mydeployment\n  deployment_config_name: myDeploymentConfig # optional, override DeploymentGroup setting\n```\n\n`ecspresso deploy` creates a new deployment for CodeDeploy, and it continues on CodeDeploy.\n\n```console\n$ ecspresso deploy --config ecspresso.yml --rollback-events DEPLOYMENT_FAILURE\n2024-01-01T00:00:00.000+09:00 [INFO] [myService/default] Starting deploy\nService: myService\nCluster: default\nTaskDefinition: myService:5\nTaskSets:\n   PRIMARY myService:5 desired:1 pending:0 running:1\nEvents:\n2024-01-01T00:00:01.000+09:00 [INFO] [myService/default] creating a new task definition [path:ecs-task-def.json]\n2024-01-01T00:00:01.000+09:00 [INFO] [myService/default] registering a new task definition\n2024-01-01T00:00:01.000+09:00 [INFO] [myService/default] task definition is registered [task_definition:myService:6]\n2024-01-01T00:00:01.000+09:00 [INFO] [myService/default] desired count [count:1]\n2024-01-01T00:00:02.000+09:00 [INFO] [myService/default] deployment created on CodeDeploy [deployment_id:d-XXXXXXXXX] [url:https://ap-northeast-1.console.aws.amazon.com/codesuite/codedeploy/deployments/d-XXXXXXXXX?region=ap-northeast-1]\n```\n\nCodeDeploy appspec hooks can be defined in a config file. ecspresso automatically creates `Resources` and `version` elements in appspec on deployment:\n\n```yaml\ncluster: default\nservice: test\nservice_definition: ecs-service-def.json\ntask_definition: ecs-task-def.json\nappspec:\n  Hooks:\n    - BeforeInstall: \"LambdaFunctionToValidateBeforeInstall\"\n    - AfterInstall: \"LambdaFunctionToValidateAfterTraffic\"\n    - AfterAllowTestTraffic: \"LambdaFunctionToValidateAfterTestTrafficStarts\"\n    - BeforeAllowTraffic: \"LambdaFunctionToValidateBeforeAllowingProductionTraffic\"\n    - AfterAllowTraffic: \"LambdaFunctionToValidateAfterAllowingProductionTraffic\"\n```\n\n## Scale out/in\n\nTo change the desired count of a service, specify `scale --tasks`.\n\n```console\n$ ecspresso scale --tasks 10\n```\n\n`scale` command is equivalent to `deploy --skip-task-definition --no-update-service`.\n\n## Example of deploy\n\necspresso can deploy a service using a `service_definition` JSON file.\n\n```console\n$ ecspresso deploy --config ecspresso.yml\n...\n```\n\n```yaml\n# ecspresso.yml\nservice_definition: service.json\n```\n\nservice.json example:\n\n```json\n{\n  \"role\": \"ecsServiceRole\",\n  \"desiredCount\": 2,\n  \"loadBalancers\": [\n    {\n      \"containerName\": \"myLoadbalancer\",\n      \"containerPort\": 80,\n      \"targetGroupArn\": \"arn:aws:elasticloadbalancing:[region]:[account-id]:targetgroup/{target-name}/201ae83c14de522d\"\n    }\n  ]\n}\n```\n\nKeys are in the same format as `aws ecs describe-services` output.\n\n- deploymentConfiguration\n- launchType\n- loadBalancers\n- networkConfiguration\n- placementConstraint\n- placementStrategy\n- role\n- etc.\n\n## Rollback\n\n`ecspresso rollback` rolls back a service to the previous task definition revision.\n\n```console\n$ ecspresso rollback --config ecspresso.yml\n```\n\nBy default, ecspresso finds the previous task definition revision by listing the task definition family in descending order and selecting the revision immediately before the current one.\n\nFor services using the ECS deployment controller, if there's an active deployment in progress, ecspresso will stop it with rollback. Otherwise, it updates the service with the previous task definition.\n\nFor services using the CodeDeploy deployment controller, if there's an active deployment, ecspresso stops it with rollback. Otherwise, it creates a new deployment with the previous task definition.\n\n## Example of run task\n\n```console\n$ ecspresso run --config ecspresso.yml --task-def=db-migrate.json\n```\n\nIf `--task-def` is not set, ecspresso will use the task definition included in the service.\n\nOther options for RunTask API are set by service attributes (CapacityProviderStrategy, LaunchType, PlacementConstraints, PlacementStrategy and PlatformVersion).\n\n## Notes\n\n### Version constraint\n\n`required_version` in the configuration file is for fixing the version of ecspresso.\n\n```yaml\nrequired_version: \"\u003e= 2.0.0, \u003c 3\"\n```\n\nThis allows ecspresso to execute if the version is greater than or equal to 2.0.0 and less than 3. If the version does not fall within this range, execution will fail.\n\nThis feature is implemented by [go-version](github.com/hashicorp/go-version).\n\n### Manage Application Auto Scaling\n\nFor ECS services using Application Auto Scaling, adjusting the minimum and maximum auto-scaling settings with the `ecspresso scale` command is a breeze. Simply specify either `scale --auto-scaling-min` or `scale --auto-scaling-max` to modify the settings.\n\n```console\n$ ecspresso scale --tasks 5 --auto-scaling-min 5 --auto-scaling-max 20\n```\n\n`ecspresso deploy` and `scale` can suspend and resume application auto scaling.\n\n- `--suspend-auto-scaling` sets suspended state to true.\n- `--resume-auto-scaling` sets suspended state to false.\n\nTo change the suspended state, simply use `ecspresso scale --suspend-auto-scaling` or `ecspresso scale --resume-auto-scaling`. These commands will only change the suspended state without affecting other settings.\n\n### Use Jsonnet instead of JSON and YAML.\n\necspresso supports the [Jsonnet](https://jsonnet.org/) file format.\n\n- v1.7 and later: Jsonnet support for service and task definitions\n- v2.0 and later: Jsonnet support for the configuration file\n- v2.4 and later: supports [Jsonnet functions](#jsonnet-functions)\n\nIf a file has the `.jsonnet` extension, ecspresso will proceed in the following order:\n\n1. process it as Jsonnet\n2. convert it to JSON\n3. load it with evaluation template syntax.\n\nUsing [Template syntax](#template-syntax) in Jsonnet files may lead to syntax errors due to conflicts with Jsonnet syntax. In such cases, consider using [Jsonnet functions](#jsonnet-functions) instead.\n\n```jsonnet\n{\n  cluster: 'default',\n  service: 'myservice',\n  service_definition: 'ecs-service-def.jsonnet',\n  task_definition: 'ecs-task-def.jsonnet',\n}\n```\n\necspresso includes [github.com/google/go-jsonnet](https://github.com/google/go-jsonnet) as a library, so a separate installation of jsonnet is not needed.\n\n`--ext-str` and `--ext-code` flag sets [Jsonnet External Variables](https://jsonnet.org/ref/stdlib.html#ext_vars).\n\n```console\n$ ecspresso --ext-str Foo=foo --ext-code \"Bar=1+1\" ...\n```\n\n```jsonnet\n{\n  foo: std.extVar('Foo'), // = \"foo\"\n  bar: std.extVar('Bar'), // = 2\n}\n```\n\n### Jsonnet functions\n\nv2.4 and later supports Jsonnet native functions in Jsonnet files.\n\nIn the .jsonnet file,:\n\n1. Define `local func = std.native('func');`\n2. Use `func()`\n\nJsonnet functions are evaluated when rendering Jsonnet files, which helps avoid conflicts with template syntax.\n\n#### `env`, `must_env`\n\n`env` and `must_env` functions work the similary to template functions in JSON and YAML files. However, unlike template functions, Jsonnet functions are capable of rendering non-string values from environment variables using `std.parseInt()`, `std.parseJson()`, etc.\n\n```jsonnet\nlocal env = std.native('env');\nlocal must_env = std.native('must_env');\n{\n  foo: env('FOO', 'default value'),\n  bar: must_env('BAR'),\n  bazNumber: std.parseInt(env('BAZ_NUMBER', '0')),\n  booBool: std.parseJson(env('BOO_BOOL', 'false')),\n}\n```\n\n#### Other plugin-provided functions\n\nSee [Plugins](#plugins) section.\n\n### Deploy to Fargate\n\nWhen deploying services to Fargate, both task definitions and service definitions require specific settings.\n\nFor task definitions,\n\n- requiresCompatibilities (requires \"FARGATE\")\n- networkMode (requires \"awsvpc\")\n- cpu (required)\n- memory (required)\n- executionRoleArn (optional)\n\n```json\n{\n  \"taskDefinition\": {\n    \"networkMode\": \"awsvpc\",\n    \"requiresCompatibilities\": [\n      \"FARGATE\"\n    ],\n    \"cpu\": \"1024\",\n    \"memory\": \"2048\",\n    // ...\n}\n```\n\nFor service-definitions,\n\n- launchType (requires \"FARGATE\")\n- networkConfiguration (requires \"awsvpcConfiguration\")\n\n```json5\n{\n  \"launchType\": \"FARGATE\",\n  \"networkConfiguration\": {\n    \"awsvpcConfiguration\": {\n      \"subnets\": [\n        \"subnet-aaaaaaaa\",\n        \"subnet-bbbbbbbb\"\n      ],\n      \"securityGroups\": [\n        \"sg-11111111\"\n      ],\n      \"assignPublicIp\": \"ENABLED\"\n    }\n  },\n  // ...\n}\n```\n\n### Fargate Spot support\n\n1. Set `capacityProviders` and `defaultCapacityProviderStrategy` for the ECS cluster.\n1. To migrate an existing service to use Fargate Spot, define `capacityProviderStrategy` in the service definition as shown below. Use `ecspresso deploy --update-service` to apply the settings to the service.\n\n```json\n{\n  \"capacityProviderStrategy\": [\n    {\n      \"base\": 1,\n      \"capacityProvider\": \"FARGATE\",\n      \"weight\": 1\n    },\n    {\n      \"base\": 0,\n      \"capacityProvider\": \"FARGATE_SPOT\",\n      \"weight\": 1\n    }\n  ],\n  // ...\n```\n\n### ECS Service Connect support\n\necspresso supports [ECS Service Connect](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect.html).\n\nTo configure, define `serviceConnectConfiguration` in service definitions and `portMappings` in task definitions.\n\nFor more details, see [Service Connect parameters](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect.html#service-connect-parameters)\n\n### EBS Volume support\n\necspresso supports [Amazon EBS Volumes](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ebs-volumes.html).\n\nTo configure, define `volumeConfigurations` in service definitions, and `mountPoints` and `volumes` in task definitions.\n\n\n```jsonnet\n// ecs-service-def.json\n  \"volumeConfigurations\": [\n    {\n      \"managedEBSVolume\": {\n        \"filesystemType\": \"ext4\",\n        \"roleArn\": \"arn:aws:iam::123456789012:role/ecsInfrastructureRole\",\n        \"sizeInGiB\": 10,\n        \"tagSpecifications\": [\n          {\n            \"propagateTags\": \"SERVICE\",\n            \"resourceType\": \"volume\"\n          }\n        ],\n        \"volumeType\": \"gp3\"\n      },\n      \"name\": \"ebs\"\n    }\n  ]\n```\n\n```jsonnet\n// ecs-task-def.json\n// containerDefinitions[].mountPoints\n      \"mountPoints\": [\n        {\n          \"containerPath\": \"/mnt/ebs\",\n          \"sourceVolume\": \"ebs\"\n        }\n      ]\n// volumes\n  \"volumes\": [\n    {\n      \"name\": \"ebs\",\n      \"configuredAtLaunch\": true\n    }\n  ]\n```\n\n`ecspresso run` command supports EBS volumes too.\n\nBy default, EBS volumes attached to standalone tasks are deleted when the task stops. Use the `--no-ebs-delete-on-termination` option to preserve volumes.\n\n```console\n$ ecspresso run --no-ebs-delete-on-termination\n```\n\nFor tasks run by ECS services, EBS volumes are always deleted when the task stops. This is an ECS specification that ecspresso cannot override.\n\n\n### S3 Files volume support\n\necspresso supports [Amazon S3 Files](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-files.html) volumes.\n\nTo configure, define `mountPoints` and `volumes` with `s3filesVolumeConfiguration` in task definitions.\n\n```jsonnet\n// ecs-task-def.json\n// containerDefinitions[].mountPoints\n      \"mountPoints\": [\n        {\n          \"containerPath\": \"/mnt/s3\",\n          \"sourceVolume\": \"s3files\"\n        }\n      ]\n// volumes\n  \"volumes\": [\n    {\n      \"name\": \"s3files\",\n      \"s3filesVolumeConfiguration\": {\n        \"fileSystemArn\": \"arn:aws:s3files:ap-northeast-1:123456789012:file-system/fs-01234567890abcdef\",\n        \"rootDirectory\": \"/\"\n      }\n    }\n  ]\n```\n\nSee [Prerequisites for S3 Files](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-files-prereq-policies.html) for IAM role and security group configuration required for S3 Files mount targets.\n\n### VPC Lattice support\n\necspresso supports [VPC Lattice](https://aws.amazon.com/vpc/lattice/) integration.\n\n1. Define `portMappings` in the task definition. The `name` field is required.\n```json\n{\n  \"containerDefinitions\": [\n    {\n      \"name\": \"webserver\",\n      \"portMappings\": [\n        {\n          \"name\": \"web-80-tcp\",\n          \"containerPort\": 80,\n          \"hostPort\": 80,\n          \"protocol\": \"tcp\",\n          \"appProtocol\": \"http\"\n        }\n      ],\n```\n\n2. Define `vpcLatticeConfigurations` in the service definition. The `portName`, `roleArn`, and `targetGroupArn` fields are required.`\n\n- The `portName` must match the `name` field of the `portMappings` in the task definition.\n- The `roleArn` is the IAM role that the ECS service assumes to call the VPC Lattice API.\n  - The role must have the `ecs.amazonaws.com` service principal.\n  - The role should have the `AmazonECSInfrastructureRolePolicyForVpcLattice` policy or equivalent permissions.\n- The `targetGroupArn` is the ARN of the VPC Lattice target group.\n\n```json\n{\n  \"vpcLatticeConfigurations\": [\n    {\n      \"portName\": \"web-80-tcp\",\n      \"roleArn\": \"arn:aws:iam::123456789012:role/ecsInfrastructureRole\",\n      \"targetGroupArn\": \"arn:aws:vpc-lattice:ap-northeast-1:123456789012:targetgroup/tg-009147df264a0bacb\"\n    }\n  ],\n```\n\necspresso doesn't create or modify any VPC Lattice resources. You must create and associate a VPC Lattice target group with the ECS service.\n\nSee also [Use Amazon VPC Lattice to connect, observe, and secure your Amazon ECS services](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-vpc-lattice.html).\n\n### ECS Express mode support\n\necspresso supports [ECS Express](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/express-service-overview.html) mode, which provides a simplified way to deploy ECS services with a single definition file instead of separate task and service definitions.\n\n#### Supported commands\n\nThe following commands work with Express mode:\n\n- `init --express` - Import an existing Express service into definition files\n- `deploy` - Create or update Express services\n- `diff` - Show differences between local and remote Express definitions\n- `render expressdef` - Render an Express definition file\n- `delete` - Delete an Express service\n- `status` - Show Express service status including ingress paths\n- `rollback` - Partial support (works only during active deployments)\n- `verify` - Verify resources in Express definition\n- `exec`, `refresh`, `tasks`, `wait` - Also supported\n\n#### Unsupported commands\n\nSome commands do not work with Express mode: `scale`, `run`, `revisions`, `register`, `deregister`, `appspec`.\n\n#### Configuration\n\nTo use Express mode, specify `express_definition` instead of `task_definition` and `service_definition` in your config file:\n\n```yaml\n# ecspresso.yml\nregion: ap-northeast-1\ncluster: ecspresso\nservice: myservice\nexpress_definition: ecs-express-def.json\n```\n\n#### Minimal Express definition\n\n```json\n{\n  \"executionRoleArn\": \"arn:aws:iam::123456789012:role/ecsTaskExecutionRole\",\n  \"infrastructureRoleArn\": \"arn:aws:iam::123456789012:role/ecsInfrastructureRoleForExpressServices\",\n  \"primaryContainer\": {\n    \"image\": \"nginx:latest\"\n  }\n}\n```\n\n#### Full Express definition example\n\n```jsonnet\n// ecs-express-def.jsonnet\n{\n  cpu: '256',\n  memory: '512',\n  executionRoleArn: 'arn:aws:iam::123456789012:role/ecsTaskExecutionRole',\n  taskRoleArn: 'arn:aws:iam::123456789012:role/ecsTaskRole',\n  infrastructureRoleArn: 'arn:aws:iam::123456789012:role/ecsInfrastructureRoleForExpressServices',\n  healthCheckPath: '/',\n  networkConfiguration: {\n    securityGroups: ['sg-00123456789abcdef'],\n    subnets: ['subnet-00123456789abcdef', 'subnet-0123456789abcdef0'],\n  },\n  primaryContainer: {\n    image: 'nginx:latest',\n    containerPort: 80,\n    environment: [\n      { name: 'ENV', value: 'production' },\n    ],\n    awsLogsConfiguration: {\n      logGroup: '/aws/ecs/myservice',\n      logStreamPrefix: 'ecs',\n    },\n  },\n  scalingTarget: {\n    autoScalingMetric: 'AVERAGE_CPU',\n    autoScalingTargetValue: 60,\n    minTaskCount: 1,\n    maxTaskCount: 10,\n  },\n  tags: [\n    { key: 'Environment', value: 'production' },\n  ],\n}\n```\n\n#### Migration from Express mode\n\nExisting ECS Express services can be imported as non-express (normal) mode by `ecspresso init --no-express`. This creates standard definition files (`ecspresso.yml`, `ecs-service-def.json`, and `ecs-task-def.json`).\n\nNote: ECS Express mode cannot update `deploymentConfiguration` and `loadBalancers` in a service definition. `ecspresso init --no-express` also omits these fields.\n\n### How to check diff and verify service/task definitions before deploy.\n\necspresso supports `diff` and `verify` commands.\n\n#### diff\n\nShows differences between local task/service definitions and remote (on ECS) definitions.\n\n```diff\n$ ecspresso diff\n--- arn:aws:ecs:ap-northeast-1:123456789012:service/ecspresso-test/nginx-local\n+++ ecs-service-def.json\n@@ -38,5 +38,5 @@\n   },\n   \"placementConstraints\": [],\n   \"placementStrategy\": [],\n-  \"platformVersion\": \"1.3.0\"\n+  \"platformVersion\": \"LATEST\"\n }\n\n--- arn:aws:ecs:ap-northeast-1:123456789012:task-definition/ecspresso-test:202\n+++ ecs-task-def.json\n@@ -1,6 +1,10 @@\n {\n   \"containerDefinitions\": [\n     {\n       \"cpu\": 0,\n       \"environment\": [],\n       \"essential\": true,\n-      \"image\": \"nginx:latest\",\n+      \"image\": \"nginx:alpine\",\n       \"logConfiguration\": {\n         \"logDriver\": \"awslogs\",\n         \"options\": {\n```\n\nv2.4 or later, `ecspresso diff --external` can invoke an external command. You can use the \"diff\" command you like.\n\nFor example, use [difftastic](https://github.com/Wilfred/difftastic) (`difft`) command.\n\n```console\n$ ecspresso diff --external \"difft --color=always\"\n\n$ ECSPRESSO_DIFF_COMMAND=\"difft --color=always\" ecspresso diff\n```\n\nThe command should exit with status 0. If it exits with a non-zero status when two files differ (for example, `diff(1)`), you need to write a wrapper command.\n\n`ecspresso diff --jsonnet` renders the diff output in Jsonnet format instead of JSON. This is useful when you manage definitions in Jsonnet files.\n\n```console\n$ ecspresso diff --jsonnet\n```\n\n`ecspresso diff --without-service` skips the diff of the service definition and only shows the diff of the task definition.\n\n```console\n$ ecspresso diff --without-service\n```\n\n\n#### verify\n\nVerify resources related with service/task definitions.\n\nFor example it checks if,\n- An ECS cluster exists.\n- The target groups in service definitions match the container name and port defined in the definitions.\n- A task role and a task execution role exist and can be assumed by ecs-tasks.amazonaws.com.\n- Container images exist at the URL defined in task definitions. (Checks only for ECR or DockerHub public images.)\n- Secrets in task definitions exist and are readable.\n- Log streams can be created and messages can be put into the specified CloudWatch log groups streams.\n\necspresso verify tries to assume the task execution role defined in task definitions to verify these items. If it fails to assume the role, it continues to verify with the current session.\n\n```console\n$ ecspresso verify\n2024-01-01T00:00:00.000+09:00 [INFO] [nginx-local/ecspresso-test] Starting verify\n  TaskDefinition\n    ExecutionRole[arn:aws:iam::123456789012:role/ecsTaskRole]\n    --\u003e [OK]\n    TaskRole[arn:aws:iam::123456789012:role/ecsTaskRole]\n    --\u003e [OK]\n    ContainerDefinition[nginx]\n      Image[nginx:alpine]\n      --\u003e [OK]\n      LogConfiguration[awslogs]\n      --\u003e [OK]\n    --\u003e [OK]\n  --\u003e [OK]\n  ServiceDefinition\n  --\u003e [OK]\n  Cluster\n  --\u003e [OK]\n2024-01-01T00:00:04.000+09:00 [INFO] [nginx-local/ecspresso-test] Verify OK!\n```\n\n### Manipulate ECS tasks\n\necspresso can manipulate ECS tasks using the  `tasks` and `exec` commands.\n\nAfter v2.0, These operations are provided by [ecsta](https://github.com/fujiwara/ecsta) as a library. The ecsta CLI can manipulate any ECS tasks, not limited to those deployed by ecspresso.\n\nConsider using ecsta as a CLI command.\n\n#### tasks\n\nThe `tasks` command lists tasks related to the ecspresso configuration. When `service` is configured, it lists tasks belonging to the service plus standalone tasks of the same family (typically launched by `ecspresso run`). Tasks of other services that share the task definition family are excluded. When `service` is not configured, it lists tasks of the task definition family.\n\n```\nUsage: ecspresso tasks \u003ccommand\u003e [flags]\n\nCommon flags:\n      --id=                       task ID\n      --output=table              output format (table, json, tsv)\n\nCommands:\n  tasks list          list tasks (default)\n  tasks find          find a task from tasks list and dump it as JSON\n  tasks stop          stop a task\n  tasks trace         trace a task\n  tasks logs          show logs of a task\n```\n\n##### tasks find\n\nThe `find` subcommand enables task selection from a list and displays it as JSON.\n\nThe `ECSPRESSO_FILTER_COMMAND` environment variable can be set to specify a command for filtering tasks, such as [peco](https://github.com/peco/peco), [fzf](https://github.com/junegunn/fzf), etc.\n\n```console\n$ ECSPRESSO_FILTER_COMMAND=peco ecspresso tasks find\n```\n\n##### tasks stop\n\nThe `stop` subcommand allows for task selection and stopping from a list.\n\n```console\n$ ecspresso tasks stop --force\n```\n\n```\nFlags:\n      --force=false               stop the task without confirmation\n```\n\n##### tasks logs\n\nThe `logs` subcommand shows CloudWatch Logs of the task.\n\n```console\n$ ecspresso tasks logs -f -d 5m --container app\n```\n\n```\nFlags:\n  -f, --follow=false              follow logs\n  -d, --duration=1m               duration of logs\n  -s, --start-time=               start time of logs\n      --container=                container name\n```\n\nUse `--follow` to follow logs in real time, `--duration` to specify the time range, and `--start-time` to specify an absolute start time. When `--log-format json` is set, logs are output as JSON lines.\n\n#### exec\n\nThe `exec` command executes a command on a task.\n\n[session-manager-plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html) is required in PATH.\n\n```\nUsage: ecspresso exec \u003ccommand\u003e [flags]\n\nCommon flags:\n      --id=                       task ID\n      --container=                container name\n\nCommands:\n  exec run              execute command on task (default)\n  exec portforward      port forwarding to a task\n  exec cp \u003csrc\u003e \u003cdest\u003e  copy files between local and task\n```\n\nIf `--id` is not set, the command shows a list of tasks to select a task to execute.\n\nThe `ECSPRESSO_FILTER_COMMAND` environment variable works the same as with the `tasks` command.\n\nSee also the official documentation [Using Amazon ECS Exec for debugging](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html).\n\n##### exec run\n\nThe `run` subcommand (default) executes a command on a task interactively.\n\n```console\n$ ecspresso exec run --command \"ls -la\"\n```\n\n```\nFlags:\n      --command=sh                command to execute\n```\n\n##### exec portforward\n\nThe `portforward` subcommand enables port forwarding from a local port to an ECS task's port.\n\n```console\n$ ecspresso exec portforward --port 80 --local-port 8080\n```\n\n```\nFlags:\n      --local-port=0              local port number\n      --port=0                    remote port number\n      --host=                     remote host\n  -L                              short expression of local-port:host:port\n```\n\nIf `--id` is not set, the command shows a list of tasks to select for port forwarding.\n\nWhen `--local-port` is not specified, an ephemeral port is used as the local port.\n\nThe `-L` option is a short expression for `local-port:host:port`. For example, `-L 8080:example.com:80` is equivalent to `--local-port 8080 --host example.com --port 80`.\n\n```console\n$ ecspresso exec portforward -L 8080:example.com:80\n```\n\n##### exec cp\n\nThe `cp` subcommand copies files between local and a running ECS task.\n\nThe source and destination arguments use `taskID:/path` format for the remote side. Use `_` as the task ID to select a task interactively.\n\n```console\n# Copy a local file to the task\n$ ecspresso exec cp /local/file.txt _:/remote/file.txt\n\n# Copy a file from the task to local\n$ ecspresso exec cp _:/remote/file.txt /local/file.txt\n\n# Specify a task ID directly\n$ ecspresso exec cp /local/file.txt abcdef1234567890:/remote/file.txt\n```\n\n```\nFlags:\n      --port=12345                port number for file transfer\n      --[no-]progress             show progress bar (default true)\n```\n\n### Show documentation\n\nThe `docs` command shows the embedded documentation (this README) directly from the ecspresso binary. This command does not require AWS credentials or a configuration file.\n\n```\nFlags:\n      --article=\"readme\"          article name to display\n      --list                      list available articles\n      --index                     show table of contents\n      --search=\"\"                 search keyword in documents\n      --json                      output in JSON format\n```\n\nShow the full README:\n\n```console\n$ ecspresso docs\n```\n\nShow the table of contents with section headings and line numbers:\n\n```console\n$ ecspresso docs --index\n```\n\nSearch for sections containing a keyword (case-insensitive):\n\n```console\n$ ecspresso docs --search \"fargate\"\n```\n\nOutput in JSON format (useful for LLM agents and other tools):\n\n```console\n$ ecspresso docs --search \"deploy\" --json\n```\n\nThe JSON output contains structured sections with `level`, `title`, `content`, and `line` fields, making it easy for automated tools and LLM agents to consume ecspresso documentation programmatically.\n\nList available articles:\n\n```console\n$ ecspresso docs --list\nreadme\tecspresso README\n```\n\n### LLM agent integration\n\necspresso provides an [Agent Skill](https://agentskills.io/) for LLM agents (Claude Code, GitHub Copilot, OpenAI Codex, etc.) to use ecspresso effectively. The skill covers common workflows, command usage patterns, and best practices. Powered by [Songmu/skillsmith](https://github.com/Songmu/skillsmith).\n\nInstall the skill for your user:\n\n```console\n$ ecspresso skills install\n```\n\nThis installs the skill to `~/.agents/skills/ecspresso/SKILL.md`. Compatible LLM agents automatically discover skills in this directory — no additional configuration is needed.\n\nTo share the skill with your team via the repository, use `--scope repo`:\n\n```console\n$ ecspresso skills install --scope repo\n```\n\nThis installs to `.agents/skills/` in the repository root. Commit this directory so that team members' agents can use the skill without installing it individually.\n\nOther `skills` operations:\n\n```console\n$ ecspresso skills list        # List available skills\n$ ecspresso skills status      # Show installation status\n$ ecspresso skills update      # Update installed skills\n$ ecspresso skills uninstall   # Remove installed skills\n$ ecspresso skills reinstall   # Reinstall all managed skills\n```\n\n## Plugins\n\necspresso supports plugins to extend template functions and Jsonnet native functions.\n\n### tfstate\n\nThe tfstate plugin introduces the `tfstate` and `tfstatef` template functions.\n\necspresso.yml\n```yaml\nregion: ap-northeast-1\ncluster: default\nservice: test\nservice_definition: ecs-service-def.json\ntask_definition: ecs-task-def.json\nplugins:\n  - name: tfstate\n    config:\n      url: s3://my-bucket/terraform.tfstate\n      # or path: terraform.tfstate    # path to local file\n```\n\necs-service-def.json\n```json\n{\n  \"networkConfiguration\": {\n    \"awsvpcConfiguration\": {\n      \"subnets\": [\n        \"{{ tfstatef `aws_subnet.private['%s'].id` `az-a` }}\"\n      ],\n      \"securityGroups\": [\n        \"{{ tfstate `data.aws_security_group.default.id` }}\"\n      ]\n    }\n  }\n}\n```\n\n`{{ tfstate \"resource_type.resource_name.attr\" }}` will expand to the attribute value of the resource in tfstate.\n\n`{{ tfstatef \"resource_type.resource_name['%s'].attr\" \"index\" }}` is similar to `{{ tfstatef \"resource_type.resource_name['index'].attr\" }}`. This function is useful for build a resource addresses with environment variables.\n\n```\n{{ tfstatef `aws_subnet.ecs['%s'].id` (must_env `SERVICE`) }}\n```\n\n#### tfstate Jsonnet function\n\n`tfstate` Jsonnet function works the same as template function in JSON and YAML files.\n`tfstatef` Jsonnet function is not provided. Use `std.format()` or interpolation instead.\n\n```jsonnet\nlocal tfstate = std.native('tfstate');\n{\n  networkConfiguration: {\n    awsvpcConfiguration: {\n      subnets: [\n        tfstate('aws_subnet.private[\"%s\"].id' % 'az-z'),\n        tfstate(std.format('aws_subnet.private[\"%s\"].id', 'az-b')),\n      ],\n      securityGroups: [\n        sg.id for sg in std.objectValues(tfstate('data.aws_security_group.default'))\n        // data.aws_security_group.default[\"first\"].id\n        // data.aws_security_group.default[\"second\"].id\n      ]\n    }\n  }\n}\n```\n\nWhen the tfstate includes count/for_each resources, so the resource address can be specified with an index.\n\n```jsonnet\nlocal tfstate = std.native('tfstate');\ntfstate('aws_subnet.private[\"%s\"].id' % 'az-a') // aws_subnet.private[\"az-a\"].id\n```\n\nTo fetch all resources of count/for_each resources, use `std.objectValues()`.\n\n```jsonnet\nlocal tfstate = std.native('tfstate');\n{\n  subnets: [\n    subnet.id for subnet in std.objectValues(tfstate('aws_subnet.private'))\n    // aws_subnet.private[\"az-a\"].id\n    // aws_subnet.private[\"az-b\"].id\n    // aws_subnet.private[\"az-c\"].id\n  ],\n}\n```\n\n#### Supported tfstate URL formats\n\n- Local file `file://path/to/terraform.tfstate`\n- HTTP/HTTPS `https://example.com/terraform.tfstate`\n- Amazon S3 `s3://{bucket}/{key}`\n- Terraform Cloud `remote://api.terraform.io/{organization}/{workspaces}`\n  - `TFE_TOKEN` environment variable is required.\n- Google Cloud Storage `gs://{bucket}/{key}`\n- Azure Blog Storage `azurerm://{resource_group_name}/{storage_account_name}/{container_name}/{blob_name}`\n\nThis plugin uses [tfstate-lookup](https://github.com/fujiwara/tfstate-lookup) to load tfstate.\n\n#### Multiple tfstate support\n\n`func_prefix` adds prefixes to template function names for each plugin configuration, enabling support for multiple tfstate files.\n\n```yaml\n# ecspresso.yml\nplugins:\n   - name: tfstate\n     config:\n       url: s3://tfstate/first.tfstate\n     func_prefix: first_\n   - name: tfstate\n     config:\n       url: s3://tfstate/second.tfstate\n     func_prefix: second_\n```\n\nIn templates, functions are called with the specified prefixes.\n\n```go-template\n[\n  \"{{ first_tfstate `aws_s3_bucket.main.arn` }}\",\n  \"{{ second_tfstate `aws_s3_bucket.main.arn` }}\"\n]\n```\n\nSimilar features are also supported for Jsonnet.\n\n```jsonnet\nlocal first_tfstate = std.native('first_tfstate'); // func_prefix: first_\nlocal second_tfstate = std.native('second_tfstate'); // func_prefix: second_\n[\n  first_tfstate('aws_s3_bucket.main.arn'),\n  second_tfstate('aws_s3_bucket.main.arn'),\n]\n```\n\n### CloudFormation\n\nThe cloudformation plugin introduces the `cfn_output` and `cfn_export` template functions.\n\nAn example of a CloudFormation stack template defining Outputs and Exports.\n\n```yaml\n# StackName: ECS-ecspresso\nOutputs:\n  SubnetAz1:\n    Value: !Ref PublicSubnetAz1\n  SubnetAz2:\n    Value: !Ref PublicSubnetAz2\n  EcsSecurityGroupId:\n    Value: !Ref EcsSecurityGroup\n    Export:\n      Name: !Sub ${AWS::StackName}-EcsSecurityGroupId\n```\n\nLoad the cloudformation plugin in a config file.\n\necspresso.yml\n```yaml\n# ...\nplugins:\n  - name: cloudformation\n```\n\n`cfn_output StackName OutputKey` looks up the OutputValue of OutputKey in the StackName.\n`cfn_export ExportName` looks up the exported value by name.\n\necs-service-def.json\n```json\n{\n  \"networkConfiguration\": {\n    \"awsvpcConfiguration\": {\n      \"subnets\": [\n        \"{{ cfn_output `ECS-ecspresso` `SubnetAz1` }}\",\n        \"{{ cfn_output `ECS-ecspresso` `SubnetAz2` }}\"\n      ],\n      \"securityGroups\": [\n        \"{{ cfn_export `ECS-ecspresso-EcsSecurityGroupId` }}\"\n      ]\n    }\n  }\n}\n```\n\n#### Jsonnet functions `cfn_output`, `cfn_export`\n\nSimilar features are also supported for Jsonnet.\n\n\n```jsonnet\nlocal cfn_output = std.native('cfn_output');\nlocal cfn_export = std.native('cfn_export');\n{\n  subnets: [\n    cfn_output('ECS-ecspresso', 'SubnetAz1'),\n    cfn_output('ECS-ecspresso', 'SubnetAz2'),\n  ],\n  securityGroups: [\n    cfn_export('ECS-ecspresso-EcsSecurityGroupId'),\n  ],\n}\n```\n\n### SSM Parameter Store lookups\n\nThe `ssm` template function reads parameters from AWS Systems Manager (SSM) Parameter Store.\n\nGiven SSM Parameter Store has the following parameters:\n\n- name: '/path/to/string', type: String, value: \"ImString\"\n- name: '/path/to/stringlist', type: StringList, value: \"ImStringList0,ImStringList1\"\n- name: '/path/to/securestring', type: SecureString, value: \"ImSecureString\"\n\nThis template,\n\n```json\n{\n  \"string\": \"{{ ssm `/path/to/string` }}\",\n  \"stringlist\": \"{{ ssm `/path/to/stringlist` 1 }}\",  *1\n  \"securestring\": \"{{ ssm `/path/to/securestring` }}\"\n}\n```\n\nwill be rendered as:\n\n```json\n{\n  \"string\": \"ImString\",\n  \"stringlist\": \"ImStringList1\",\n  \"securestring\": \"ImSecureString\"\n}\n```\n\n#### Jsonnet functions `ssm`, `ssm_list`\n\nThe `ssm` function works the same as template function. For string list parameters, use `ssm_list` to specify the index.\n\n```jsonnet\nlocal ssm = std.native('ssm');\nlocal ssm_list = std.native('ssm_list');\n{\n  string: ssm('/path/to/string'),\n  stringlist: ssm_list('/path/to/stringlist', 1),\n  securestring: ssm('/path/to/securestring'),\n}\n```\n\n### Resolve secretsmanager secret ARN\n\nThe `secretsmanager_arn` template function resolves the Secrets Manager secret ARN by secret name.\n\n```go-template\n  \"secrets\": [\n    {\n      \"name\": \"FOO\",\n      \"valueFrom\": \"{{ secretsmanager_arn `foo` }}\"\n    }\n  ]\n```\n\nwill be rendered as:\n\n```json\n  \"secrets\": [\n    {\n      \"name\": \"FOO\",\n      \"valueFrom\": \"arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:foo-06XQOH\"\n    }\n  ]\n```\n\n#### Jsonnet function `secretsmanager_arn`\n\nThe `secretsmanager_arn` function works the same as template function.\n\n```jsonnet\nlocal secretsmanager_arn = std.native('secretsmanager_arn');\n{\n  secrets: [\n    {\n      name: \"FOO\",\n      valueFrom: secretsmanager_arn('foo'),\n    }\n  ]\n}\n```\n\n### Execute external commands\n\nThe `external` plugin introduces functions to execute any external commands.\n\nFor example, `jq -n \"{ Now: now | todateiso8601\" }` returns the current date in ISO8601 format as a JSON object.\n\n```console\n$ jq -n \"{ Now: now | todateiso8601 }\"\n{\n  \"Now\": \"2024-10-25T16:13:22Z\"\n}\n```\n\nYou can use this command as a template function in the definition files.\n\nFirst, define the plugin in the configuration file.\n\necspresso.yml\n```yaml\nplugins:\n  - name: external\n    config:\n      name: jq\n      command: [\"jq\", \"-n\"]\n      num_args: 1\n      timeout: 5\n```\n\nThe `config` section defines the following parameters:\n\n- `name`: template function name\n- `command`: external command and arguments (array)\n  - The command must return a JSON string or any strings to stdout.\n- `num_args`: number of arguments (optional, default 0)\n- `parser`: parser type \"json\" or \"string\" (optional, default \"json\")\n- `timeout`: command execution timeout seconds (optional, default never timeout)\n\nAnd use the template function in the definition files as follows.\n\n```jsonnet\nlocal jq = std.native('jq');\n{\n  today: jq('{ Now: now | todateiso8601 }').Now,\n}\n```\n\n```go-template\n{\n  \"today\": \"{{ (jq `{Now: now | todateiso8601}`).Now }}\"\n}\n```\n\n## LICENSE\n\nMIT\n\n## Author\n\nKAYAC Inc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkayac%2Fecspresso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkayac%2Fecspresso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkayac%2Fecspresso/lists"}