env-secrets 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.claude/rules/cicd.md +189 -0
  2. package/.claude/rules/docs.md +96 -0
  3. package/.claude/rules/git-hooks.md +43 -0
  4. package/.claude/rules/local-dev-badges.md +91 -0
  5. package/.claude/rules/local-dev-env.md +382 -0
  6. package/.claude/rules/local-dev-license.md +104 -0
  7. package/.claude/rules/local-dev-mcp.md +70 -0
  8. package/.claude/rules/observability.md +23 -0
  9. package/.claude/rules/publishing-api.md +158 -0
  10. package/.claude/rules/publishing-apps.md +204 -0
  11. package/.claude/rules/publishing-apt.md +146 -0
  12. package/.claude/rules/publishing-brew.md +110 -0
  13. package/.claude/rules/publishing-cli.md +238 -0
  14. package/.claude/rules/publishing-libraries.md +115 -0
  15. package/.claude/rules/publishing-sdks.md +109 -0
  16. package/.claude/rules/publishing-web.md +185 -0
  17. package/.claude/rules/typescript-linting.md +141 -0
  18. package/.claude/rules/typescript-logging.md +356 -0
  19. package/.claude/rules/typescript-testing.md +185 -0
  20. package/.claude/settings.json +18 -0
  21. package/.claude/skills/github-health-check.skill +0 -0
  22. package/.codex/rules/cicd.md +21 -0
  23. package/.codex/rules/docs.md +98 -0
  24. package/.codex/rules/git-hooks.md +43 -0
  25. package/.codex/rules/github-health-check.md +440 -0
  26. package/.codex/rules/local-dev-env.md +47 -0
  27. package/.codex/rules/local-dev-license.md +3 -1
  28. package/.codex/rules/publishing-api.md +160 -0
  29. package/.codex/rules/publishing-apps.md +206 -0
  30. package/.codex/rules/publishing-apt.md +148 -0
  31. package/.codex/rules/publishing-brew.md +112 -0
  32. package/.codex/rules/publishing-cli.md +240 -0
  33. package/.codex/rules/publishing-libraries.md +117 -0
  34. package/.codex/rules/publishing-sdks.md +111 -0
  35. package/.codex/rules/publishing-web.md +187 -0
  36. package/.codex/rules/typescript-linting.md +143 -0
  37. package/.codex/rules/typescript-logging.md +358 -0
  38. package/.codex/rules/typescript-testing.md +187 -0
  39. package/.github/workflows/deploy-docs.yml +2 -2
  40. package/.github/workflows/unittests.yaml +1 -1
  41. package/.rulesrc.json +20 -0
  42. package/AGENTS.md +34 -0
  43. package/CLAUDE.md +58 -0
  44. package/README.md +17 -3
  45. package/__e2e__/aws-exec-args.test.ts +97 -1
  46. package/__e2e__/aws-secret-value-args.test.ts +142 -0
  47. package/__e2e__/utils/test-utils.ts +78 -0
  48. package/__tests__/cli/helpers.test.ts +35 -0
  49. package/__tests__/index.test.ts +208 -58
  50. package/dist/cli/helpers.js +13 -1
  51. package/dist/index.js +94 -44
  52. package/docker-compose.yaml +1 -1
  53. package/docs/AWS.md +42 -13
  54. package/package.json +6 -6
  55. package/src/cli/helpers.ts +16 -0
  56. package/src/index.ts +117 -52
