🔧 DevTools Automation #1
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
| # DevTools Script Automation | |
| # | |
| # Runs DevTools maintenance scripts automatically and on-demand. | |
| # Scheduled: gh-prefix-labels + gh-dependabot-labels (weekly, Sunday 06:00 UTC) | |
| # Manual: Any gh-* script via workflow_dispatch | |
| # | |
| # ┌─────────────────────────────────────────────────────────────────────┐ | |
| # │ Setup: DEVTOOLS_PAT │ | |
| # │ │ | |
| # │ Create a Fine-grained PAT (recommended) or Classic PAT and store │ | |
| # │ it as Org-Level secret "DEVTOOLS_PAT": │ | |
| # │ Org Settings > Secrets and variables > Actions > New secret │ | |
| # │ │ | |
| # │ ── Fine-grained PAT (Settings > Developer Settings > PATs) ── │ | |
| # │ │ | |
| # │ Resource owner: bauer-group │ | |
| # │ Repository access: All repositories │ | |
| # │ │ | |
| # │ Repository permissions: │ | |
| # │ Administration: Read and write (repo settings, topics, │ | |
| # │ branch protection) │ | |
| # │ Contents: Read and write (CODEOWNERS, templates, │ | |
| # │ branches, workflow files) │ | |
| # │ Issues: Read and write (labels for dependabot/sync) │ | |
| # │ Pull requests: Read and write (PR cleanup) │ | |
| # │ Actions: Read (usage, workflows, billing) │ | |
| # │ Environments: Read (environments audit) │ | |
| # │ Secrets: Read (secrets audit) │ | |
| # │ Webhooks: Read and write (webhook manager) │ | |
| # │ Workflows: Read and write (add workflow files) │ | |
| # │ Metadata: Read (always granted) │ | |
| # │ │ | |
| # │ Organization permissions: │ | |
| # │ Members: Read (org membership) │ | |
| # │ Administration: Read (billing info) │ | |
| # │ Self-hosted runners: Read (runner status) │ | |
| # │ │ | |
| # │ ── Classic PAT (alternative) ── │ | |
| # │ │ | |
| # │ Scopes: repo, admin:org, read:org, workflow, │ | |
| # │ read:packages, delete:packages, write:packages, │ | |
| # │ admin:repo_hook │ | |
| # └─────────────────────────────────────────────────────────────────────┘ | |
| name: 🔧 DevTools Automation | |
| on: | |
| schedule: | |
| - cron: '0 6 * * 0' # Sunday 06:00 UTC | |
| workflow_dispatch: | |
| inputs: | |
| script: | |
| description: 'Script to run' | |
| type: choice | |
| options: | |
| - gh-prefix-labels | |
| - gh-dependabot-labels | |
| - gh-labels-sync | |
| - gh-stale-branches | |
| - gh-codeowners-sync | |
| - gh-branch-protection | |
| - gh-repo-settings | |
| - gh-template-sync | |
| - gh-actions-usage | |
| - gh-environments-audit | |
| - gh-license-audit | |
| - gh-secrets-audit | |
| - gh-runners-selfhosted-status | |
| - gh-topic-manager | |
| extra-args: | |
| description: 'Additional arguments (e.g. --repo CS-MyProject, --verbose)' | |
| required: false | |
| default: '' | |
| dry-run: | |
| description: 'Dry run (show changes without applying)' | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| # ── Scheduled: runs weekly for recurring maintenance ── | |
| scheduled: | |
| if: github.event_name == 'schedule' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - script: gh-prefix-labels | |
| args: '--execute' | |
| - script: gh-dependabot-labels | |
| args: '--execute' | |
| name: 'scheduled: ${{ matrix.script }}' | |
| env: | |
| GH_TOKEN: ${{ secrets.DEVTOOLS_PAT }} | |
| steps: | |
| - name: Check DEVTOOLS_PAT | |
| id: auth | |
| env: | |
| TOKEN: ${{ secrets.DEVTOOLS_PAT }} | |
| run: | | |
| if [ -z "$TOKEN" ]; then | |
| echo "::warning::DEVTOOLS_PAT secret is not configured. Skipping script execution." | |
| echo "::warning::See workflow file header for setup instructions (Fine-grained or Classic PAT)." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: actions/checkout@v4 | |
| if: steps.auth.outputs.skip != 'true' | |
| - name: Install Python dependencies | |
| if: steps.auth.outputs.skip != 'true' | |
| run: pip install pyyaml | |
| - name: Resolve script path | |
| if: steps.auth.outputs.skip != 'true' | |
| id: resolve | |
| run: | | |
| SCRIPT_PY="services/devtools/scripts/${{ matrix.script }}.py" | |
| SCRIPT_SH="services/devtools/scripts/${{ matrix.script }}.sh" | |
| if [ -f "$SCRIPT_PY" ]; then | |
| echo "path=$SCRIPT_PY" >> "$GITHUB_OUTPUT" | |
| echo "runner=python" >> "$GITHUB_OUTPUT" | |
| elif [ -f "$SCRIPT_SH" ]; then | |
| echo "path=$SCRIPT_SH" >> "$GITHUB_OUTPUT" | |
| echo "runner=bash" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "::error::Script not found: ${{ matrix.script }}" | |
| exit 1 | |
| fi | |
| - name: Run ${{ matrix.script }} | |
| if: steps.auth.outputs.skip != 'true' | |
| run: | | |
| ${{ steps.resolve.outputs.runner }} ${{ steps.resolve.outputs.path }} ${{ matrix.args }} 2>&1 | tee /tmp/script-output.log | |
| - name: Job summary | |
| if: always() | |
| run: | | |
| if [ "${{ steps.auth.outputs.skip }}" = "true" ]; then | |
| echo "## ⚠️ ${{ matrix.script }} — Skipped" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "DEVTOOLS_PAT secret is not configured." >> "$GITHUB_STEP_SUMMARY" | |
| echo "See workflow file header for setup instructions." >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| echo "## 🔧 ${{ matrix.script }}" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Trigger**: Schedule (weekly)" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Args**: \`${{ matrix.args }}\`" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Status**: ${{ job.status }}" >> "$GITHUB_STEP_SUMMARY" | |
| if [ -f /tmp/script-output.log ]; then | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "<details><summary>Script output</summary>" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| sed 's/\x1b\[[0-9;]*m//g' /tmp/script-output.log >> "$GITHUB_STEP_SUMMARY" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| echo "</details>" >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| fi | |
| # ── Manual: any script via workflow_dispatch ── | |
| manual: | |
| if: github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| name: 'manual: ${{ inputs.script }}' | |
| env: | |
| GH_TOKEN: ${{ secrets.DEVTOOLS_PAT }} | |
| steps: | |
| - name: Check DEVTOOLS_PAT | |
| id: auth | |
| env: | |
| TOKEN: ${{ secrets.DEVTOOLS_PAT }} | |
| run: | | |
| if [ -z "$TOKEN" ]; then | |
| echo "::warning::DEVTOOLS_PAT secret is not configured. Skipping script execution." | |
| echo "::warning::See workflow file header for setup instructions (Fine-grained or Classic PAT)." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: actions/checkout@v4 | |
| if: steps.auth.outputs.skip != 'true' | |
| - name: Install Python dependencies | |
| if: steps.auth.outputs.skip != 'true' | |
| run: pip install pyyaml | |
| - name: Resolve script path | |
| if: steps.auth.outputs.skip != 'true' | |
| id: resolve | |
| run: | | |
| SCRIPT_PY="services/devtools/scripts/${{ inputs.script }}.py" | |
| SCRIPT_SH="services/devtools/scripts/${{ inputs.script }}.sh" | |
| if [ -f "$SCRIPT_PY" ]; then | |
| echo "path=$SCRIPT_PY" >> "$GITHUB_OUTPUT" | |
| echo "runner=python" >> "$GITHUB_OUTPUT" | |
| elif [ -f "$SCRIPT_SH" ]; then | |
| echo "path=$SCRIPT_SH" >> "$GITHUB_OUTPUT" | |
| echo "runner=bash" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "::error::Script not found: ${{ inputs.script }}" | |
| exit 1 | |
| fi | |
| - name: Build arguments | |
| if: steps.auth.outputs.skip != 'true' | |
| id: args | |
| run: | | |
| SCRIPT="${{ inputs.script }}" | |
| ARGS="" | |
| # Scripts use different dry-run patterns: | |
| # --execute pattern (default=dry-run): add --execute when dry-run is off | |
| # --dry-run pattern (default=execute): add --dry-run when dry-run is on | |
| # no toggle (read-only/direct): ignore dry-run setting | |
| EXECUTE_SCRIPTS="gh-prefix-labels gh-dependabot-labels gh-stale-branches gh-codeowners-sync gh-repo-settings gh-template-sync" | |
| DRYRUN_SCRIPTS="gh-labels-sync" | |
| if echo "$EXECUTE_SCRIPTS" | grep -qw "$SCRIPT"; then | |
| if [ "${{ inputs.dry-run }}" = "false" ]; then | |
| ARGS="--execute" | |
| fi | |
| elif echo "$DRYRUN_SCRIPTS" | grep -qw "$SCRIPT"; then | |
| if [ "${{ inputs.dry-run }}" = "true" ]; then | |
| ARGS="--dry-run" | |
| fi | |
| fi | |
| if [ -n "${{ inputs.extra-args }}" ]; then | |
| ARGS="$ARGS ${{ inputs.extra-args }}" | |
| fi | |
| echo "value=$ARGS" >> "$GITHUB_OUTPUT" | |
| - name: Run ${{ inputs.script }} | |
| if: steps.auth.outputs.skip != 'true' | |
| run: | | |
| ${{ steps.resolve.outputs.runner }} ${{ steps.resolve.outputs.path }} ${{ steps.args.outputs.value }} 2>&1 | tee /tmp/script-output.log | |
| - name: Job summary | |
| if: always() | |
| run: | | |
| if [ "${{ steps.auth.outputs.skip }}" = "true" ]; then | |
| echo "## ⚠️ ${{ inputs.script }} — Skipped" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "DEVTOOLS_PAT secret is not configured." >> "$GITHUB_STEP_SUMMARY" | |
| echo "See workflow file header for setup instructions." >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| echo "## 🔧 ${{ inputs.script }}" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Trigger**: Manual" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Dry run**: ${{ inputs.dry-run }}" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Args**: \`${{ steps.args.outputs.value }}\`" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Extra args**: \`${{ inputs.extra-args }}\`" >> "$GITHUB_STEP_SUMMARY" | |
| echo "- **Status**: ${{ job.status }}" >> "$GITHUB_STEP_SUMMARY" | |
| if [ -f /tmp/script-output.log ]; then | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "<details><summary>Script output</summary>" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| sed 's/\x1b\[[0-9;]*m//g' /tmp/script-output.log >> "$GITHUB_STEP_SUMMARY" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| echo "</details>" >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| fi |