Skip to content

feat(init): provision the labels a repo's dependabot.yml declares - #3116

Merged
mlorentedev merged 4 commits into
mainfrom
feat/init-github-labels
Nov 3, 2026
Merged

mlorentedev merged 4 commits into
mainfrom
feat/init-github-labels

Conversation

@mlorentedev

@mlorentedev mlorentedev commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Closes #1222

Spec: specs/HARNESS-081-dependabot-labels-provisioned/

Summary

Dependabot applies a custom label only if it already exists, and it never creates one. The dependencies label that the spec-gate skip keys on only existed after someone created it by hand.

  • dotf init github (and the github step of dotf init) reads the target repo's own .github/dependabot.yml (or .yaml) and creates each declared label the repo lacks, alongside delete_branch_on_merge.
    • Label names compare case-insensitively, the way GitHub compares them.
    • It reads before it writes, so a second run creates nothing.
    • --dry-run lists the labels it would create.
    • A create that the server rejects fails the command.
  • scripts/bitacora-rollout.sh adds a step 3b that runs dotf init github --repo <owner>/<repo>.
    • Under --check it passes --dry-run. It does not run under --backfill-only.
    • A non-zero exit or a [WARN] skip counts as an error.

Verification

  • cd cli && go build ./... && go vet ./... && GOOS=windows go vet ./... && go test ./... passes. golangci-lint run (2.12.2, the pinned version) reports 0 issues.
  • shellcheck scripts/bitacora-rollout.sh is clean. bats tests/bitacora-rollout.bats tests/stub-real-pairing.bats passes 22/22 under /bin/bash 3.2.
  • Nothing was run against a live repo. The rollout is run by hand with BITACORA_PAT, --check first.

Knowledge

Dependabot never creates a custom label and drops a missing one from its
PRs, so the 'dependencies' label the spec-gate skip keys on never existed
until someone created it by hand. dotf init github now reads the target
repo's own dependabot.yml and creates each declared label it lacks, beside
delete_branch_on_merge; a create the server rejects fails the command.

bitacora-rollout.sh applies both defaults per repo through dotf init
github (--dry-run under --check), and treats a [WARN] skip as an error:
nobody reads a notice in a rollout.

Refs #1222
…o skip

Both were unguarded: a mutation dropping either survived the suite. The
missing-file check now matches 'HTTP 404' rather than a bare '404'.

Refs #1222
@mlorentedev
mlorentedev marked this pull request as ready for review November 3, 2026 05:45
@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 23 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
Commits

Reviewing files that changed from the base of the PR and between 1a6a8b0 and cfd48e5.

Files selected for processing: 14
  • cli/internal/cmd/init.go
  • cli/internal/initrepo/labels.go
  • cli/internal/initrepo/labels_test.go
  • cli/internal/initrepo/orchestrator.go
  • scripts/bitacora-rollout.sh
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/features.json
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/proposal.md
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/review-request-round1.json
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/review-request.json
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/review-round1.md
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/review.md
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/tasks.md
  • specs/archive/HARNESS-081-dependabot-labels-provisioned/verification.md
  • tests/bitacora-rollout.bats
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

- [x] Lint passes
- [x] No unrelated changes in the diff (no scope creep)
- [x] `verification.md` filled in
- [ ] PR opened referencing this spec folder

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Harness compliance

Class: REAL
Definition of Done (closing pass / board): the PR is submitted while its own closing boxes are still unticked. tasks.md still reads "- [ ] PR opened referencing this spec folder" even though this PR opens it and references the spec folder, and verification.md's archive checklist still has the bitácora board item unchecked while the PR presents the change as complete. A reader of the spec folder cannot tell whether the board/ticket step was performed, deferred to merge, or simply forgotten; DoD requires silence to be a stated skip, not an unticked box.

