Sync Repository Settings #5
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: Sync Repository Settings | |
| on: | |
| schedule: | |
| # Every Sunday at midnight UTC | |
| - cron: "0 0 * * 0" | |
| workflow_dispatch: | |
| inputs: | |
| mode: | |
| description: "Run mode" | |
| required: true | |
| default: "--dry-run" | |
| type: choice | |
| options: | |
| - "--dry-run" | |
| - "--apply" | |
| concurrency: | |
| group: settings-sync | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| sync: | |
| name: Sync Settings | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Run settings sync | |
| id: sync | |
| uses: ./.github/actions/sync-settings | |
| with: | |
| mode: ${{ github.event.inputs.mode || '--apply' }} | |
| github_token: ${{ secrets.ORG_SETTINGS_PAT }} | |
| - name: Upload report artifact | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: sync-report-${{ github.run_number }} | |
| path: reports/sync-report.md | |
| retention-days: 90 | |
| - name: Post job summary | |
| if: always() | |
| run: | | |
| { | |
| echo "## Settings Sync Results" | |
| echo "" | |
| echo "| Metric | Value |" | |
| echo "| --- | --- |" | |
| echo "| Repositories scanned | $TOTAL_REPOS |" | |
| echo "| Compliant | $COMPLIANT |" | |
| echo "| Drift detected | $DRIFT |" | |
| echo "| Mode | $MODE |" | |
| echo "" | |
| echo "### Full Report" | |
| echo "" | |
| cat reports/sync-report.md | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| env: | |
| TOTAL_REPOS: ${{ steps.sync.outputs.total_repos }} | |
| COMPLIANT: ${{ steps.sync.outputs.compliant }} | |
| DRIFT: ${{ steps.sync.outputs.drift }} | |
| MODE: ${{ github.event.inputs.mode || '--apply' }} | |
| - name: Create drift issue | |
| if: steps.sync.outputs.has_drift == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_SETTINGS_PAT }} | |
| DRIFT: ${{ steps.sync.outputs.drift }} | |
| TOTAL_REPOS: ${{ steps.sync.outputs.total_repos }} | |
| RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| SYNC_MODE: ${{ github.event.inputs.mode || '--apply' }} | |
| run: | | |
| TITLE="chore: settings drift detected — $(date '+%Y-%m-%d')" | |
| BODY="## Settings Drift Report | |
| **Run**: $RUN_URL | |
| **Mode**: $SYNC_MODE | |
| **Repos with drift**: $DRIFT / $TOTAL_REPOS | |
| See the [workflow run]($RUN_URL) for the full report." | |
| # Create new issue first, then close old ones | |
| if ! gh issue create --title "$TITLE" --body "$BODY" --label "settings-drift"; then | |
| echo "::error::Failed to create drift issue" | |
| exit 1 | |
| fi | |
| # Close previous drift issues (all except the one just created) | |
| LATEST=$(gh issue list --label "settings-drift" --state open --json number --jq '.[0].number') | |
| gh issue list --label "settings-drift" --state open --json number --jq '.[].number' | while read -r num; do | |
| if [ "$num" != "$LATEST" ]; then | |
| gh issue close "$num" --comment "Superseded by new sync run." | |
| fi | |
| done | |
| - name: Close drift issue if compliant | |
| if: steps.sync.outputs.has_drift == 'false' | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_SETTINGS_PAT }} | |
| run: | | |
| gh issue list --label "settings-drift" --state open --json number --jq '.[].number' | while read -r num; do | |
| gh issue close "$num" --comment "All repositories are now compliant." | |
| done | |
| new-repo-check: | |
| name: Discover New Repositories | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Check for new repos | |
| id: newrepos | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_SETTINGS_PAT }} | |
| run: | | |
| mkdir -p reports | |
| { | |
| echo "## New Repository Discovery" | |
| echo "" | |
| } > reports/new-repos.md | |
| WEEK_AGO=$(date -u -d '7 days ago' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null \ | |
| || date -u -v-7d '+%Y-%m-%dT%H:%M:%SZ') | |
| NEW_REPOS=$(gh repo list gamaware --no-archived --json name,createdAt \ | |
| --jq "[.[] | select(.createdAt > \"$WEEK_AGO\")] | .[].name" \ | |
| --limit 1000 || echo "") | |
| if [ -n "$NEW_REPOS" ]; then | |
| echo "has_new=true" >> "$GITHUB_OUTPUT" | |
| { | |
| echo "New repositories found in the last 7 days:" | |
| echo "" | |
| echo "$NEW_REPOS" | while read -r repo; do | |
| echo "- **$repo**" | |
| done | |
| echo "" | |
| echo "These repositories will be included in the next settings sync." | |
| } >> reports/new-repos.md | |
| else | |
| echo "has_new=false" >> "$GITHUB_OUTPUT" | |
| echo "No new repositories found in the last 7 days." >> reports/new-repos.md | |
| fi | |
| cat reports/new-repos.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Create issue for new repos | |
| if: steps.newrepos.outputs.has_new == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_SETTINGS_PAT }} | |
| run: | | |
| BODY=$(cat reports/new-repos.md) | |
| gh issue create \ | |
| --title "chore: new repositories discovered — $(date '+%Y-%m-%d')" \ | |
| --body "$BODY" \ | |
| --label "new-repo" | |
| - name: Upload new repos report | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: new-repos-report-${{ github.run_number }} | |
| path: reports/new-repos.md | |
| retention-days: 30 |