diff --git a/.github/workflows/ci-pending.yml b/.github/workflows/ci-pending.yml index 090e33a..2b05274 100644 --- a/.github/workflows/ci-pending.yml +++ b/.github/workflows/ci-pending.yml @@ -11,6 +11,7 @@ permissions: jobs: mark-pending: runs-on: ubuntu-latest + environment: production if: "startsWith(github.event.issue.title, 'publish: ')" steps: - name: Get auth token @@ -20,6 +21,9 @@ jobs: client-id: ${{ vars.SENTRY_INTERNAL_APP_ID }} private-key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} + # Add the label first — this is the critical step. The poller + # token and variable set below are best-effort optimizations + # that must not block label addition. - name: Add ci-pending label env: # Use the app token so the label event triggers publish.yml @@ -29,3 +33,21 @@ jobs: gh issue edit "${{ github.event.issue.number }}" \ -R "$GITHUB_REPOSITORY" \ --add-label "ci-pending" + + # Best-effort: enable the cron poller variable. If this fails, the + # poller's cron will still pick up the issue (it just won't skip the + # runner provisioning on idle ticks until the variable is set). + - name: Get poller app token + id: poller-token + continue-on-error: true + uses: actions/create-github-app-token@v3 + with: + client-id: ${{ vars.CI_POLLER_APP_CLIENT_ID }} + private-key: ${{ secrets.CI_POLLER_APP_PRIVATE_KEY }} + + - name: Enable cron poller + if: steps.poller-token.outcome == 'success' + env: + GH_TOKEN: ${{ steps.poller-token.outputs.token }} + run: | + gh variable set CI_POLLER_HAS_PENDING -R "$GITHUB_REPOSITORY" -b "true" diff --git a/.github/workflows/ci-poller.yml b/.github/workflows/ci-poller.yml index cd83bdd..4d8e3fa 100644 --- a/.github/workflows/ci-poller.yml +++ b/.github/workflows/ci-poller.yml @@ -3,6 +3,7 @@ name: CI Status Poller on: schedule: - cron: "*/5 * * * *" + workflow_dispatch: permissions: contents: read @@ -11,29 +12,16 @@ permissions: jobs: check-ci: runs-on: ubuntu-latest + environment: production + # Skip entirely (no runner provisioned) when there's nothing to check. + # Set to "true" by ci-pending.yml, reset to "false" here when done. + # Always allow workflow_dispatch for manual recovery. + if: vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == 'workflow_dispatch' concurrency: group: ci-status-poller cancel-in-progress: false steps: - # Cheap first check with GITHUB_TOKEN — if no ci-pending issues exist, - # exit immediately without generating an app token (~5s idle cost). - - name: Check for pending issues - id: pending - env: - GH_TOKEN: ${{ github.token }} - run: | - count=$(gh issue list -R "$GITHUB_REPOSITORY" \ - --state open \ - --label ci-pending \ - --limit 1 \ - --json number -q 'length') - echo "count=${count}" >> "$GITHUB_OUTPUT" - if [[ "$count" == "0" ]]; then - echo "No ci-pending issues. Nothing to do." - fi - - name: Get auth token - if: steps.pending.outputs.count != '0' id: token uses: actions/create-github-app-token@v3 with: @@ -41,7 +29,6 @@ jobs: private-key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - name: Check CI status for ci-pending issues - if: steps.pending.outputs.count != '0' env: # Use the app token so label changes trigger publish.yml # (GITHUB_TOKEN events are suppressed by GitHub). @@ -55,6 +42,10 @@ jobs: --json number,title,labels,body) count=$(echo "$issues" | jq length) + if [[ "$count" == "0" ]]; then + echo "No ci-pending issues found." + exit 0 + fi echo "Found ${count} ci-pending issue(s)." # Check each issue's CI status @@ -182,3 +173,45 @@ jobs: gh issue comment "$number" -R "$GITHUB_REPOSITORY" --body "$comment" fi done + + # Cleanup: check if we should disable the poller. Runs even if the + # CI check step above failed, so CI_POLLER_HAS_PENDING doesn't get + # stuck on "true" permanently. + - name: Check for remaining pending issues + if: always() + id: remaining + env: + GH_TOKEN: ${{ github.token }} + run: | + count=$(gh issue list -R "$GITHUB_REPOSITORY" \ + --state open \ + --label ci-pending \ + --limit 1 \ + --json number -q 'length') + echo "count=${count}" >> "$GITHUB_OUTPUT" + + # Update the poller variable to match reality: + # - Remaining issues → ensure variable is "true" (important when + # workflow_dispatch bypassed the gate while variable was "false") + # - No remaining issues → set to "false" to stop the cron + # Placed after CI check so a token failure can't block CI checking. + - name: Get poller app token + if: always() + id: poller-token + uses: actions/create-github-app-token@v3 + with: + client-id: ${{ vars.CI_POLLER_APP_CLIENT_ID }} + private-key: ${{ secrets.CI_POLLER_APP_PRIVATE_KEY }} + + - name: Sync poller variable with pending issue state + if: always() && steps.poller-token.outcome == 'success' + env: + GH_TOKEN: ${{ steps.poller-token.outputs.token }} + run: | + if [[ "${{ steps.remaining.outputs.count }}" == "0" ]]; then + echo "All ci-pending issues resolved. Disabling poller." + gh variable set CI_POLLER_HAS_PENDING -R "$GITHUB_REPOSITORY" -b "false" + else + echo "Still pending issues. Ensuring poller stays enabled." + gh variable set CI_POLLER_HAS_PENDING -R "$GITHUB_REPOSITORY" -b "true" + fi