Collect and Publish #27
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: Collect and Publish | |
| on: | |
| schedule: | |
| - cron: "0 6 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| skip_collect: | |
| description: "Republish existing retained data without collecting" | |
| type: boolean | |
| required: true | |
| default: false | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: reponomics-retained-state-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| collect: | |
| if: ${{ github.ref == 'refs/heads/main' && (github.event_name != 'workflow_dispatch' || !inputs.skip_collect) }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| actions: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: main | |
| - name: Resolve Reponomics configuration | |
| run: python .github/scripts/resolve-reponomics-config.py --require-setup | |
| - name: Refuse incomplete key rotation | |
| if: env.REPONOMICS_SETUP_COMPLETE == 'true' | |
| env: | |
| DASHBOARD_NEXT_SECRET: ${{ secrets.DASHBOARD_NEXT_SECRET }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${DASHBOARD_NEXT_SECRET:-}" ]; then | |
| { | |
| echo "## Collection stopped" | |
| echo | |
| echo "\`DASHBOARD_NEXT_SECRET\` is still set." | |
| echo "Finish key rotation by replacing \`DASHBOARD_SECRET_DO_NOT_REPLACE\`" | |
| echo "with the new key, then delete \`DASHBOARD_NEXT_SECRET\`." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| - name: Mint GitHub App installation token (advanced) | |
| id: collection_app_token | |
| if: ${{ env.REPONOMICS_SETUP_COMPLETE == 'true' && env.USE_GITHUB_APP == 'true' }} | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ vars.COLLECTION_APP_ID || secrets.COLLECTION_APP_ID }} | |
| private-key: ${{ secrets.COLLECTION_APP_PRIVATE_KEY }} | |
| owner: ${{ github.repository_owner }} | |
| - name: Resolve collection token | |
| id: resolve_collection_token | |
| if: env.REPONOMICS_SETUP_COMPLETE == 'true' | |
| env: | |
| USE_GITHUB_APP: ${{ env.USE_GITHUB_APP }} | |
| COLLECTION_TOKEN: ${{ secrets.COLLECTION_TOKEN }} | |
| APP_COLLECTION_TOKEN: ${{ steps.collection_app_token.outputs.token }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$USE_GITHUB_APP" = "true" ]; then | |
| if [ -z "${APP_COLLECTION_TOKEN:-}" ]; then | |
| { | |
| echo "## Collection stopped" | |
| echo | |
| echo "Advanced GitHub App collection mode is enabled, but no installation token was minted." | |
| echo "Set \`vars.COLLECTION_APP_ID\` and \`secrets.COLLECTION_APP_PRIVATE_KEY\`," | |
| echo "then run collection again." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| if [[ "$APP_COLLECTION_TOKEN" == *$'\n'* || "$APP_COLLECTION_TOKEN" == *$'\r'* ]]; then | |
| { | |
| echo "## Collection stopped" | |
| echo | |
| echo "Advanced GitHub App collection mode produced an invalid multiline token." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| printf '%s=%s\n' collection_token "$APP_COLLECTION_TOKEN" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ -z "${COLLECTION_TOKEN:-}" ]; then | |
| { | |
| echo "## Collection stopped" | |
| echo | |
| echo "Missing \`COLLECTION_TOKEN\` secret for PAT-based collection mode." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| if [[ "$COLLECTION_TOKEN" == *$'\n'* || "$COLLECTION_TOKEN" == *$'\r'* ]]; then | |
| { | |
| echo "## Collection stopped" | |
| echo | |
| echo "\`COLLECTION_TOKEN\` must be a single-line token value." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| printf '%s=%s\n' collection_token "$COLLECTION_TOKEN" >> "$GITHUB_OUTPUT" | |
| - name: Collect retained dashboard data | |
| if: env.REPONOMICS_SETUP_COMPLETE == 'true' | |
| uses: ./.github/actions/reponomics | |
| with: | |
| mode: collect | |
| collection-token: ${{ steps.resolve_collection_token.outputs.collection_token }} | |
| use-github-app: ${{ env.USE_GITHUB_APP }} | |
| github-token: ${{ github.token }} | |
| dashboard-secret: ${{ secrets.DASHBOARD_SECRET_DO_NOT_REPLACE }} | |
| data-mode: ${{ env.DATA_MODE }} | |
| retention-days: ${{ env.RETENTION_DAYS }} | |
| publish-pages: ${{ env.PUBLISH_PAGES_DASHBOARD }} | |
| generate-readme: ${{ env.PUBLISH_README_DASHBOARD }} | |
| publish: | |
| needs: collect | |
| if: ${{ github.ref == 'refs/heads/main' && (github.event_name != 'workflow_dispatch' || !inputs.skip_collect) }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| actions: read | |
| pages: write | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: main | |
| - name: Resolve Reponomics configuration | |
| run: python .github/scripts/resolve-reponomics-config.py --require-setup | |
| - name: Publish dashboard outputs | |
| if: >- | |
| env.REPONOMICS_SETUP_COMPLETE == 'true' && | |
| (env.PUBLISH_PAGES_DASHBOARD == 'true' || env.PUBLISH_README_DASHBOARD == 'true') | |
| uses: ./.github/actions/reponomics | |
| with: | |
| mode: publish | |
| artifact-run-id: ${{ github.run_id }} | |
| github-token: ${{ github.token }} | |
| dashboard-secret: ${{ secrets.DASHBOARD_SECRET_DO_NOT_REPLACE }} | |
| data-mode: ${{ env.DATA_MODE }} | |
| retention-days: ${{ env.RETENTION_DAYS }} | |
| publish-pages: ${{ env.PUBLISH_PAGES_DASHBOARD }} | |
| generate-readme: ${{ env.PUBLISH_README_DASHBOARD }} | |
| auto-doctor-cadence: | |
| needs: publish | |
| if: ${{ always() && github.ref == 'refs/heads/main' && (github.event_name != 'workflow_dispatch' || !inputs.skip_collect) }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| due: ${{ steps.auto_doctor_cadence.outputs.due }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: main | |
| - name: Resolve Reponomics configuration | |
| run: python .github/scripts/resolve-reponomics-config.py --require-setup | |
| - name: Check auto-doctor cadence | |
| id: auto_doctor_cadence | |
| if: >- | |
| env.REPONOMICS_SETUP_COMPLETE == 'true' && | |
| env.AUTO_DOCTOR_EVERY_N_DAYS != '0' && | |
| (env.PUBLISH_PAGES_DASHBOARD == 'true' || env.PUBLISH_README_DASHBOARD == 'true') | |
| run: python .github/scripts/auto-doctor-state.py --interval-days "$AUTO_DOCTOR_EVERY_N_DAYS" check | |
| auto-doctor: | |
| needs: auto-doctor-cadence | |
| if: ${{ needs.auto-doctor-cadence.outputs.due == 'true' }} | |
| permissions: | |
| contents: read | |
| actions: read | |
| uses: ./.github/workflows/doctor.yml | |
| with: | |
| artifact_run_id: ${{ github.run_id }} | |
| secrets: inherit | |
| auto-doctor-marker: | |
| needs: | |
| - auto-doctor-cadence | |
| - auto-doctor | |
| if: ${{ always() && needs.auto-doctor-cadence.outputs.due == 'true' && needs.auto-doctor.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: main | |
| - name: Resolve Reponomics configuration | |
| run: python .github/scripts/resolve-reponomics-config.py --require-setup | |
| - name: Mark successful auto-doctor | |
| id: auto_doctor_marker | |
| run: python .github/scripts/auto-doctor-state.py --interval-days "$AUTO_DOCTOR_EVERY_N_DAYS" --run-id "$GITHUB_RUN_ID" mark | |
| - name: Commit auto-doctor marker | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add .reponomics/auto-doctor.json | |
| if git diff --cached --quiet; then | |
| exit 0 | |
| fi | |
| git commit -m "chore: record Reponomics auto-doctor [skip ci]" | |
| git pull --rebase origin "${GITHUB_REF_NAME:-main}" | |
| git push | |
| republish: | |
| if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch' && inputs.skip_collect }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| actions: read | |
| pages: write | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: main | |
| - name: Resolve Reponomics configuration | |
| run: python .github/scripts/resolve-reponomics-config.py --require-setup | |
| - name: Republish dashboard outputs | |
| if: >- | |
| env.REPONOMICS_SETUP_COMPLETE == 'true' && | |
| (env.PUBLISH_PAGES_DASHBOARD == 'true' || env.PUBLISH_README_DASHBOARD == 'true') | |
| uses: ./.github/actions/reponomics | |
| with: | |
| mode: publish | |
| github-token: ${{ github.token }} | |
| dashboard-secret: ${{ secrets.DASHBOARD_SECRET_DO_NOT_REPLACE }} | |
| data-mode: ${{ env.DATA_MODE }} | |
| retention-days: ${{ env.RETENTION_DAYS }} | |
| publish-pages: ${{ env.PUBLISH_PAGES_DASHBOARD }} | |
| generate-readme: ${{ env.PUBLISH_README_DASHBOARD }} |