env-secrets 0.5.3 → 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.
- package/.claude/rules/cicd.md +189 -0
- package/.claude/rules/docs.md +96 -0
- package/.claude/rules/git-hooks.md +43 -0
- package/.claude/rules/local-dev-badges.md +91 -0
- package/.claude/rules/local-dev-env.md +382 -0
- package/.claude/rules/local-dev-license.md +104 -0
- package/.claude/rules/local-dev-mcp.md +70 -0
- package/.claude/rules/observability.md +23 -0
- package/.claude/rules/publishing-api.md +158 -0
- package/.claude/rules/publishing-apps.md +204 -0
- package/.claude/rules/publishing-apt.md +146 -0
- package/.claude/rules/publishing-brew.md +110 -0
- package/.claude/rules/publishing-cli.md +238 -0
- package/.claude/rules/publishing-libraries.md +115 -0
- package/.claude/rules/publishing-sdks.md +109 -0
- package/.claude/rules/publishing-web.md +185 -0
- package/.claude/rules/typescript-linting.md +141 -0
- package/.claude/rules/typescript-logging.md +356 -0
- package/.claude/rules/typescript-testing.md +185 -0
- package/.claude/settings.json +18 -0
- package/.claude/skills/github-health-check.skill +0 -0
- package/.codex/rules/cicd.md +21 -0
- package/.codex/rules/docs.md +98 -0
- package/.codex/rules/git-hooks.md +43 -0
- package/.codex/rules/github-health-check.md +440 -0
- package/.codex/rules/local-dev-env.md +47 -0
- package/.codex/rules/local-dev-license.md +3 -1
- package/.codex/rules/publishing-api.md +160 -0
- package/.codex/rules/publishing-apps.md +206 -0
- package/.codex/rules/publishing-apt.md +148 -0
- package/.codex/rules/publishing-brew.md +112 -0
- package/.codex/rules/publishing-cli.md +240 -0
- package/.codex/rules/publishing-libraries.md +117 -0
- package/.codex/rules/publishing-sdks.md +111 -0
- package/.codex/rules/publishing-web.md +187 -0
- package/.codex/rules/typescript-linting.md +143 -0
- package/.codex/rules/typescript-logging.md +358 -0
- package/.codex/rules/typescript-testing.md +187 -0
- package/.github/workflows/deploy-docs.yml +1 -1
- package/.github/workflows/unittests.yaml +1 -1
- package/.rulesrc.json +20 -0
- package/AGENTS.md +34 -0
- package/CLAUDE.md +58 -0
- package/README.md +17 -3
- package/__e2e__/aws-secret-value-args.test.ts +142 -0
- package/__tests__/cli/helpers.test.ts +35 -0
- package/dist/cli/helpers.js +13 -1
- package/dist/index.js +79 -40
- package/docs/AWS.md +42 -13
- package/package.json +5 -5
- package/src/cli/helpers.ts +16 -0
- package/src/index.ts +97 -48
|
@@ -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
|
+
[](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
|
+
[](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.
|