Eighth and final phase of Arc 1. Where code becomes shippable.

This phase closes Arc 1 by installing the professional engineering hygiene that separates “I write code” from “I ship software.” Git workflows, CI pipelines, semantic versioning, release engineering: these are the practices that turn the tests, profiles, and architecture from Phases 5-7 into a deliverable. By phase end, sift and pulse both have proper CI pipelines, semantic versioning, automated releases, and a Git workflow that another engineer would recognize as professional.

This is also the phase that prepares you for the Arc 1 Final Exam. By the time you sit it, your Arc 1 portfolio includes: two shipped CLIs with tests, profiles, architectural rationale, CI/CD, versioned releases, and proper Git history. That’s the engineer the Junior Software Engineer exit ramp hires.


Prerequisites

  • Phase 7 complete; sift and pulse >80% test coverage
  • GitHub account with workflows enabled (or GitLab / equivalent)
  • You accept: release engineering is unglamorous and load-bearing. The reproducibility you build here is what makes production stable for years.

Why this phase exists

Most junior engineers commit to main directly, use Git as a save button, manually tag releases when they remember, and have no CI. Most senior engineers branch deliberately, write commit messages that survive git log archeology, automate releases, and treat the CI pipeline as a contract that gates what merges. The difference compounds over years.

This phase installs the senior practices: trunk-based development (or thoughtful gitflow), conventional commits, semantic versioning that actually means something, CI workflows that test + lint + build + release on every push, and automated cross-platform binary releases for the Go CLI.


The pattern-first frame

Same eight steps as every phase.


1. PROBLEM

You have code. You have tests. You have working artifacts. How does the code get from your machine to a user’s hands reliably, repeatedly, and verifiably? How does the next version replace the previous one safely? How does a user know what changed between v1.2.0 and v1.3.0? How does future-you find when a specific behavior was introduced?

That’s the release engineering problem. Git solves version control; CI solves automated verification; semantic versioning solves communication of change; release automation solves the human-error problem. Together they form the shipping pipeline every professional software project needs.


2. PRINCIPLES

2.1 Trunk-based development vs gitflow

Two major Git workflow philosophies. Trunk-based: one long-lived branch (main); short feature branches that merge within hours or days; releases cut from main. Gitflow: long-lived main + develop branches; feature branches off develop; release branches off develop merging into main.

In 2026, trunk-based has won for most contexts (continuous deployment, small/medium teams), but gitflow still fits some workflows (heavy release cadence, regulated industries).

→ Pattern: trunk-based-development

Investigate:

2.2 Conventional commits and commit-message discipline

Commit messages are documentation. A good message answers “why” and “what changed at the level of the change,” not just “what files were touched.” Conventional commits is one structured format (feat:, fix:, chore:, docs:, refactor:, perf:, test:) that enables tooling (automated changelogs, semantic version bumps).

Investigate:

2.3 Semantic versioning

The contract: MAJOR.MINOR.PATCH. MAJOR for breaking changes, MINOR for new features (backward-compatible), PATCH for bug fixes. The version number is a promise to consumers about what’s safe to upgrade to.

→ Pattern: semantic-versioning

Investigate:

2.4 CI as a contract

The CI pipeline is the gate. Every push runs: linter, tests, build, security scans. Anything that fails blocks the merge. The CI workflow is part of the codebase: version-controlled, reviewable, evolving with the project.

Investigate:

2.5 Release automation

Manual releases are error-prone. Automated release pipelines bump the version, generate the changelog from commits, build artifacts (wheels, binaries), publish to registries (PyPI, GoReleaser → GitHub releases), and tag the repo, all triggered by a merge to main or a release-trigger event.

→ Pattern: release-engineering

Investigate:

2.6 Pre-commit hooks and local quality gates

The earlier the feedback, the cheaper. Pre-commit hooks run linters and formatters before a commit lands locally. They catch the trivial issues (formatting, missing imports, secrets) before CI does.

Investigate:


3. TRADE-OFFS

DecisionOptionsCost
Git workflowTrunk-based; gitflow; GitHub Flow; release branchesTrunk: simpler, requires feature flags. Gitflow: heavy, fits scheduled releases.
Commit messagesConventional commits; free-form; “fixup” + squash on mergeConventional: enables automation. Free-form: simpler, less tooling.
CI platformGitHub Actions; GitLab CI; CircleCI; Buildkite; DroneGitHub Actions: ubiquitous, free for public repos. GitLab: integrated. Others: niche.
Release tooling (Python)release-please; bumpver; manual + GitHub Release UIrelease-please: full automation. bumpver: middle ground. Manual: simplest, error-prone.
Release tooling (Go)goreleaser; manual go build + GitHub Releasegoreleaser: standard, multi-platform. Manual: less common in OSS Go.
Pre-commitpre-commit framework; project-specific hooks; nonepre-commit: cross-language, mature. None: catch issues in CI instead.

