Context
ADR 0002 defines the target release process for wire-webapp:
main becomes the trunk branch.
- Every merge to
main deploys to Edge.
- Release branches use
release/YYYY-MM-DD.N.
- Release branch updates deploy to Beta.
- Successful Beta deployments create
YYYY-MM-DD.N-beta.M tags.
- Production waits for GitHub Environment approval.
- Production promotes the Beta-tested artifact and does not rebuild from source.
- Successful Production deployments create
YYYY-MM-DD.N-production tags.
- Production tags are immutable release history.
- Rollback is handled by a dedicated GitHub Actions workflow.
- On-premises maintenance releases are handled separately from the normal cloud release flow.
ADR:
docs/decision-records/0002-trunk-based-automated-release-process.md
Goal
Implement ADR 0002 in small, reviewable, low-risk steps.
The final release process should be GitHub-driven, auditable, and safe:
- build once
- deploy to Beta
- validate on Beta
- approve Production through GitHub Environment approval
- promote the same artifact to Production
- create the Production tag only after successful Production deployment
- keep rollback explicit and auditable
Non-goals for the first phase
The first phase should not try to do everything at once.
Out of scope initially:
- Deleting
dev.
- Deleting or renaming
master.
- Removing all old release triggers immediately.
- Full on-premises maintenance release automation.
- Perfect durable artifact storage for rollback.
- Full feature flag governance automation.
- Large workflow rewrites without intermediate compatibility.
Progress checklist
Phase 1: Inspect the current release implementation
Create an implementation inventory before changing code.
The inventory should cover:
- existing workflows for build, deploy, release, E2E, rollback, Docker, Helm, and notifications
- existing scripts for release tagging and changelog generation
- current branch assumptions
- current tag assumptions
- current deployment targets and environment names
- Testiny integration
- Wire / Deployoholics notification integration
- conflicts between the current implementation and ADR 0002
- a proposed PR sequence with small, reviewable steps
Acceptance criteria:
- No files are changed.
- No branch is created.
- No PR is opened.
- The current implementation is documented well enough to plan the first implementation PR.
Phase 2: Add release metadata helpers
Add small deterministic helpers for release metadata.
Required behavior:
- validate release branch names matching
release/YYYY-MM-DD.N
- extract the release identifier
YYYY-MM-DD.N
- compute the next Beta tag from existing tags matching
YYYY-MM-DD.N-beta.M
- compute the Production tag
YYYY-MM-DD.N-production
- detect whether the Production tag already exists
- detect whether an existing Production tag points to the current release commit
- never move, delete, or force-push tags
- add tests for the pure release metadata logic
Acceptance criteria:
- Release naming rules are test-covered.
- Tag selection behavior is deterministic.
- No workflow behavior changes yet.
Phase 3: Prepare reusable E2E / Testiny support
Prepare .github/workflows/e2e-tests.yml so it can be called by the future release workflow.
Required behavior:
- support
testinyRunName through workflow_call
- support
TESTINY_API_KEY through workflow_call secrets
- keep existing manual dispatch behavior unchanged
- keep Playwright sharding and report generation unchanged
Acceptance criteria:
- A caller workflow can run E2E against a provided webapp URL.
- A caller workflow can upload the result to a named Testiny run.
- Existing manual E2E usage still works.
Phase 4: Add Edge deployment from trunk
Add a dedicated Edge deployment workflow.
Required behavior:
- trigger on pushes to
main
- during transition, support the current branch setup only if needed
- build/package the webapp
- deploy to Edge
- do not require GitHub Environment approval
- use concurrency so superseded Edge runs can be cancelled
Acceptance criteria:
- Edge follows trunk.
- Edge deployment is separate from the old release/tag-driven Production flow.
- Existing Production release behavior is not changed in this phase.
Phase 5: Add release branch to Beta workflow
Add the first version of the cloud release workflow.
Required behavior:
- trigger on pushes to
release/**
- validate the branch name as
release/YYYY-MM-DD.N
- build the release artifact once
- deploy the artifact to Beta
- create
YYYY-MM-DD.N-beta.M only after successful Beta deployment
- fetch tags before computing the next Beta tag
- fail if a concurrent workflow created the same Beta tag
- never force-push tags
- run E2E against Beta
- report E2E results to Testiny
- add a GitHub step summary with release identifier, commit SHA, artifact checksum, Beta tag, Beta URL, E2E result, and Testiny run name
- notify the release channel / Deployoholics on failure
Acceptance criteria:
- Pushing to a valid release branch automatically deploys Beta.
- Beta tags are created only after successful Beta deployment.
- E2E and Testiny are part of the release branch workflow.
- No Production deployment is added yet.
Phase 6: Add Production approval and promotion
Extend the release workflow with the Production part.
Required behavior:
- Production waits for GitHub Environment approval.
- Production deploys the same artifact that was deployed to Beta.
- Production does not rebuild from source.
- Production deployment is serialized across the repository.
- Production deployments are not cancelled automatically.
- Before deploying, check whether
YYYY-MM-DD.N-production already exists.
- If the Production tag already points to the same commit, skip redeployment.
- If the Production tag exists and points to a different commit, fail.
- Create
YYYY-MM-DD.N-production only after successful Production deployment.
- Never move, delete, or force-push Production tags.
- Notify the release channel / Deployoholics on failure.
Acceptance criteria:
- Beta-tested artifact is promoted to Production.
- Production tag represents a successful Production deployment.
- Existing Production tags remain immutable.
- Re-running the workflow does not redeploy a commit that already has the matching Production tag.
Phase 7: Add release branch creation workflow
Add a manual workflow for creating release branches from GitHub Actions.
Required behavior:
- use
workflow_dispatch
- input:
release_identifier in format YYYY-MM-DD.N
- input:
source_ref, defaulting to main
- input: confirmation boolean
- create
release/YYYY-MM-DD.N
- fail if the branch already exists
- do not create tags
- do not deploy directly; the pushed branch should trigger the release workflow
Acceptance criteria:
- Release branches can be created without local machine release operations.
- Branch creation is auditable in GitHub Actions.
Phase 8: Add first-class rollback workflow
Add or adapt a dedicated Production rollback workflow.
Required behavior:
- use
workflow_dispatch
- input: previous known-good Production tag
- input: rollback reason
- input: optional incident reference
- input: confirmation boolean
- validate the tag exists
- deploy to Production through GitHub Actions
- use the Production GitHub Environment
- serialize against other Production deployments
- notify the release channel / Deployoholics
- do not create, move, delete, or rewrite release tags
Acceptance criteria:
- Rollback is explicit and auditable.
- Rollback is owned by engineering release owners, not QA.
- Runtime state is visible through GitHub deployment metadata, logs, and notifications.
Phase 9: Cut over branch model
After the new workflows are proven:
- rename
master to main
- retire
dev as a long-lived release branch
- update branch protection rules
- update GitHub workflow branch filters
- update documentation
- update external integrations
- update any
wire-builds mappings if still needed
Acceptance criteria:
main is the single trunk branch.
- Edge follows
main.
- Release branches are cut from
main.
dev and master no longer carry release meaning.
Phase 10: Retire old tag-driven release path
After the new release workflow is proven:
- stop Production deployment from pre-created Production tags
- deprecate or remove local release tagging commands
- remove outdated
staging / production release tag assumptions where no longer needed
- keep compatibility only where explicitly required
Acceptance criteria:
- Production tags are created after successful Production deployment.
- Local machines are no longer required for normal release operations.
- Old release paths cannot accidentally bypass the new process.
Phase 11: Add maintenance release automation separately
Add maintenance release automation only after the cloud release path is stable.
Required behavior:
- create maintenance branches only when needed
- use branch names like
maintenance/<maintenance-line-key>
- do not deploy maintenance branches to normal Beta or Production
- validate maintenance artifacts through a dedicated maintenance path
- create maintenance tags like
<maintenance-line-key>-maintenance.X
Acceptance criteria:
- On-premises maintenance releases are separate from cloud releases.
- Normal cloud cadence is not constrained by maintenance lines.
Open questions
- Which existing environment maps to ADR “Beta” during the transition?
- Should
wire-webapp-staging be renamed conceptually or physically?
- Where should immutable release artifacts live long term?
- Is GitHub Actions artifact retention sufficient for the first iteration?
- Should Elastic Beanstalk application versions become the durable promotion unit?
- What exact Testiny run naming convention should release workflows use?
- Which GitHub Environment reviewers should approve Production?
- Which Wire channel should receive release workflow failure and stalled approval notifications?
- What is the planned date for
master to main rename?
- Which external integrations still depend on
dev or master?
- Which parts of
wire-builds still need updates from the webapp release workflow?
Risks
- Accidentally keeping both old and new Production paths active.
- Creating Production tags before deployment instead of after deployment.
- Rebuilding for Production and invalidating Beta validation.
- Cancelling an in-progress Production deployment.
- Losing rollback ability because the artifact is not durable enough.
- Blocking release migration on branch renaming too early.
- Mixing maintenance release automation into the cloud release workflow.
Suggested first PR
Start with release metadata helpers and tests.
This should not change any workflow behavior.
Suggested scope:
- validate
release/YYYY-MM-DD.N
- extract release identifier
- compute next Beta tag
- compute Production tag
- detect existing Production tag behavior
- add tests
- no GitHub Actions changes
Context
ADR 0002 defines the target release process for
wire-webapp:mainbecomes the trunk branch.maindeploys to Edge.release/YYYY-MM-DD.N.YYYY-MM-DD.N-beta.Mtags.YYYY-MM-DD.N-productiontags.ADR:
docs/decision-records/0002-trunk-based-automated-release-process.mdGoal
Implement ADR 0002 in small, reviewable, low-risk steps.
The final release process should be GitHub-driven, auditable, and safe:
Non-goals for the first phase
The first phase should not try to do everything at once.
Out of scope initially:
dev.master.Progress checklist
dev/mastertomain.Phase 1: Inspect the current release implementation
Create an implementation inventory before changing code.
The inventory should cover:
Acceptance criteria:
Phase 2: Add release metadata helpers
Add small deterministic helpers for release metadata.
Required behavior:
release/YYYY-MM-DD.NYYYY-MM-DD.NYYYY-MM-DD.N-beta.MYYYY-MM-DD.N-productionAcceptance criteria:
Phase 3: Prepare reusable E2E / Testiny support
Prepare
.github/workflows/e2e-tests.ymlso it can be called by the future release workflow.Required behavior:
testinyRunNamethroughworkflow_callTESTINY_API_KEYthroughworkflow_callsecretsAcceptance criteria:
Phase 4: Add Edge deployment from trunk
Add a dedicated Edge deployment workflow.
Required behavior:
mainAcceptance criteria:
Phase 5: Add release branch to Beta workflow
Add the first version of the cloud release workflow.
Required behavior:
release/**release/YYYY-MM-DD.NYYYY-MM-DD.N-beta.Monly after successful Beta deploymentAcceptance criteria:
Phase 6: Add Production approval and promotion
Extend the release workflow with the Production part.
Required behavior:
YYYY-MM-DD.N-productionalready exists.YYYY-MM-DD.N-productiononly after successful Production deployment.Acceptance criteria:
Phase 7: Add release branch creation workflow
Add a manual workflow for creating release branches from GitHub Actions.
Required behavior:
workflow_dispatchrelease_identifierin formatYYYY-MM-DD.Nsource_ref, defaulting tomainrelease/YYYY-MM-DD.NAcceptance criteria:
Phase 8: Add first-class rollback workflow
Add or adapt a dedicated Production rollback workflow.
Required behavior:
workflow_dispatchAcceptance criteria:
Phase 9: Cut over branch model
After the new workflows are proven:
mastertomaindevas a long-lived release branchwire-buildsmappings if still neededAcceptance criteria:
mainis the single trunk branch.main.main.devandmasterno longer carry release meaning.Phase 10: Retire old tag-driven release path
After the new release workflow is proven:
staging/productionrelease tag assumptions where no longer neededAcceptance criteria:
Phase 11: Add maintenance release automation separately
Add maintenance release automation only after the cloud release path is stable.
Required behavior:
maintenance/<maintenance-line-key><maintenance-line-key>-maintenance.XAcceptance criteria:
Open questions
wire-webapp-stagingbe renamed conceptually or physically?mastertomainrename?devormaster?wire-buildsstill need updates from the webapp release workflow?Risks
Suggested first PR
Start with release metadata helpers and tests.
This should not change any workflow behavior.
Suggested scope:
release/YYYY-MM-DD.N