Repository navigation
ci: release the package with release-please - #44
aliaksandr-kazarez wants to merge 8 commits into
Conversation
a6282da to
5c59167
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The first-version behavior, graduation instructions, and mutable privileged action reference need correction.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds automated prerelease versioning, changelog generation, tagging, and GitHub Releases via release-please.
Changes:
- Configures alpha releases and Swift version-file updates.
- Adds manifest-based version tracking.
- Adds a GitHub App-authenticated release workflow.
File summaries
| File | Description |
|---|---|
release-please-config.json |
Defines prerelease and version-update behavior. |
.release-please-manifest.json |
Initializes package version tracking. |
.github/workflows/release-please.yml |
Runs release-please on main. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
66e8b8d to
8089fc5
Compare
8089fc5 to
e12d2c3
Compare
e12d2c3 to
61fc004
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Release authentication and the initial history cutoff remain unresolved, preventing a reliable first release.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (2)
Resolved since last review (3)
| app-id: ${{ secrets.SDK_RELEASE_BOT_APP_ID }} | ||
| private-key: ${{ secrets.SDK_RELEASE_BOT_PRIVATE_KEY }} |
| @@ -0,0 +1,22 @@ | |||
| { | |||
| "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", | |||
| "packages": { | |||
jlmitra-ampl
left a comment
There was a problem hiding this comment.
Reviewed for least privilege. The pattern matches session-replay-flutter, and it's tighter in several places (SHA pins, the verify gate, queued concurrency). Three permission-scoping comments are inline.
Two repo-settings items sit outside this diff; I'll raise them separately:
- The
release tagsruleset blocks delete, update and force-push onv*, but it doesn't restrict creation. Anyone with write access, or any workflow token withcontents: write, can create a release tag. For SPM that is a publish, and it can't be undone. Suggest adding acreationrule with the release App as the only bypass. - Actions settings: switch the default workflow permission to
read, and turn off "Allow GitHub Actions to create and approve pull requests".
Unrelated to permissions: the # v0 comment on 8091f292 is 5 commits behind the current v0 tag (820754f). Those commits don't touch release-please-action, but the comment is misleading.
| permissions: | ||
| contents: write | ||
| pull-requests: write |
There was a problem hiding this comment.
Least privilege: GITHUB_TOKEN doesn't need write here. Every write in this workflow goes through the App token. release-please-action only falls back to github.token when token is empty, and the token step fails before that can happen. So these two grants go unused. They also flow into the verify job. unit-test.yml's own contents: read caps them there, but only by accident. (This came over from session-replay-flutter, which has the same over-grant.)
Suggest denying everything at the top level and granting per job:
| permissions: | |
| contents: write | |
| pull-requests: write | |
| permissions: {} |
and then:
verify:
permissions:
contents: read
uses: ./.github/workflows/unit-test.yml
release-please:
permissions: {}| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | ||
| with: | ||
| app-id: ${{ secrets.SDK_RELEASE_BOT_APP_ID }} | ||
| private-key: ${{ secrets.SDK_RELEASE_BOT_PRIVATE_KEY }} |
There was a problem hiding this comment.
Narrow the App token. With no permission-* inputs, the token gets every permission the App's installation has. That matters most if we use the org-wide SDK release bot. release-please only needs contents and pull requests. It's already limited to this repo by default, since owner/repositories are unset.
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ secrets.SDK_RELEASE_BOT_APP_ID }} | |
| private-key: ${{ secrets.SDK_RELEASE_BOT_PRIVATE_KEY }} | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ secrets.SDK_RELEASE_BOT_APP_ID }} | |
| private-key: ${{ secrets.SDK_RELEASE_BOT_PRIVATE_KEY }} | |
| permission-contents: write | |
| permission-pull-requests: write |
If labelling the release PR fails (autorelease: pending), add permission-issues: write.
|
|
||
| release-please: | ||
| needs: verify | ||
| runs-on: ubuntu-24.04 |
There was a problem hiding this comment.
Keep the App key behind an environment. Put the App ID and private key in a release environment that only main can deploy to (Settings → Environments → Deployment branches: main). This repo is public and its default workflow permission is write. Any collaborator can open a pull request from a branch in this repo that adds a pull_request workflow, and that workflow can read repo-level secrets. Environment secrets are only released to jobs running on main. This applies directly if we go the repo-scoped App route, as session-replay-flutter does. If we stay on the org secrets instead, they should be limited to selected repositories.
| runs-on: ubuntu-24.04 | |
| runs-on: ubuntu-24.04 | |
| environment: release |
jlmitra-ampl
left a comment
There was a problem hiding this comment.
approving conditionally pending addressing comments
61ad843 to
102f53c
Compare
Adds the release pipeline. Modelled on session-replay-flutter, which runs the same setup on prerelease versions today. * release-please opens a version PR from conventional commits; merging it tags the repo and cuts the GitHub release * alpha prereleases via versioning "prerelease" + prerelease-type "alpha", so the first release is v0.0.1-alpha.1 * release-type "simple" because release-please has no Swift updater; files carrying a version go in extra-files with an x-release-please-version marker * no publish job: SPM resolves from the git tag, so tagging is publishing, and this SDK ships no podspec Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f8d387b6 was v3.0.0. bcd2ba49 is v3.2.0, the current v3 tag and the pin 16 other amplitude workflows already use. Same major, so the app-id and private-key inputs are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Matches what #48 established for the other workflows, with one inversion: cancel-in-progress is false. Cancelling a release run between the tag and the GitHub Release would strand a tag that the release tags ruleset forbids moving or deleting. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tagging is publishing for SPM, and the release tags ruleset makes a tag immutable the moment it is created. Two gaps closed ahead of the first one. release-please ran as a second workflow on the same push as the tests, so it could tag a commit whose matrix was still running or already red. It now calls unit-test.yml as a `verify` job and needs it. unit-test.yml drops its own push trigger so the matrix still runs exactly once on main. Nothing asserted that the tag and the version constant agree, though release-please writes both from the same number, and its generic updater skips a file that lost its annotation without a warning. A drift would ship events reporting a version that does not exist, permanently. lint.yml now compares the manifest against the constant; it is already a required check, so the release PR cannot merge with a drift. lint.yml also drops its push trigger. After the merge it gated nothing, and it runs on a larger runner, which is billed even on a public repo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Security review on the release workflow. GITHUB_TOKEN no longer gets contents and pull-requests write. Every write goes through the App token, so the workflow denies everything and grants verify only the contents read its checkout needs. The App token is narrowed to contents and pull requests; labelling a PR needs nothing more. The job runs in a `release` environment so the App key is released only to runs on main, not to any branch a collaborator pushes. The action is re-pinned to 820754f, the current v0. Nothing in the five commits between is loaded by the release-please action. The amplitude/actions action reimplements release-please and supports neither bootstrap-sha nor Release-As. The manifest therefore starts at 0.1.0-alpha.1, the release tagged by hand in #50, and the graduation steps now use a breaking-change title instead of a Release-As footer. prerelease-type and bump-patch-for-minor-pre-major are dropped: from an existing alpha the action bumps the alpha counter whatever they say. The README and docs pages join extra-files, so their version strings follow each release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the manifest at 0.1.0-alpha.1 and the constant still 0.0.0 on main, the version check held this PR until #50 merged, and #50 is blocked on taxonomy. At 0.0.0 the two agree again, and merging this first is harmless: the action looks for a v0.0.0 tag, finds none, and proposes nothing. #50 now carries the manifest bump alongside the constant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102f53c to
c5f6fce
Compare