4. TOOLS (as of 2026-06)

Git

Quality gates

CI platforms

Release automation

Reading


5. MASTERY: Harden sift and pulse release pipelines

5.1 The deliverable

sift and pulse both with:

By phase end both projects should have v1.0.0 released publicly with a clean release pipeline.

5.2 Operational depth checklist

[ ] Configure trunk-based workflow on sift and pulse; squash-merge enabled
[ ] Set up pre-commit with: language-specific formatters, gitleaks, commitlint
[ ] CI workflow for sift: ruff + mypy + pytest + coverage upload
[ ] CI workflow for pulse: golangci-lint + go test -race + coverage upload
[ ] Set up release-please for both projects
[ ] Set up PyPI publishing for sift (with trusted publishing if using GitHub Actions)
[ ] Set up GoReleaser for pulse: produce binaries for Linux/macOS/Windows × amd64/arm64
[ ] Cut v1.0.0 for both projects
[ ] Generate first auto-generated CHANGELOG.md
[ ] Test the release pipeline end-to-end: make a small commit, watch release-please propose, merge, observe release
[ ] Document the release process in each repo's CONTRIBUTING.md

6. COMPARE: gitflow as an alternative

Take ONE small experimental fork of sift or pulse. Set it up with gitflow conventions (main + develop + release/* + hotfix/* branches). Spend a week using it. Reflect on what changed vs trunk-based.

400-word reflection on when each workflow fits.


7. OPERATE


8. CONTRIBUTE


What ships from this phase


Learning loop cadence

Week 1     PROBLEM + PRINCIPLES 2.1-2.2 (trunk-based, commits)
           Set up trunk-based workflow + commitlint

Week 2     PRINCIPLES 2.3 (semver)
           Set up pre-commit hooks

Week 3     PRINCIPLES 2.4 (CI as contract)
           Build CI workflows for sift + pulse

Week 4     PRINCIPLES 2.5 (release automation)
           Set up release-please + PyPI publish (sift)

Week 5     PRINCIPLES 2.6 (pre-commit)
           Set up GoReleaser for pulse; cut v1.0.0 for both

Week 6     COMPARE: gitflow experiment
           chronicle runbooks

Week 7     OPERATE + CONTRIBUTE
           Exit Test + Arc 1 Final Exam prep

Validation criteria

[ ] sift v1.0.0 released on PyPI with automated pipeline
[ ] pulse v1.0.0 released with GoReleaser binaries
[ ] CI green on every push for both projects; coverage tracked
[ ] Pre-commit hooks operational
[ ] release-please proposing release PRs automatically
[ ] First merged upstream PR
[ ] All 11 operational depth checks
[ ] Compare reflection (400 words)
[ ] 3-4 runbooks
[ ] 2 ADRs
[ ] Pattern entries deepened STUB → OUTLINE:
    - trunk-based-development
    - semantic-versioning
    - release-engineering
[ ] Exit Test passed
[ ] Arc 1 Final Exam prep can begin

Exit Test

Time: 3 hours.

Part 1: Build (90 min)

Given a fresh Python project skeleton (provided): set up trunk-based workflow + pre-commit + CI + release-please + PyPI publish. Verify by making a small commit and watching the release pipeline propose a v0.1.0 release.

Part 2: Diagnose (60 min)

A broken release scenario (provided). Identify and fix. Possible scenarios: failed PyPI auth, GoReleaser config drift, release-please refusing to bump, CI cache poisoning.

Part 3: Articulate (30 min)

~600 words: “You join a team that uses gitflow with manual releases and free-form commit messages. Propose a migration to trunk-based + conventional commits + automated releases. Cover the steps, the resistance you’d expect, and the wins.”


Anti-patterns

Anti-patternWhy
Committing directly to mainDefeats CI, defeats review, makes rollback harder
Long-lived feature branchesMerge conflicts compound; the work gets stale relative to main
Free-form commit messages“Fix stuff” tells future-you nothing
Skipping CI “just this once”This is how main ends up broken on a Friday afternoon
Hand-bumping versionsError-prone; humans miss version bumps for breaking changes constantly
Treating the changelog as optionalUsers depend on the changelog; missing one is a contract break

Patterns touched this phase


→ Next: Arc 1 Final Exam