How a change reaches main at Changineers: branch model, PR mechanics, CI gates, dependency and secret handling.
This page describes how a change moves from an engineer’s machine to
the main branch. All Changineers code is hosted in GitHub, and
repositories are private by default.
Branch model
Section titled “Branch model”We run a single long-lived main branch. Merges to main
auto-deploy to the non-production beta environment. The path from
beta to production is governed by
Change management; merging a PR is not a
production release.
Feature branches are short-lived: hours to days, not weeks. A branch should cover a feature or a slice of one that is independently shippable. Long-running work is split into smaller pieces and rolled out gradually behind feature flags rather than held on a long-lived branch.
Pull requests
Section titled “Pull requests”Changes reach main through pull requests. We squash-merge. Branch
protection on main requires the CI checks below to pass; human
review is not required to merge.
Pre-merge testing
Section titled “Pre-merge testing”CI on each pull request runs:
- Unit and integration tests, including integration tests that exercise authentication and authorisation boundaries.
- Static analysis (see Static analysis).
- A dependency vulnerability scan (see Dependency vulnerabilities).
- A secrets scan (see Application secrets).
Static analysis
Section titled “Static analysis”Three tools run on every PR:
- Biome lints the codebase and checks code quality.
- TypeScript type-checks the codebase.
- CodeQL scans for security patterns.
Biome and TypeScript run together as pnpm lint; failures block
merge. CodeQL runs report-only via GitHub Advanced Security;
findings appear in the repository’s GitHub Security tab and are
triaged there.
Post-merge testing
Section titled “Post-merge testing”After a merge to main, smoke and browser tests run against the
beta deployment. An expanded smoke and browser suite runs nightly
against beta.
Reviewing each other’s code
Section titled “Reviewing each other’s code”Reviews are encouraged but optional for routine changes. For changes that touch a high-risk component, ask for a review in Slack #dev. High-risk by convention covers security, finance, and auditing code paths.
Dependency vulnerabilities
Section titled “Dependency vulnerabilities”Two pieces work together:
- Renovate runs continuously and opens pull requests to upgrade dependencies, including security-labelled PRs when an advisory lands.
- OSV-Scanner runs in
CI on every PR and on
main. It blocks merges that depend on a vulnerable version, which closes the window between an advisory landing and the corresponding Renovate PR being merged.
If OSV-Scanner blocks a merge, the fix is to apply the relevant Renovate PR (or open one manually) rather than to suppress the finding. If applying the upgrade isn’t trivial (the upgrade breaks the app, the dependency has been deprecated, no fixed version exists yet), the finding moves into Vulnerability management for triage.
Supply-chain risk
Section titled “Supply-chain risk”Adding a dependency means trusting its maintainers, its transitive dependencies, and its build pipeline. That’s not a reason to avoid dependencies, we use plenty, but think about it before pulling in something new, especially for small problems where rolling our own would be tractable. If you’re choosing between adding a dep or writing a few hundred lines yourself, that’s a design conversation worth having; capture the call in the ADR.
Application secrets
Section titled “Application secrets”Application secrets are not stored in source code. Production secrets live in AWS Secrets Manager and are fetched at runtime by the services that need them.
Trufflehog catches accidental commits of secrets:
- Pre-commit hook on each developer’s machine catches secrets before they enter git history.
- CI check on every PR and on
mainis the backstop. A merge is blocked if any secret is detected.
If a secret is committed and pushed before the local hook catches it, treat it as leaked: rotate the secret first, then remove it from history.
Infrastructure as code
Section titled “Infrastructure as code”Changineers infrastructure (the platform, supporting AWS services, the AWS Organization itself) lives in Terraform repos and ships the same way. Non-production changes apply on merge; production changes go through the release PR in Change management.
If you find yourself wanting to make a change directly in the AWS console, stop and check whether it should be Terraform instead. The exception path (CTO-approved, time-bound elevated SSO) exists for the exceptional case; see Change management § Authorised actors.