Archive Done Project Items #118
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Archive Done Project Items | |
| on: | |
| schedule: | |
| # Daily at 07:00 UTC (offset from history-publish at 08:00 and verify-execution at 06:00). | |
| - cron: "0 7 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| days: | |
| description: "Archive closed items older than N days (default 2)" | |
| required: false | |
| type: string | |
| default: "2" | |
| dry_run: | |
| description: "Print what would be archived without acting" | |
| required: false | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: archive-done | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| issues: write | |
| repository-projects: write | |
| jobs: | |
| archive: | |
| name: Archive stale done items | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Diagnostic: surface secret state before the script runs. This is | |
| # purely informational; the script's pre-flight probe is what actually | |
| # fails fast with an actionable error when the token is unscoped. | |
| # | |
| # Note: the `repository-projects: write` permission above grants | |
| # repo-level classic Projects access only; it does NOT grant the | |
| # org-level ProjectV2 scope required by archive-stale-done.sh. That | |
| # requires a fine-grained PAT with Projects:Read+Write on | |
| # stellar-experimental, set as the PROJECT_BOARD_TOKEN secret. | |
| # `secrets.*` cannot be used in step/job `if:` expressions, so this guard | |
| # maps PROJECT_BOARD_TOKEN's presence into a step OUTPUT (`present`), which | |
| # IS usable in a later `if:`. When the secret is absent we emit a `::notice::` | |
| # (not `::warning::`) with the operator action — a clean skip should look | |
| # clean in the run log, not alarming. | |
| - name: Check PROJECT_BOARD_TOKEN secret | |
| id: check_token | |
| env: | |
| HAS_TOKEN: ${{ secrets.PROJECT_BOARD_TOKEN != '' }} | |
| run: | | |
| echo "present=$HAS_TOKEN" >> "$GITHUB_OUTPUT" | |
| if [ "$HAS_TOKEN" != "true" ]; then | |
| echo "::notice::PROJECT_BOARD_TOKEN secret is not configured; skipping the archive step (the job will conclude success). To enable archiving, create a fine-grained PAT with Projects:Read+Write on stellar-experimental and store it as the PROJECT_BOARD_TOKEN org secret. See issue #3224." | |
| else | |
| echo "PROJECT_BOARD_TOKEN is configured; the archive step will run." | |
| fi | |
| # Gated on the secret-presence OUTPUT only — NOT on the script's success. | |
| # A step skipped via `if:` does NOT fail the job, so when the secret is | |
| # absent the run concludes `success` (this is what ends the deploy-gate | |
| # CI-signal pollution). When the secret IS present the step runs against | |
| # PROJECT_BOARD_TOKEN directly; the doomed `|| secrets.GITHUB_TOKEN` | |
| # fallback is dropped because GITHUB_TOKEN structurally lacks org-project | |
| # scope. A present-but-unscoped/revoked token still runs here and fails | |
| # loudly via the script's pre-flight exit 1 (don't mask real failures). | |
| - name: Run archive-stale-done.sh | |
| if: steps.check_token.outputs.present == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.PROJECT_BOARD_TOKEN }} | |
| run: | | |
| DAYS="${{ inputs.days || '2' }}" | |
| DRY_RUN="${{ inputs.dry_run && '--dry-run' || '' }}" | |
| bash .github/skills/shared/scripts/archive-stale-done.sh $DRY_RUN "$DAYS" |