Summary
Adds the release pipeline, modelled on
session-replay-flutter. It stacks on #50 (the0.1.0-alpha.1release), which sits onmain. On every push tomainthe workflow runs the unit-test matrix, thenamplitude/actions/release-please-actionopens or updates a release PR from conventional commits. When a release PR merges, the same action creates the GitHub release and its tag. SPM has no registry, so the tag is the publish. Therelease tagsruleset makes av*tag immutable once created, so the workflow is arranged to get each tag right the first time.The action is not googleapis/release-please. It reimplements it (
release-please-action/index.js, 654 lines). It has nobootstrap-shaand noRelease-As, and it finds the commits to release by comparing against the tag for the manifest version. With no tag it comparesmain...mainand proposes nothing. So the first release,v0.1.0-alpha.1, is tagged by hand from #50's merge, which carries the constant and the changelog. This PR starts the manifest at0.1.0-alpha.1to match. Its first run onmaincompares against that tag, finds only thisci:commit, and proposes nothing. After that, the action takes over:feat,fixand breaking changes all bumpalpha.Ntoalpha.N+1.Verify before tagging. The release job
needsaverifyjob that callsunit-test.yml, so a tag is only cut on a commit whose iOS/macOS/tvOS matrix is green.unit-test.ymlandlint.ymldrop theirpush: maintriggers. The matrix still runs once per merge, insideverify. Lint onmaingated nothing and ran on a billed larger runner.Version drift check. The action's file updater silently skips a file whose
x-release-please-versionmarker is gone, which would ship a tag reporting a different version on every event.lint.ymlnow fails when.release-please-manifest.jsonandStreamingAnalyticsInfo.versiondisagree. Lint is a required check, so a drifted release PR cannot merge.README.mdand the fourdocs/pages joinextra-files; #50 adds their markers.Credentials, per the security review.
GITHUB_TOKENgets nothing (permissions: {}), exceptcontents: readforverify. Every write goes through the App token.contents: writeandpull-requests: write. Labelling a PR needs nothing more.releaseenvironment that onlymaincan deploy to. The App key is therefore released only to runs onmain, not to a workflow any collaborator pushes on a branch.create-github-app-tokenatbcd2ba49(v3.2.0), the release action at820754f(v0), runnerubuntu-24.04, 10-minute timeout. Runs queue rather than cancel, because a run killed between the tag and the release would leave a tag no one can move.Needs before merging: the App installed on this repo, and
SDK_RELEASE_BOT_APP_ID/SDK_RELEASE_BOT_PRIVATE_KEYadded as secrets of thereleaseenvironment. Without them, the token step fails on every push tomain.Graduating to 1.0.0. In one PR, remove
versioning,prereleaseandbump-minor-pre-major, and title it as a breaking change, for examplefeat(sdk)!: graduate to 1.0.0. The semantic-title check rejects an unscopedfeat!:.Validation
c5f6fce: the manifest and constant are both0.1.0-alpha.1, and every workflow file parses. Before the rebase, at61ad843onmain, all checks were green. The version check proved itself atd8896a0, failing onmanifest 0.1.0-alpha.1 != StreamingAnalyticsInfo.version 0.0.0.8091f292(itsbumpVersionandupdateGenericFile) with this config:0.1.0-alpha.1,feat,fixandfeat(sdk)!each give0.1.0-alpha.2.feat(sdk)!gives1.0.0,featgives0.2.0andfixgives0.1.1.release-please.ymlruns only on pushes tomain. Theverify→ release chain, the environment and the narrowed token are first proven by the merge of this PR.Checklist
Prepared with Claude. LLMs make mistakes — please verify before acting.