diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 6d45b31c..48a14fbe 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -219,9 +219,17 @@ jobs: bun-version: 1.4.2 - name: Install dependencies run: bun install --frozen-lockfile + # `github.token` cannot read branch protection — that needs + # Administration: read, which the default token does not carry. So + # this job failed on every run for lack of permission, and reported + # it as though the protection itself were wrong. + # + # `BRANCH_PROTECTION_TOKEN` is a fine-grained, READ-ONLY token + # scoped to this repository. It is deliberately not an admin token: + # a check that can rewrite the rules it verifies is not a check. - name: Verify develop branch protection env: - GITHUB_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ secrets.BRANCH_PROTECTION_TOKEN || github.token }} GITHUB_REPOSITORY: ${{ github.repository }} run: bun run ci:branch-protection diff --git a/delendai.config.json b/delendai.config.json index 0b8df2fd..55b4b649 100644 --- a/delendai.config.json +++ b/delendai.config.json @@ -1,5 +1,14 @@ { "coreVersion": "0.1.0", + "development": { + "profile": "shared-checkout-pr", + "branches": { "integration": "develop", "release": "main" }, + "integration": { + "requiredChecks": ["ci-summary"], + "requiredApprovals": 0, + "releaseRequiredApprovals": 1 + } + }, "cacheDir": ".cache/delendai", "docsDir": "docs/delendai", "surfaceMode": "managed", diff --git a/scripts/gates/branch-protection.script.ts b/scripts/gates/branch-protection.script.ts index 13bfebc0..eab95aaf 100644 --- a/scripts/gates/branch-protection.script.ts +++ b/scripts/gates/branch-protection.script.ts @@ -252,10 +252,26 @@ async function checkBranchProtection( options.token, ); if (protectionResponse.status === 404) { + // 404 en `/protection` significa "la rama no tiene regla", no + // "faltan contexts". Decirlo mal manda a corregir un campo dentro + // de una protección que no existe. return { branch: options.branch, ok: false, - detail: `required_status_checks.contexts ausente`, + detail: `la rama no tiene ninguna regla de protección`, + }; + } + if (protectionResponse.status === 401 || protectionResponse.status === 403) { + // NO es lo mismo que "la protección está mal". No se ha leído nada, + // así que no se concluye nada sobre ella: leer branch protection + // exige Administration: read, y el token por defecto de Actions no + // lo tiene. Un check que no pudo verificar una propiedad tampoco + // puede certificarla, así que sigue siendo un fallo — pero con el + // motivo correcto y el remedio a mano. + return { + branch: options.branch, + ok: false, + detail: `no se pudo leer la protección (HTTP ${protectionResponse.status}); nada se concluye de ello. Configura BRANCH_PROTECTION_TOKEN con Administration: read`, }; } if (!protectionResponse.ok) {