Skip to content

Implement ADR 0002: trunk-based automated release process #21597

Closed

Description

@screendriver

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

  • Inspect the current release implementation.
  • Add release metadata helpers.
  • Prepare reusable E2E / Testiny support.
  • Add Edge deployment from trunk.
  • Add release branch to Beta workflow.
  • Add Production approval and artifact promotion.
  • Add release branch creation workflow.
  • Add first-class Production rollback workflow.
  • Cut over branch model from dev / master to main.
  • Retire old tag-driven release path.
  • Add maintenance release automation separately.

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

Activity

  1. screendriver commented on Jun 19, 2026

    @screendriver
    MemberAuthor

    Implementation inventory completed.

    Important findings:

    • Current release deployment is still partly driven by pre-existing tags.
    • Current Production tag format is YYYY-MM-DD-production.N, but ADR 0002 requires YYYY-MM-DD.N-production.
    • Current staging tag format is YYYY-MM-DD-staging.N, but ADR 0002 requires Beta tags like YYYY-MM-DD.N-beta.M.
    • Release branches currently trigger the publish workflow, but no Beta deployment target is mapped for them.
    • Edge currently follows dev, not main.
    • Testiny support exists, but workflow_call does not yet expose testinyRunName / TESTINY_API_KEY.
    • The current redeploy workflow rebuilds from a tag and is not yet a first-class rollback workflow.
    • dev and master still carry release meaning.

    Proposed first PR:

    Add pure release metadata helpers and tests.

    Scope:

    • validate release/YYYY-MM-DD.N
    • extract YYYY-MM-DD.N
    • compute next YYYY-MM-DD.N-beta.M
    • compute YYYY-MM-DD.N-production
    • detect whether a Production tag already exists
    • detect whether an existing Production tag points to the current release commit
    • no GitHub Actions behavior changes
  2. screendriver commented on Jun 24, 2026

    @screendriver
    MemberAuthor

    Phase 3 is done.

    Pull request merged:

    This prepared the reusable E2E workflow for future release workflows by exposing Testiny reporting through workflow_call.

    Next phase:

    Add a dedicated Edge deployment workflow.

    Important transition note:

    The new workflow should not automatically run on dev, because the existing publish workflow still deploys dev to wire-webapp-edge. The new workflow should auto-trigger on main only and optionally support manual dispatch for safe testing.

  3. screendriver commented on Jun 24, 2026

    @screendriver
    MemberAuthor

    Phase 4 is done.

    PR merged:

    This adds the future main → Edge deployment workflow without changing the existing dev → Edge path or the current release process.

    Next phase:

    Add the release branch → Beta workflow.

  4. screendriver commented on Jun 25, 2026

    @screendriver
    MemberAuthor

    Phase 5 is done.

    Pull request merged:

    This adds the manual transition version of the release-cloud Beta workflow:

    • explicit release_branch input
    • explicit confirmation before deployment
    • validation before checkout
    • build once
    • deploy to the temporary Beta mapping (wire-webapp-staging)
    • create YYYY-MM-DD.N-beta.M after successful Beta deployment
    • run E2E against Beta
    • report to Testiny

    Automatic release/** triggering stays disabled during the transition to avoid disrupting the current release process.

  5. screendriver commented on Jun 29, 2026

    @screendriver
    MemberAuthor

    Phase 6 is done.

    Pull request merged:

    This extends the manual release-cloud workflow with optional Production promotion:

    • explicit promote_to_production input
    • Production preflight after successful Beta E2E
    • Beta tag verification
    • Production tag computation
    • skip behavior when Production promotion was not requested
    • skip behavior when the matching Production tag already exists for the selected release commit
    • wire-webapp-prod GitHub Environment approval
    • same-artifact promotion to Production
    • YYYY-MM-DD.N-production tag creation after successful Production deployment

    The workflow remains manual-only during the transition.

  6. screendriver commented on Jun 30, 2026

    @screendriver
    MemberAuthor

    Phase 7 is done.

    Pull request merged:

    This adds the manual GitHub Actions workflow for creating release/YYYY-MM-DD.N branches.

    The workflow:

    • validates the release identifier
    • rejects .0 release identifiers
    • validates source_ref
    • defaults source_ref to dev during the transition
    • creates and pushes release/<release_identifier>
    • does not deploy
    • does not create tags

    Next phase:

    Add first-class Production rollback workflow.

  7. screendriver commented on Jun 30, 2026

    @screendriver
    MemberAuthor

    Phase 8 is done.

    Pull request merged:

    This adds a manual first-class Production rollback workflow:

    • validates an existing ADR Production tag
    • requires rollback reason and explicit confirmation
    • rebuilds from the selected Production tag as an interim limitation
    • deploys to wire-webapp-prod
    • uses the Production GitHub Environment approval gate
    • serializes with other Production deployments
    • does not create, move, delete, or rewrite release tags
    • sends failure notification to Deployoholics

    Next phase:

    Cut over the branch model.

  8. screendriver commented on Jul 14, 2026

    @screendriver
    MemberAuthor

    The Edge and Beta environment expectations have been clarified in ADR 0002.

    Pull request:

    Before starting the branch-model cutover, the next step is a focused cutover-readiness inventory. This will classify repository and external branch dependencies and define the atomic migration sequence for dev / master → main.

  9. screendriver commented on Jul 14, 2026

    @screendriver
    MemberAuthor

    Phase 9 coordinated branch cutover completed operationally on 2026-07-14.

    Phase 9 is not complete until PR #21841 is reviewed and merged and the external integrations are verified.

  10. screendriver commented on Jul 14, 2026

    @screendriver
    MemberAuthor

    Phase 9 is complete.

    Merged pull requests:

    Current state:

    • main is the single trunk branch
    • Edge follows main
    • release branches are created from main
    • Beta is available at https://wire-webapp-beta.wire.com/
    • the physical Beta deployment target remains wire-webapp-staging
    • ADR Production tags do not trigger the legacy tag-driven deployment
    • dev and master remain temporarily for compatibility but are no longer normal development branches
    • release-cloud remains manual-only
    • the legacy release path remains temporarily active

    Remaining steps before Phase 10:

    • Verify main, Edge, and Production GitHub protection settings
    • Complete one controlled Beta-to-Production release
    • Verify Beta tag creation, E2E, Testiny, Production approval, same-artifact promotion, and Production tagging
    • Verify the ADR Production tag does not trigger the legacy workflow
    • Enable automatic release-branch deployment safely
    • Prove one automatic release-branch Beta deployment

    Phase 10 will retire the remaining tag-driven release path only after those checks succeed.

  11. screendriver commented on Jul 29, 2026

    @screendriver
    MemberAuthor

    Phase 10 cleanup is in progress.

    Pull request:

    #22030

    This retires the legacy tag-driven release path and prepares deletion of the obsolete dev and master branches.

    Deliver main, Hosted Dev, the dev distribution channel, and recovery workflows remain unchanged.

    The Phase 10 checkbox stays open until the pull request is merged and both remote branches are deleted.

  12. screendriver commented on Jul 29, 2026

    @screendriver
    MemberAuthor

    Phase 10 is complete.

    Completed by:

    Retired:

    • legacy master deployment;
    • old staging and Production tag-driven deployment;
    • q1-2024 and q2-2025 publication;
    • arbitrary manual release-artifact publication;
    • local staging and Production tag commands;
    • obsolete dev and master branch assumptions.

    Deleted remote branches:

    • master
    • dev

    Preserved:

    • Deliver main;
    • Edge;
    • Hosted Dev;
    • dev Docker and Helm distribution;
    • wire-builds/dev;
    • Release WebApp;
    • Production rollback;
    • Production redeploy from historical tags;
    • Production distribution repair.

    The legacy path was intentionally retired before the first complete Production run of the final workflow. The next real release will validate the new path end to end, and any issue will be repaired there rather than through a legacy fallback.

    Phase 11 remains open for separate maintenance-release automation.

  13. screendriver commented on Aug 7, 2026

    @screendriver
    MemberAuthor

    Phase 11 is nearly complete.

    Implemented:

    Once #22136 is merged, the repository implementation and branch-protection setup for Phase 11 are complete.

    There is no Phase 12 in this issue; Phase 11 is the final defined phase.

  14. screendriver commented on Aug 7, 2026

    @screendriver
    MemberAuthor

    ADR 0002 implementation is complete.

    Phase 11 is now complete:

    The normal cloud release process was already proven end to end with release 2026-07-27.1, and maintenance releases are now isolated from the normal cloud release cadence as defined by ADR 0002.

    A maintenance line will be created only when a real maintenance release is required; no artificial maintenance branch or release is needed to complete this migration.

    All 11 implementation phases are complete. There is no Phase 12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions