Skip to content
prod 352bb92
Browse

6 · Commit & freeze the vendor

Objective — earn the whole section: verify the frozen author/vX baseline from Create the project, push develop + the author branch + tag to the private remote, cut your working branch, and prove the seam is clean.

Steps at a glance:

  1. Verify the pristine baseline exists — confirm the frozen vendor import and tag exist before pushing, so later work has a trustworthy rollback and diff anchor.
  2. Safety-check before pushing — Never trust that .gitignore is perfect — prove it before anything hits the remote.
  3. Push to the private remote — push the protected baseline to the private remote, so the pristine vendor history is backed up before setup work continues.
  4. Cut your working branch — With the baseline frozen and pushed, create the branch the rest of the playbook commits against.
  5. Verify the seam — prove the baseline branch, working branch, and pristine tag line up, so future vendor updates compare against the right seam.

Create the project already created the pristine vendor baseline — the immutable snapshot you diff against at every vendor update. This page pushes that baseline; it does not re-commit vendor source mixed with AI files.

flowchart TD
V["verify author-vX tag<br/>+ author/vX branch"] -->|missing| L["legacy: run Create the project<br/>baseline commit"]
V -->|present| P["push develop +<br/>author branch + tag"]
P --> W["git checkout -b<br/>Setup/Initial-Launch"]
W --> S["seam check<br/>.env + vendor/"]
  1. Confirm the frozen branch, tag, and pristine import commit from AI dev environment setup — this page verifies those outcomes; it does not recreate the vendor import.

    Required outcomeWhere createdVerified here
    T1 vendor import commitCreate the project §6git log develop --oneline shows pristine + C2–C6
    author/vX.X.X branchSamegit branch --list 'author/*'
    author-vX.X.X tagSamegit tag --list 'author-*'
    Terminal window
    git tag --list 'author-*'
    git branch --list 'author/*'
    git branch --show-current # expect develop (or your working branch after Verify & gate)
    git log develop --oneline -6 # expect C1…C6 (pristine + five AI commits)
    git log author/v${VERSION} -1 --oneline 2>/dev/null || git log -1 --oneline
    # Expected: author-vX.X.X tag + author/vX.X.X branch; log shows pristine import message
    • author-v${VERSION} tag and author/v${VERSION} branch exist locally.
  2. If either is missing — you skipped the baseline commit. Go back to Create the project · pristine baseline before continuing. Do not run a mixed git add . import here.

    • ✅ Baseline present — continue. If missing — stop and create it on Create the project only.

Never trust that .gitignore is perfect — prove it before anything hits the remote.

  1. Scan the working tree for anything that must not be committed.

    Terminal window
    git status | grep -E "vendor/|node_modules/|\.env$" && echo "STOP! Fix .gitignore!" || echo "Safe"
    git check-ignore -q _source/ && echo "_source ignored OK" || echo "FAIL: /_source/ must stay ignored"
    # Expected: "Safe" — no vendor/, node_modules/, or .env in the status
    • ✅ Prints Safe. If it prints STOP!, fix .gitignore before continuing.
  1. Add the remote and push develop, the author branch, and the tag.

    Terminal window
    git remote add origin "$GITHUB_REPO" 2>/dev/null || git remote set-url origin "$GITHUB_REPO"
    git push -u origin develop
    git push origin "author/v${VERSION}" "author-v${VERSION}"
    # Expected: develop, author/vX.X.X, and author-vX.X.X all pushed to origin
    • ✅ On GitHub, the branches dropdown shows develop + author/vX.X.X, and Tags shows author-vX.X.X.
  2. Set the GitHub default branch to develop. The empty repo was created before develop existed, so enforce the default branch immediately after the first push creates it. In setup-new, develop is the active work and PR target; main remains the protected release/tag branch.

    Terminal window
    REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner')
    gh repo edit "$REPO" --default-branch develop
    gh repo view "$REPO" --json defaultBranchRef -q '.defaultBranchRef.name'
    # Expected: develop
    • ✅ The verify command prints develop.
  3. 🤖 Activate the local pre-push hook — the interim signing gate that runs on this clone before each push. The repo ships .githooks/pre-push (committed); the core.hooksPath pointer is a local git setting, so every clone must opt in once.

    Terminal window
    git config core.hooksPath .githooks
    # Verify it fires: a push containing any unsigned non-baseline commit is now rejected locally.
    • git config --get core.hooksPath prints .githooks.

3b. 👤 Enable signed-commit protection on the remote (USER step)

