- CI/CD workflows
This repository uses a Git Flow‐inspired process with the following branches:
- feature branches (e.g. feat/some-cool-feature)
- dev for development (collecting features)
- hotfix for urgent fixes that need to go to production quickly
- release-candidate (staging environment)
- master (production)
We have two major paths: Feature to Dev and Hotfix to Hotfix. In both cases, merging into dev or hotfix triggers a job that:
- resets
release-candidateto match the incoming branch - bumps version
- builds a Docker image for staging
Once validated in staging, a manual dispatch of the Fast forward release-candidate to master job can fast‐forward release-candidate → master. Which does:
- forwards
release-candidatechanges to master (including the version bump commit) - makes the image available to production environment
- propagate changes back into
devandhotfixvia rebase
This ensures dev and hotfix is always up to date with master.
flowchart TD
%% Nodes
A[Feature Branches]
B[dev]
H[Hotfix Branches]
G[hotfix]
C_merge[merge-to-dev-or-hotfix.yml]
RC[release-candidate]
D[master]
%% Dev Flow
subgraph Dev Flow
A -->|"(1a) Merge Pull Request"| B
end
%% Hotfix Flow
subgraph Hotfix Flow
H -->|"(1a) Merge Pull Request"| G
end
B -->|"(1b) Merge triggers"| C_merge
G -->|"(1b) Merge triggers"| C_merge
C_merge -->|"(2) Resets and syncs rc + version bump + build image"| RC
RC -->|"(3a) Manual step: release.yml"| D
D -->|"(3b) rebases to"| B
D -->|"(3b) rebases to"| G
- Code Integration: Branches are merged to either
devorhotfix- Merge triggers
merge-to-dev-or-hotfix.ymlworkflow
- Merge triggers
- Staging Preparation:
merge-to-dev-or-hotfix.ymlworkflow:- Resets
release-candidateto match the merged branch - Bumps version using
conventional-recommended-bump - Builds and pushes Docker image (
vX.X.X-SHA) to staging environment (NOTE: deployment not automatic)
- Resets
- Production Release: After staging validation, manually trigger
release.yml:- Fast-forwards
masterto matchrelease-candidate - Tags Docker image as
latestfor production (NOTE: deployment not automatic) - Creates and pushes Git tag and creates a GitHub release
- Rebases both
hotfixanddevbranch ontomaster
- Fast-forwards
-
Initial State: Commit
Amerges todevrelease-candidateis reset todev, version-bumped (commitB)release-candidatenow contains:A+B
Branch Commits master(previous commits) release-candidateA+BdevAhotfix(previous commits) -
Hotfix Process: Fix (commit
C) merges tohotfixbranchrelease-candidateis reset tohotfix, replacing commitsAandBwithC, then is version-bumped (commitD)release-candidatenow contains:C+D
Branch Commits master(previous commits) release-candidateC+DdevAhotfixC -
Production Release: Manual trigger of
release.ymlmasteris fast-forwarded to matchrelease-candidate(C+D)hotfixis rebased onmaster(synced withC+D)Branch Commits masterC+Drelease-candidateC+D+A+BdevC+D+AhotfixC+D
Result: All branches contain the hotfix (C + D). The development work (A) remains in dev and release-candidate, ready for the next production release via the same process.
Below is a breakdown of each workflow file's responsibilities and when they run.
These workflows lives in each of the individual repository.
- Triggers on pull request events
- Performs:
- Setup (Node install, caching)
- Lint
- TypeScript build and type checks
- Test
This is our PR check pipeline. It ensures code quality, builds and type correctness, and all tests are passing.
- Triggers on
pushevents to either thedevbranch or thehotfixbranch. - Once a PR merges into
devorhotfix, this workflow does:- Reset
release-candidate=dev(or hotfix) - Bump version (via
conventional-recommended-bump) onrelease-candidate - Builds a Docker image from
release-candidate - Tag the built image with
staging(NOTE: deployment is not done automatically)
- Reset
This means that every merge into dev or hotfix automatically flows into release-candidate for our staging environment.
This job is manually triggered in the GitHub Actions UI once staging testing passed. This is the final step in releasing to production.
- Manually triggered in the GitHub Actions UI (i.e. workflow_dispatch)
- Steps:
- Fast‐forwards
masterfromrelease-candidate. - Tags the Docker image with
latestfor production. - Creates a Git tag and a GitHub release
- Uses rebase to sync
hotfixfrommaster. - Uses rebase to sync
devfrommaster.
- Fast‐forwards
master is updated, a production image is pushed, and we sync dev and hotfix via rebase so that everything is consistent with production.
- Used by merge-to-dev-or-hotfix.yml to reset
release-candidateto whichever branch was just merged (devorhotfix). - Runs
git reset --hard origin/<base-ref>and force-pushes back to<target-ref>.
- Builds and pushes a Docker image to GitHub Container Registry (GHCR).
- The image tag is typically
<package.json version>-<git SHA>.
- Also used in merge-to-dev-or-hotfix.yml after the reset.
- Runs
conventional-recommended-bumpto automatically determine if the version should be patch/minor/major, then commits and pushes the newpackage.json
- After building an image, we sometimes want an additional "friendly" tag. E.g.,
latestformasterorstagingforrelease-candidate. - This workflow pulls the previously built image and re‐tags/pushes it to GHCR.
- Called to do a
--ff-onlymerge from a source branch (e.g.release-candidate) to a target branch (e.g.master). - If there are commits on the target branch that aren't in the source, fast-forward fails. That's when we fallback to
rebase.yml.
- Uses rebase to sync the target branch from the source branch
- A force push is required after rebasing, as the commit SHAs will change.
- Creates a new Git tag in the format
v<version>from the package.json version value. - Pushes the newly created tag to the remote repository.
- Creates a GitHub release
- Validates if commits on a given reference compared to the latest git tag will trigger a version bump.
- Outputs
triggers_bumpandbump_type.
- Checks if a specified workflow with a particular status exists and either fails or continues based on configuration.
- Useful to prevent concurrent workflow executions.
- Compares the version in package.json against the latest git tag version.
- Fails if they are identical, ensuring meaningful version increments.