Maintenance #11
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: Maintenance | |
| on: | |
| schedule: | |
| - cron: '0 0 * * 1' # Every Monday 00:00 UTC | |
| workflow_dispatch: | |
| # Workflow-level grant is minimal (read). Only the issue-touching jobs | |
| # below are granted `issues: write` at the job scope — the reused CI job | |
| # never needs to write issues. | |
| permissions: | |
| contents: read | |
| jobs: | |
| ci: | |
| uses: ./.github/workflows/ci.yml | |
| permissions: | |
| contents: read | |
| open-issue-on-failure: | |
| needs: ci | |
| if: failure() | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const existing = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| labels: 'maintenance', | |
| }); | |
| if (existing.data.length > 0) { | |
| console.log('Open maintenance issue already exists, skipping.'); | |
| return; | |
| } | |
| const run = await github.rest.actions.getWorkflowRun({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: context.runId, | |
| }); | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: 'Maintenance CI failed', | |
| body: `The scheduled maintenance CI check failed.\n\n` + | |
| `**Run:** ${run.data.html_url}\n\n` + | |
| `Please check for dependency vulnerabilities, license issues, or build failures.\n\n` + | |
| `---\n_Opened automatically by the Maintenance workflow._`, | |
| labels: ['maintenance'], | |
| }); | |
| close-issue-on-success: | |
| needs: ci | |
| if: success() | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| // Close any open maintenance issues — the most recent CI run | |
| // proves the underlying problem is resolved. Without this job | |
| // the issues opened by `open-issue-on-failure` linger forever | |
| // and the repo looks broken to outside visitors even after the | |
| // fix lands. | |
| const open = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| labels: 'maintenance', | |
| }); | |
| if (open.data.length === 0) { | |
| console.log('No open maintenance issues to close.'); | |
| return; | |
| } | |
| const run = await github.rest.actions.getWorkflowRun({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: context.runId, | |
| }); | |
| for (const issue of open.data) { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: `Maintenance CI is green again — closing automatically.\n\n**Run:** ${run.data.html_url}`, | |
| }); | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| state: 'closed', | |
| }); | |
| console.log(`Closed issue #${issue.number}`); | |
| } |