Section titled “3b. 👤 Enable signed-commit protection on the remote (USER step)”
  1. 👤 Confirm the prerequisite once. Branch protection (the classic API below) on a private repo under a free personal account requires GitHub Pro. On a free account, use a Ruleset instead (Option B) — rulesets enforce signed commits on private repos at no extra cost. Public repos and org/Team plans can use either.

    • ✅ You know which path applies: Pro / org → Option A or B · free personal + private → Option B (Ruleset).
  2. 👤 Option A — branch protection via gh (one command per branch). Replace OWNER/REPO with the real slug. Run for develop now; re-run for main (the setup-new release branch) the moment it exists.

    Terminal window
    # Require signed commits on develop (idempotent — safe to re-run)
    gh api -X PUT "repos/OWNER/REPO/branches/develop/protection/required_signatures" \
    -H "Accept: application/vnd.github+json"
    # Later, when main exists:
    gh api -X PUT "repos/OWNER/REPO/branches/main/protection/required_signatures" \
    -H "Accept: application/vnd.github+json"
    # Verify (expects: "enabled": true)
    gh api "repos/OWNER/REPO/branches/develop/protection/required_signatures" \
    -H "Accept: application/vnd.github+json" --jq .enabled
    • ✅ The verify call prints true for develop (and later main).
  3. 👤 Option B — Ruleset via the GitHub UI (works on free private repos, no Pro). This is the fallback when Option A returns 403/Upgrade required, and the most robust path overall.

    1. GitHub → your repo → Settings → Rules → Rulesets → New ruleset → New branch ruleset.
    2. Name it e.g. require-signed-commits; set Enforcement status → Active.
    3. Under Target branches → Add target → Include by pattern, add develop (and main, or Include default branch).
    4. Under Rules, tick Require signed commits.
    5. Create.
    • ✅ The ruleset shows Active and lists develop (+ main once it exists) under target branches.
  4. 👤 Re-apply when main is born. The release branch usually doesn’t exist yet at Phase 2. Add the same rule/ruleset target before the first production merge — track it on the checklist below so it isn’t forgotten.

    • main carries an identical signed-commit rule before any code merges into it.

With the baseline frozen and pushed, create the branch the rest of the playbook commits against.

Option A (default):

  1. Branch off develop for the working branch.

    Terminal window
    git checkout develop
    git checkout -b Setup/Initial-Launch
    # Expected: now on Setup/Initial-Launch, branched from develop
    • git branch --show-current prints Setup/Initial-Launch.

Option B — cut a phase-scoped branch instead (see Branch strategy · Option B CLI appendix):

Terminal window
git checkout develop
git checkout -b Setup/Phase-2-Code-Repo
# Expected: git branch --show-current → Setup/Phase-2-Code-Repo
  • ✅ Working branch matches the model recorded in Zaj-PROJECT.md.
  1. Prove secrets and installed vendor never entered history.

    Terminal window
    git log --all --full-history -- .env # → nothing
    git log --all --full-history -- vendor/ # → nothing
    git log author/v${VERSION} -1 --oneline 2>/dev/null || true
    git diff author/v${VERSION} develop --stat | head -20
    # Expected: .env and vendor/ logs empty; diff shows AI/bootstrap files on develop beyond pristine
    • ✅ Both .env and vendor/ logs are empty; optional stat diff confirms develop moved forward from the frozen author tree.

Do not mark this step done until every box below is checked.

  • 🤖 Baseline verifiedauthor/vX.X.X + author-vX.X.X exist locally (created at Create the project).
  • 🤖 develop pushed to the private remote (includes C1–C6 after Verify & gate).
  • 🤖 Remote default branch verifiedgh repo view --json defaultBranchRef -q '.defaultBranchRef.name' prints develop.
  • 🤖 Local pre-push hook activegit config --get core.hooksPath prints .githooks (interim gate; --no-verify bypasses it).
  • 👤 Signed-commit protection enabled on the remote — GitHub Require signed commits on develop (via gh api .../required_signatures or a Settings → Rules → Ruleset). Free personal + private repo → use a Ruleset (Pro not required).
  • 👤 main rule queued — same signed-commit rule applied to main/production before the first production merge (the branch usually doesn’t exist yet at Phase 2).
  • 🤖 Snapshot on remoteauthor/vX.X.X branch and author-vX.X.X tag pushed.
  • 🤖 Working branch checked outSetup/Initial-Launch (or your Option B branch).
  • 🤖 Seam cleangit log --all -- .env vendor/ returns nothing.