Comment on lines +113 to +117
if err != nil {
var exit *exec.ExitError
if errors.As(err, &exit) && strings.Contains(string(exit.Stderr), "HTTP 404") {
continue
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent success

Class: REAL
A 404 from the contents API is treated as "this repo declares no labels", turning an unreadable dependabot.yml into an [OK] result instead of the loud failure #1222 asks for. Trace: a private repository (or one a fine-grained token has not been granted) answers HTTP 404 for gh api /repos/<r>/contents/.github/dependabot.yml even though the file exists; dependabotLabels hits the continue branch, finds no .yaml either, returns (nil, nil), and ApplyDependabotLabels reports Action none — and it does so before gh label list is ever called, so the proposal's stated mitigation ("an unauthorized repo then fails label list → skip") is unreachable on this path. The rollout then prints [OK] ... current and the label stays unprovisioned: exactly the silent divergence the issue exists to close. Uncertainty: for a public repo a permission failure more often surfaces as 403, which the code already skips loudly; the silent path is the 404-masked case.

Comment on lines +179 to +183
labels, err := ApplyDependabotLabels(repo, dryRun)
if err != nil {
return "warn", detail + "; " + err.Error()
}
return "ok", detail + "; " + labels.Summary()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Status mislabeled

Class: THEORETICAL
In the github step of dotf init, a skipped label provision is folded into status ok, unlike the delete-branch default directly above it, which returns skipped. Trace: gh is present and the repo-settings read succeeds so delete-branch completes, but the dependabot.yml read fails with a non-404 (502, offline) → ApplyDependabotLabels returns Action skipped → initGithubWithDryRun returns ("ok", "...; dependabot labels skipped: ..."). Any consumer that keys on the status (the init summary / okOrSkip accounting) records a success for a degraded step, and only the free-text detail reveals the skip. The rollout path is unaffected because it calls dotf init github and fails on any [WARN].

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

1222 - Partially compliant

Compliant requirements:

  • Idempotent reconciliation against repo state: the code reads the declared labels and the existing labels before writing, so a second run creates nothing.
  • Fail loudly on a rejected create: gh label create failure returns a non-zero exit naming label and repo, and the rollout converts any error or [WARN] skip into an err that fails the repo.
  • Not a one-off manual create: provisioning is a dotf init github default, called as step 3b of scripts/bitacora-rollout.sh, so it travels across the rollout instead of living in a hand-run command.
  • Placement open question resolved in favor of extending bitacora-rollout.sh (owner's option B, recorded in the proposal); bitacora-reconcile.yml is untouched.

Non-compliant requirements:

  • A schedule preceding Dependabot's Monday window: no scheduled reconciler is added; the proposal explicitly declares it out of scope and relies on re-running dotf init / the rollout to heal drift.
  • The static guard asserting every declared label is provisioned by the repo: not implemented; declared out of scope with the rationale that the step reads the declaration at run time.

Requires further human verification:

  • Whether provisioning only at dotf init / rollout time is acceptable to the issue author instead of the schedule the ticket asked for (an owner decision recorded only in the proposal's "Out of scope").
  • Live execution: the PR states nothing was run against a real repository; the rollout with BITACORA_PAT (--check first) still needs to be run by the owner.
  • Whether the rollout's token actually has label write on every repository in the OPS-002 rollout (the proposal assumes parity with its existing workflow-write scope).
⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Harness compliance
Class: REAL
Definition of Done, evidence: the PR's Verification section claims results in prose only ("passes", "reports 0 issues", "22/22") with no captured command output, and no dotf pr triage-queue result is reported anywhere in the PR. The rule requires a completion claim to be backed by the command output produced in this session rather than an assertion, and for PR work specifically a triage-queue run returning exit 0. Paste the terminal output (or link the CI run log) for each claimed command and the queue result.


⚙️ Agent run details
  • Model: openai/mimo-v2.6-flash
  • Tokens: 32,576 in / 25,598 out / 58,174 total
  • Time cost: 393.0s
  • AI calls: 1

The delete-branch default above it already reports its skip; folding the
labels skip into ok left only the free-text detail to show it.

Refs #1222
@mlorentedev

Copy link
Copy Markdown
Owner Author

Review triage

Reviewed by pr-agent (github-actions) on dce3bc78. CodeRabbit posted only a rate-limit notice, so it did not review this PR. The spec's adversarial review (nan/glm5.3-flash) took two rounds: FAIL on 31ccb79d, then PASS on c4a003c1. Its dispositions are in specs/archive/HARNESS-081-dependabot-labels-provisioned/verification.md. The PR author did this triage.

Finding Disposition Reason
orchestrator.go:183 status mislabeled: a skipped labels default reads ok Applied, cfd48e58 The step now reports warn, matching the delete-branch skip above it. TestInitGithubStepWarnsWhenTheLabelsAreSkipped covers it.
labels.go:117 silent success: a 404 masking an unreadable dependabot.yml Declined Both callers read the repository (delete_branch_on_merge) before the labels. A repository the token cannot see answers 404 there first, and that read is a [WARN] skip, which the rollout fails. For a repository the token can see, a token missing the contents permission gets 403, which is already a skip (TestApplyDependabotLabelsSkipsWhenTheRepoCannotBeRead). Only a real missing file reaches the 404 branch.
tasks.md:42 "PR opened" box unticked Declined Ticking it after review changes the contract digest the review was signed against, and dotf spec archive refused the archive for exactly that. The PR is recorded in verification.md under round-2 dispositions. The board item closes with Closes #1222 on merge.
Verification claims in prose, no captured output Declined This head's CI runs the same suites (test, cli-lint, test-macos, test-windows, integration). The review artifacts record the fresh reviewer-run output.
Ticket compliance: no schedule, no static guard Declined Both are out of scope in the proposal, by the owner's option-B decision on #1222. The rollout heals a deleted label on its next run. Reading the declaration at run time leaves no second list to guard.
Live run not done Owner action After merge: dotf secrets run --only BITACORA_PAT -- ./scripts/bitacora-rollout.sh --check, then the real run.

Ticketed: #3121 (dependabot.yaml fallback untested, review round 2 Minor).

@mlorentedev
mlorentedev merged commit 30bdedb into main Nov 3, 2026
29 checks passed
@mlorentedev
mlorentedev deleted the feat/init-github-labels branch November 3, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HARNESS-081: the 'dependencies' label does not exist, so the spec-gate skip for Dependabot has never fired

1 participant