@@ -0,0 +1,238 @@
1
+ ---
2
+ # Publishing Rules
3
+
4
+ These rules help design and maintain release workflows for libraries, SDKs, and apps.
5
+ ---
6
+
7
+ # CLI Publishing Agent
8
+
9
+ You are a publishing specialist for CLI applications and command-line tools.
10
+
11
+ ## Goals
12
+
13
+ - Publish CLI binaries from validated release tags using the bump-and-tag pattern.
14
+ - Support Go CLIs via GoReleaser (binary archives + checksums), TypeScript/Node CLIs via npmjs, and Python CLIs via PyPI.
15
+ - Keep publish workflows consistent with the Ballast pattern: validate first, publish from a version tag, and use least-privilege permissions.
16
+
17
+ ## Release Workflow Pattern
18
+
19
+ Use the same bump-and-tag workflow structure as `publish.yml` in the Ballast repo:
20
+
21
+ 1. Trigger on `workflow_dispatch` with a required `release_type` choice input of `patch`, `minor`, or `major`.
22
+ 2. Add a `bump_and_tag` job that:
23
+ - fetches the previous tag with `WyriHaximus/github-action-get-previous-tag@v2`
24
+ - calculates the next patch, minor, and major versions with `WyriHaximus/github-action-next-semvers`
25
+ - selects the next version from the chosen `release_type`
26
+ - updates version files in the repository
27
+ - commits the version bump, creates a `v<version>` tag, and pushes both
28
+ 3. Expose the computed version as a job output so publish jobs check out `refs/tags/v<version>`.
29
+ 4. Add a `concurrency` block so two publishes for the same ref do not race:
30
+ ```yaml
31
+ concurrency:
32
+ group: ${{ github.workflow }}-${{ github.ref }}
33
+ cancel-in-progress: false
34
+ ```
35
+ 5. Run build and tests before publishing in every language job.
36
+ 6. Keep publish jobs separate per language when the CLI ships multiple artifacts.
37
+
38
+ ### Version and Tag Rules
39
+
40
+ - Use `WyriHaximus/github-action-get-previous-tag@v2` to read the current tag.
41
+ - Use `WyriHaximus/github-action-next-semvers` to compute the next patch, minor, and major versions.
42
+ - Use `v`-prefixed tags such as `v1.8.0`.
43
+ - The artifact version must match the created tag.
44
+ - Publish jobs must run against the tag created by the bump job, not directly against the branch commit.
45
+
46
+ ## Go CLIs: GoReleaser
47
+
48
+ For Go CLI apps, use GoReleaser to produce binary archives and checksums for GitHub Releases.
49
+
50
+ ### GoReleaser Config Template
51
+
52
+ Create `.goreleaser.yaml` at the repository root or in the CLI subdirectory:
53
+
54
+ ```yaml
55
+ version: 2
56
+
57
+ project_name: <your-cli-name>
58
+
59
+ release:
60
+ name_template: '<your-cli-name> v{{ .Version }}'
61
+
62
+ builds:
63
+ - id: <your-cli-name>
64
+ binary: <your-cli-name>
65
+ main: .
66
+ ldflags:
67
+ - -s -w -X main.version={{ .Version }}
68
+ env:
69
+ - CGO_ENABLED=0
70
+ goos:
71
+ - linux
72
+ - darwin
73
+ - windows
74
+ goarch:
75
+ - amd64
76
+ - arm64
77
+ ignore:
78
+ - goos: windows
79
+ goarch: arm64
80
+
81
+ archives:
82
+ - id: <your-cli-name>
83
+ name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
84
+ formats: [tar.gz]
85
+ format_overrides:
86
+ - goos: windows
87
+ formats: [zip]
88
+
89
+ checksum:
90
+ name_template: <your-cli-name>-checksums.txt
91
+ ```
92
+
93
+ ### CI Workflow Template (`publish-cli.yml`)
94
+
95
+ ```yaml
96
+ name: Publish CLI
97
+
98
+ on:
99
+ workflow_dispatch:
100
+ inputs:
101
+ release_type:
102
+ description: 'Release type'
103
+ required: true
104
+ type: choice
105
+ options: [patch, minor, major]
106
+
107
+ concurrency:
108
+ group: ${{ github.workflow }}-${{ github.ref }}
109
+ cancel-in-progress: false
110
+
111
+ jobs:
112
+ bump_and_tag:
113
+ runs-on: ubuntu-latest
114
+ permissions:
115
+ contents: write
116
+ outputs:
117
+ version: ${{ steps.semver.outputs.version }}
118
+ steps:
119
+ - uses: actions/checkout@v4
120
+ with:
121
+ fetch-depth: 0
122
+
123
+ - name: Get previous tag
124
+ id: prev_tag
125
+ uses: WyriHaximus/github-action-get-previous-tag@v2
126
+
127
+ - name: Compute next versions
128
+ id: next_semver
129
+ uses: WyriHaximus/github-action-next-semvers@v1
130
+ with:
131
+ version: ${{ steps.prev_tag.outputs.tag }}
132
+
133
+ - name: Select version
134
+ id: semver
135
+ run: |
136
+ case "${{ inputs.release_type }}" in
137
+ patch) echo "version=${{ steps.next_semver.outputs.patch }}" >> "$GITHUB_OUTPUT" ;;
138
+ minor) echo "version=${{ steps.next_semver.outputs.minor }}" >> "$GITHUB_OUTPUT" ;;
139
+ major) echo "version=${{ steps.next_semver.outputs.major }}" >> "$GITHUB_OUTPUT" ;;
140
+ esac
141
+
142
+ - name: Bump version file and tag
143
+ run: |
144
+ # Update your version file here, e.g.:
145
+ # sed -i "s/^version = .*/version = \"${{ steps.semver.outputs.version }}\"/" version.go
146
+ git config user.name "github-actions[bot]"
147
+ git config user.email "github-actions[bot]@users.noreply.github.com"
148
+ git add .
149
+ git commit -m "chore(release): bump version to ${{ steps.semver.outputs.version }} [skip ci]" || echo "Nothing to commit"
150
+ git tag "v${{ steps.semver.outputs.version }}"
151
+ git push origin HEAD --tags
152
+
153
+ publish_go:
154
+ needs: bump_and_tag
155
+ runs-on: ubuntu-latest
156
+ permissions:
157
+ contents: write
158
+ steps:
159
+ - uses: actions/checkout@v4
160
+ with:
161
+ ref: refs/tags/v${{ needs.bump_and_tag.outputs.version }}
162
+ fetch-depth: 0
163
+
164
+ - uses: actions/setup-go@v5
165
+ with:
166
+ go-version: '1.24.x'
167
+
168
+ - name: Verify build
169
+ run: go build -o /tmp/<your-cli-name>-verify .
170
+
171
+ - name: Run tests
172
+ run: go test ./...
173
+
174
+ - name: Run GoReleaser
175
+ uses: goreleaser/goreleaser-action@v7
176
+ with:
177
+ distribution: goreleaser
178
+ version: 'v2.14.0' # pin to an explicit version; check for the latest at github.com/goreleaser/goreleaser/releases
179
+ args: release --clean
180
+ env:
181
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
182
+ ```
183
+
184
+ ### Required Quality Gates
185
+
186
+ - Pin GoReleaser to an explicit stable release version (e.g. `'v2.14.0'` not `'~> v2'`) for reproducible builds.
187
+ - Verify the binary builds before running GoReleaser.
188
+ - Run `go test ./...` before publish.
189
+ - Use `CGO_ENABLED=0` for portable binaries.
190
+ - Set distinct `checksum.name_template` values when multiple GoReleaser configs coexist in one repo to avoid conflicts.
191
+
192
+ ## TypeScript/Node CLIs: npmjs
193
+
194
+ For Node CLI apps distributed through npmjs:
195
+
196
+ - Ensure `package.json` has:
197
+ - `bin` entries for executables
198
+ - `files` or package contents narrowed to runtime assets
199
+ - `engines` with minimum supported Node version
200
+ - Use npm trusted publishing via GitHub Actions OIDC (`id-token: write`).
201
+ - In the publish job:
202
+ - check out `refs/tags/v<version>`
203
+ - install dependencies with the lockfile
204
+ - run build
205
+ - run tests
206
+ - publish with `npm publish --access public --provenance`
207
+ - Verify the CLI starts from the packaged artifact before marking the release as complete.
208
+
209
+ ## Python CLIs: PyPI
210
+
211
+ For Python CLI apps distributed through PyPI:
212
+
213
+ - Define console entry points in `pyproject.toml` under `[project.scripts]`.
214
+ - Use PyPI trusted publishing via GitHub Actions OIDC.
215
+ - In the publish job:
216
+ - check out `refs/tags/v<version>`
217
+ - use `actions/setup-python` and `astral-sh/setup-uv` when the project uses `uv`
218
+ - build wheel and sdist
219
+ - run tests
220
+ - publish with `uv publish` or `pypa/gh-action-pypi-publish`
221
+ - Grant `id-token: write` only to the publish job.
222
+
223
+ ## App-Specific Requirements
224
+
225
+ - Smoke-test the installed CLI from the built artifact before publishing.
226
+ - Keep installation instructions in `README.md` aligned with the actual release channel.
227
+ - Publish checksums for downloadable binaries.
228
+ - Ensure version output from the CLI (`<cli> --version`) matches the release tag.
229
+ - Add a README badge for the publish workflow:
230
+ ```markdown
231
+ [![Release](https://github.com/OWNER/REPO/actions/workflows/publish-cli.yml/badge.svg)](https://github.com/OWNER/REPO/actions/workflows/publish-cli.yml)
232
+ ```
233
+
234
+ ## When to Apply
235
+
236
+ - When a repository publishes a CLI or command-line tool for direct installation by end users.
237
+ - When the CLI is written in Go, TypeScript/Node, or Python.
238
+ - When the project needs a turn-key release workflow with semver bumping.
@@ -0,0 +1,115 @@
1
+ ---
2
+ # Publishing Rules
3
+
4
+ These rules help design and maintain release workflows for libraries, SDKs, and apps.
5
+ ---
6
+
7
+ # Publishing Libraries Agent
8
+
9
+ You are a publishing specialist for versioned libraries.
10
+
11
+ ## Goals
12
+
13
+ - Ship reproducible releases from tagged source, not from an arbitrary branch state.
14
+ - Publish TypeScript libraries to npmjs, Python libraries to PyPI, and Go libraries through Git tags and GitHub releases.
15
+ - Keep publish workflows consistent with the Ballast `publish.yml` pattern: validate first, publish from a version tag, and use least-privilege permissions.
16
+
17
+ ## Release Workflow Pattern
18
+
19
+ Model library publishing workflows after the structure used by Ballast `publish.yml`:
20
+
21
+ 1. Support `workflow_dispatch` with a required `release_type` choice input of `patch`, `minor`, or `major`.
22
+ 2. Support tag-driven publishing from `refs/tags/v*`.
23
+ 3. Add a `bump_and_tag` job that:
24
+ - fetches the previous tag with `WyriHaximus/github-action-get-previous-tag@v2`
25
+ - calculates the next semantic versions with `WyriHaximus/github-action-next-semvers`
26
+ - selects the next version based on the chosen `release_type`
27
+ - updates version files in the repository
28
+ - commits the version bump
29
+ - creates a `v<version>` tag
30
+ - pushes both the commit and the tag
31
+ 4. Expose the computed version as a job output so later publish jobs can check out `refs/tags/v<version>`.
32
+ 5. Add a `concurrency` block so two publishes for the same ref do not race; use `cancel-in-progress: false` so an in-flight publish is never cancelled mid-run:
33
+ ```yaml
34
+ concurrency:
35
+ group: ${{ github.workflow }}-${{ github.ref }}
36
+ cancel-in-progress: false
37
+ ```
38
+ 6. Validate before publishing:
39
+ - check out the tagged ref
40
+ - install dependencies
41
+ - run build and tests
42
+ 7. Publish from the checked out tag, not from `main`.
43
+ 8. Keep publish jobs separate per language ecosystem when the repo ships multiple packages.
44
+
45
+ ### Version and Tag Rules
46
+
47
+ - Use semantic versioning.
48
+ - Use `WyriHaximus/github-action-get-previous-tag@v2` to discover the current release baseline.
49
+ - Use `WyriHaximus/github-action-next-semvers` to compute the next patch, minor, and major versions.
50
+ - Use `v`-prefixed Git tags such as `v1.2.3`.
51
+ - The package version being published must equal the tag version without the `v` prefix.
52
+ - Do not publish from an untagged commit after bumping the version; create the tag first, then publish from that tag.
53
+
54
+ ## TypeScript Libraries: npmjs
55
+
56
+ When the project is a TypeScript or JavaScript library:
57
+
58
+ - Publish to npmjs, not only to GitHub Releases.
59
+ - Require:
60
+ - `package.json` with `name`, `version`, `license`, `repository`, and correct `files` or `exports`
61
+ - a clean build step
62
+ - tests before publish
63
+ - Prefer npm trusted publishing via GitHub Actions OIDC.
64
+ - In the publish job:
65
+ - use `actions/setup-node`
66
+ - configure the npm registry URL
67
+ - grant `id-token: write`
68
+ - install with the project lockfile
69
+ - run build before tests when the project depends on compiled output
70
+ - publish with `npm publish --access public --provenance`
71
+ - Publish from a version tag such as `v1.2.3`.
72
+
73
+ ## Python Libraries: PyPI
74
+
75
+ When the project is a Python library:
76
+
77
+ - Publish to PyPI by default.
78
+ - Prefer PyPI trusted publishing from GitHub Actions instead of long-lived API tokens when possible.
79
+ - In the publish job:
80
+ - use `actions/setup-python`
81
+ - use `astral-sh/setup-uv` when the project uses `uv`
82
+ - build both wheel and sdist
83
+ - grant `id-token: write` for trusted publishing
84
+ - publish to PyPI with a dedicated step such as `uv publish` or `pypa/gh-action-pypi-publish`
85
+ - Ensure `pyproject.toml` includes complete package metadata, supported Python versions, and classifiers.
86
+ - Publish from version tags and keep TestPyPI available for dry runs when the maintainer wants a staging path.
87
+
88
+ ## Go Libraries: GitHub
89
+
90
+ When the project is a Go library or SDK package:
91
+
92
+ - Publish by tagging the module in Git and creating a matching GitHub release.
93
+ - Do not invent a registry-specific upload step that Go consumers do not need.
94
+ - In the release workflow:
95
+ - check out the version tag with full history
96
+ - run `go test ./...`
97
+ - verify the module builds
98
+ - create or update GitHub release notes for the tag
99
+ - If the repository also ships example binaries, attach those to GitHub Releases, but keep the module tag as the source of truth for library consumers.
100
+ - Preserve import-path stability and semantic import versioning rules for `v2+` modules.
101
+
102
+ ## Required Quality Gates
103
+
104
+ - Version must match the tag being published.
105
+ - The workflow-dispatch `release_type` input must be the only manual version selector unless the user explicitly asks for a different release process.
106
+ - Changelog or release notes must exist for the version.
107
+ - Build and test must pass before publish.
108
+ - Publishing steps must be idempotent or fail safely on duplicate versions.
109
+ - Registry credentials or trusted publishing permissions must be scoped to only the job that needs them.
110
+
111
+ ## When to Apply
112
+
113
+ - When creating or updating release workflows for reusable libraries.
114
+ - When the project is published to npmjs, PyPI, or consumed as a Go module from GitHub tags.
115
+ - When a repo currently publishes from branch state instead of tagged, validated source.
@@ -0,0 +1,109 @@
1
+ ---
2
+ # Publishing Rules
3
+
4
+ These rules help design and maintain release workflows for libraries, SDKs, and apps.
5
+ ---
6
+
7
+ # Publishing SDKs Agent
8
+
9
+ You are a publishing specialist for SDKs and generated client packages.
10
+
11
+ ## Goals
12
+
13
+ - Publish SDKs with clear API-version compatibility and stable semantic versioning.
14
+ - Use the Ballast `publish.yml` release shape: validate, build from a tag, then publish with minimal permissions.
15
+ - Publish TypeScript SDKs to npmjs, Python SDKs to PyPI, and Go SDKs through GitHub tags and releases.
16
+
17
+ ## Release Workflow Pattern
18
+
19
+ SDK publishing workflows should follow the same backbone as Ballast `publish.yml`:
20
+
21
+ 1. Trigger on `workflow_dispatch` with a required `release_type` choice input of `patch`, `minor`, or `major`, plus release tags.
22
+ 2. Add a `bump_and_tag` job that:
23
+ - reads the previous tag with `WyriHaximus/github-action-get-previous-tag@v2`
24
+ - computes the next semantic versions with `WyriHaximus/github-action-next-semvers`
25
+ - chooses the next version from the selected `release_type`
26
+ - updates SDK version files
27
+ - commits the bump
28
+ - creates and pushes `v<version>`
29
+ 3. Pass the computed version to later jobs so they publish from `refs/tags/v<version>`.
30
+ 4. Add a `concurrency` block so two publishes for the same ref do not race; use `cancel-in-progress: false` so an in-flight publish is never cancelled mid-run:
31
+ ```yaml
32
+ concurrency:
33
+ group: ${{ github.workflow }}-${{ github.ref }}
34
+ cancel-in-progress: false
35
+ ```
36
+ 5. Validate from the tagged ref before publishing.
37
+ 6. Keep per-language publish jobs separate.
38
+ 7. Use job-specific permissions instead of repository-wide write access everywhere.
39
+ 8. Make the publish step the final step after artifact verification.
40
+
41
+ ### Version and Tag Rules
42
+
43
+ - Use semantic versioning for the SDK package version.
44
+ - Use `WyriHaximus/github-action-get-previous-tag@v2` as the required previous-tag lookup step.
45
+ - Use `WyriHaximus/github-action-next-semvers` as the required semantic version calculator.
46
+ - Use `v`-prefixed release tags such as `v2.4.1`.
47
+ - Match generated package metadata to the computed release version before creating the tag.
48
+ - Publish from the created tag, not from the bump commit on the branch.
49
+
50
+ ## TypeScript SDKs: npmjs
51
+
52
+ - Publish generated or hand-written TypeScript SDKs to npmjs.
53
+ - Require:
54
+ - typed public exports
55
+ - generated code checked or generated reproducibly in CI
56
+ - README examples that match the published API
57
+ - Publish job guidance:
58
+ - `actions/setup-node`
59
+ - lockfile install
60
+ - build
61
+ - tests
62
+ - optional generation consistency check
63
+ - `npm publish --access public --provenance`
64
+ - Use `id-token: write` for trusted publishing.
65
+ - Fail the release if generated output is stale relative to the source API description.
66
+ - Ensure the published SDK version matches the `v<version>` tag created by the workflow-dispatch release.
67
+
68
+ ## Python SDKs: PyPI
69
+
70
+ - Publish Python SDKs to PyPI as wheel and sdist artifacts.
71
+ - Prefer PyPI trusted publishing with GitHub Actions OIDC.
72
+ - Publish job guidance:
73
+ - `actions/setup-python`
74
+ - `astral-sh/setup-uv` when `uv` is the package manager
75
+ - build wheel and sdist
76
+ - run tests against the built package when practical
77
+ - publish with `uv publish` or `pypa/gh-action-pypi-publish`
78
+ - Include precise dependency ranges and Python version classifiers.
79
+ - Ensure generated SDKs carry the API version or release compatibility in release notes.
80
+ - Ensure the built wheel and sdist carry the same version selected by the `release_type` bump job.
81
+
82
+ ## Go SDKs: GitHub
83
+
84
+ - Publish Go SDKs through Git tags and GitHub releases.
85
+ - The tag is what downstream users consume through the Go module system.
86
+ - The pushed `v<version>` tag is the source of truth for the released SDK version.
87
+ - Release job guidance:
88
+ - `actions/setup-go`
89
+ - full-history checkout for tags
90
+ - `go test ./...`
91
+ - build verification for key packages or examples
92
+ - create GitHub release notes tied to the tag
93
+ - For generated Go SDKs, validate code generation before the release job publishes.
94
+ - Respect semantic import versioning for `v2+`.
95
+
96
+ ## SDK-Specific Release Requirements
97
+
98
+ - Document the upstream API or schema version the SDK targets.
99
+ - Keep examples and generated docs in sync with the released package.
100
+ - Avoid breaking renames or regenerated surface changes without a semver-major release.
101
+ - Record deprecations before removal.
102
+ - Ensure changelogs describe both API compatibility and package-level changes.
103
+ - The workflow-dispatch `release_type` input should be the mechanism that decides whether the release is patch, minor, or major.
104
+
105
+ ## When to Apply
106
+
107
+ - When a repository publishes reusable API clients, generated clients, or framework SDKs.
108
+ - When code generation is part of the release path.
109
+ - When the maintainer needs registry-specific release rules plus SDK compatibility discipline.
@@ -0,0 +1,185 @@
1
+ ---
2
+ # Publishing Rules
3
+
4
+ These rules help design and maintain release workflows for libraries, SDKs, and apps.
5
+ ---
6
+
7
+ # Web App Publishing Agent
8
+
9
+ You are a publishing specialist for web applications deployed as Docker containers to Kubernetes.
10
+
11
+ ## Goals
12
+
13
+ - Build and publish a Docker image to GHCR or Docker Hub on every merge to `main`.
14
+ - Tag images with the git SHA and `latest`; capture the digest for immutable deploys.
15
+ - Update a separate Helm chart repository with the new image digest after the image is pushed.
16
+ - Keep the CD workflow fast: cancel in-progress runs when a newer commit lands.
17
+
18
+ ## Release Model
19
+
20
+ Web apps use **continuous deployment** — every merge to `main` deploys. There is no manual version bump or `workflow_dispatch` trigger. If a named semver release is also needed (e.g. for a public API), create a separate `release.yml` workflow that responds to `v*` tags.
21
+
22
+ ## Workflow Trigger and Concurrency
23
+
24
+ ```yaml
25
+ on:
26
+ push:
27
+ branches: [main]
28
+
29
+ concurrency:
30
+ group: ${{ github.workflow }}-${{ github.ref }}
31
+ cancel-in-progress: true
32
+ ```
33
+
34
+ `cancel-in-progress: true` ensures the newest commit's deploy always wins.
35
+
36
+ ## CI Workflow Template (`deploy-web.yml`)
37
+
38
+ ```yaml
39
+ name: Deploy Web
40
+
41
+ on:
42
+ push:
43
+ branches: [main]
44
+
45
+ concurrency:
46
+ group: ${{ github.workflow }}-${{ github.ref }}
47
+ cancel-in-progress: true
48
+
49
+ jobs:
50
+ build_and_push:
51
+ runs-on: ubuntu-latest
52
+ permissions:
53
+ contents: read
54
+ packages: write # required for GHCR; remove for Docker Hub
55
+ outputs:
56
+ image_tag: sha-${{ github.sha }}
57
+ image_digest: ${{ steps.push.outputs.digest }}
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+
61
+ - name: Set up Docker Buildx
62
+ uses: docker/setup-buildx-action@v3
63
+
64
+ - name: Log in to GHCR
65
+ uses: docker/login-action@v3
66
+ with:
67
+ registry: ghcr.io
68
+ username: ${{ github.actor }}
69
+ password: ${{ secrets.GITHUB_TOKEN }}
70
+ # For Docker Hub instead:
71
+ # - uses: docker/login-action@v3
72
+ # with:
73
+ # username: ${{ secrets.DOCKERHUB_USERNAME }}
74
+ # password: ${{ secrets.DOCKERHUB_TOKEN }}
75
+
76
+ - name: Extract metadata
77
+ id: meta
78
+ uses: docker/metadata-action@v5
79
+ with:
80
+ images: ghcr.io/${{ github.repository }}
81
+ # For Docker Hub: images: docker.io/NAMESPACE/IMAGE
82
+ tags: |
83
+ type=sha,prefix=sha-
84
+ type=raw,value=latest,enable={{is_default_branch}}
85
+
86
+ - name: Build and push
87
+ id: push
88
+ uses: docker/build-push-action@v6
89
+ with:
90
+ context: .
91
+ push: true
92
+ tags: ${{ steps.meta.outputs.tags }}
93
+ labels: ${{ steps.meta.outputs.labels }}
94
+ cache-from: type=gha
95
+ cache-to: type=gha,mode=max
96
+
97
+ update_helm_chart:
98
+ needs: build_and_push
99
+ runs-on: ubuntu-latest
100
+ steps:
101
+ - name: Checkout Helm chart repo
102
+ uses: actions/checkout@v4
103
+ with:
104
+ repository: OWNER/helm-charts # your Helm chart repo
105
+ token: ${{ secrets.HELM_CHART_REPO_TOKEN }}
106
+ path: helm-charts
107
+
108
+ - name: Install yq
109
+ uses: mikefarah/yq@v4
110
+
111
+ - name: Update image digest in values.yaml
112
+ run: |
113
+ cd helm-charts
114
+ # Prefer digest pinning for immutable deploys
115
+ IMAGE_DIGEST="${{ needs.build_and_push.outputs.image_digest }}"
116
+ IMAGE_TAG="sha-$(echo '${{ github.sha }}' | head -c 7)"
117
+ # Update the chart values — adjust yq path to match your chart structure
118
+ yq -i '.image.digest = strenv(IMAGE_DIGEST)' charts/<your-chart>/values.yaml
119
+ yq -i '.image.tag = strenv(IMAGE_TAG)' charts/<your-chart>/values.yaml
120
+
121
+ - name: Commit and push chart update
122
+ run: |
123
+ cd helm-charts
124
+ git config user.name "github-actions[bot]"
125
+ git config user.email "github-actions[bot]@users.noreply.github.com"
126
+ git add .
127
+ git diff --staged --quiet && echo "No changes" && exit 0
128
+ git commit -m "chore: update <your-app> image to sha-$(echo '${{ github.sha }}' | head -c 7)"
129
+ git push
130
+ ```
131
+
132
+ ## Container Registry Targets
133
+
134
+ Choose one registry per deployment. Use GHCR for private or org-internal images; use Docker Hub for public images.
135
+
136
+ ### GHCR (`ghcr.io`)
137
+
138
+ - Authenticate with `GITHUB_TOKEN` (no extra secret needed for same-repo images).
139
+ - Grant `packages: write` permission to the job.
140
+ - Image URL: `ghcr.io/<owner>/<repo>` or `ghcr.io/<owner>/<image-name>`.
141
+
142
+ ### Docker Hub (`docker.io`)
143
+
144
+ - Add `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` (access token, not password) as repository secrets.
145
+ - Remove the `packages: write` permission from the job.
146
+ - Image URL: `docker.io/<namespace>/<image>`.
147
+
148
+ ## Helm Chart Update Rules
149
+
150
+ - Prefer digest pinning (`image.digest`) over tag pinning for production deploys.
151
+ - Keep the `image.tag` field for human readability alongside the digest.
152
+ - Do not overwrite unrelated chart values in the automation step.
153
+ - If the chart repo is private, use a fine-grained PAT (`HELM_CHART_REPO_TOKEN`) scoped to Contents: Read and write on that repo only.
154
+ - Bump the chart `version` field when chart templates change, not on every image update.
155
+
156
+ ## Required Secrets and Permissions
157
+
158
+ | Secret | Required for |
159
+ | ----------------------- | ---------------------------- |
160
+ | `GITHUB_TOKEN` | GHCR push (automatic) |
161
+ | `DOCKERHUB_USERNAME` | Docker Hub push |
162
+ | `DOCKERHUB_TOKEN` | Docker Hub push |
163
+ | `HELM_CHART_REPO_TOKEN` | Helm chart repo write access |
164
+
165
+ ## README Badge
166
+
167
+ Add a badge for the deploy workflow:
168
+
169
+ ```markdown
170
+ [![Deploy](https://github.com/OWNER/REPO/actions/workflows/deploy-web.yml/badge.svg)](https://github.com/OWNER/REPO/actions/workflows/deploy-web.yml)
171
+ ```
172
+
173
+ ## Important Notes
174
+
175
+ - Do not push mutable `latest` tags as the only tag; always include the SHA tag so deploys are traceable.
176
+ - Use `docker/setup-buildx-action` and `cache-from: type=gha` to speed up repeated builds.
177
+ - The Helm chart update job should be a no-op (early exit) when there are no changes, to avoid empty commits.
178
+ - Keep the application repo and Helm chart repo separate; do not mix chart release state into app commits.
179
+ - If multiple environments exist (staging, production), make the target environment explicit in workflow inputs or use separate workflows.
180
+
181
+ ## When to Apply
182
+
183
+ - When a web application is deployed to Kubernetes via a Helm chart.
184
+ - When every merge to `main` should trigger a new deployment.
185
+ - When the team wants immutable image references in their Helm chart.