Skip to content

Archive Done Project Items #118

Archive Done Project Items

Archive Done Project Items #118

Workflow file for this run

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"