diff --git a/.github/workflows/ci-ready.yml b/.github/workflows/ci-ready.yml new file mode 100644 index 0000000..9a00a94 --- /dev/null +++ b/.github/workflows/ci-ready.yml @@ -0,0 +1,104 @@ +name: CI Ready Signal + +on: + repository_dispatch: + types: [ci-ready] + +# client_payload schema: +# repo: "getsentry/sentry-native" (full owner/repo) +# version: "0.13.4" +# sha: "abc123..." (the release branch HEAD SHA) + +permissions: + contents: read + issues: read + +jobs: + signal: + runs-on: ubuntu-latest + name: Process CI-ready signal + steps: + - name: Find matching publish issue + id: find-issue + env: + REPO: ${{ github.event.client_payload.repo }} + VERSION: ${{ github.event.client_payload.version }} + run: | + title="publish: ${REPO}@${VERSION}" + echo "Looking for issue: ${title}" + + # Find matching open issue by exact title match. + # Use --limit 200 to handle active repos with many open issues. + issue=$(gh issue list -R "$GITHUB_REPOSITORY" \ + --state open \ + --limit 200 \ + --json number,title,labels \ + | jq -r --arg t "$title" \ + '[.[] | select(.title == $t)] | first // empty') + + if [[ -z "$issue" ]]; then + # Retry a few times in case the issue hasn't been created yet + for i in 1 2 3; do + echo "Issue not found, retry ${i}/3 in 10s..." + sleep 10 + issue=$(gh issue list -R "$GITHUB_REPOSITORY" \ + --state open \ + --limit 200 \ + --json number,title,labels \ + | jq -r --arg t "$title" \ + '[.[] | select(.title == $t)] | first // empty') + if [[ -n "$issue" ]]; then break; fi + done + fi + + if [[ -z "$issue" ]]; then + echo "::warning::No open issue found with title: ${title}" + exit 0 + fi + + number=$(echo "$issue" | jq -r '.number') + has_ci_pending=$(echo "$issue" | jq '[.labels[].name] | any(. == "ci-pending")') + + if [[ "$has_ci_pending" != "true" ]]; then + echo "::warning::Issue #${number} does not have ci-pending label. Ignoring signal." + exit 0 + fi + + has_accepted=$(echo "$issue" | jq '[.labels[].name] | any(. == "accepted")') + + echo "number=${number}" >> "$GITHUB_OUTPUT" + echo "has_accepted=${has_accepted}" >> "$GITHUB_OUTPUT" + echo "Found issue #${number} with ci-pending label (accepted=${has_accepted})" + + # Use a GitHub App token so the label change triggers publish.yml. + # GITHUB_TOKEN events are deliberately suppressed by GitHub and + # would not create new workflow runs. + - name: Get auth token + if: steps.find-issue.outputs.number + id: token + uses: actions/create-github-app-token@v2.2.1 + with: + app-id: ${{ vars.SENTRY_INTERNAL_APP_ID }} + private-key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} + + - name: Add ci-ready label + if: steps.find-issue.outputs.number + env: + # Override the default GITHUB_TOKEN with the app token so the + # label event triggers publish.yml (GITHUB_TOKEN events are + # suppressed by GitHub and would not start new workflow runs). + GH_TOKEN: ${{ steps.token.outputs.token }} + ISSUE_NUMBER: ${{ steps.find-issue.outputs.number }} + SHA: ${{ github.event.client_payload.sha }} + REPO: ${{ github.event.client_payload.repo }} + run: | + gh issue edit "$ISSUE_NUMBER" -R "$GITHUB_REPOSITORY" \ + --remove-label "ci-pending" \ + --add-label "ci-ready" + + if [[ "${{ steps.find-issue.outputs.has_accepted }}" == "true" ]]; then + comment="CI checks passed for ${REPO} (\`${SHA:0:8}\`). Publishing is starting now." + else + comment="CI checks passed for ${REPO} (\`${SHA:0:8}\`). Publishing will start once the **accepted** label is also present." + fi + gh issue comment "$ISSUE_NUMBER" -R "$GITHUB_REPOSITORY" --body "$comment" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 426acc5..7d7e167 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,17 +3,46 @@ on: issues: types: [labeled] +concurrency: + # Use the issue title (e.g. "publish: getsentry/foo@1.2.3") so duplicate + # issues for the same repo@version share a concurrency group. + group: ${{ github.event.issue.title }} + cancel-in-progress: false + permissions: contents: read issues: write packages: write jobs: + # Lightweight job: comment when approved but CI hasn't finished yet + waiting-for-ci: + runs-on: ubuntu-latest + name: Waiting for CI + if: >- + github.event.label.name == 'accepted' + && github.event.issue.state == 'open' + && contains(github.event.issue.labels.*.name, 'ci-pending') + steps: + - name: Comment on issue + run: | + gh issue comment "${{ github.event.issue.number }}" \ + -R "$GITHUB_REPOSITORY" \ + --body "Approved, but CI is still running on the release branch. Publishing will start automatically when CI passes." + publish: runs-on: ubuntu-latest environment: production name: Publish a new version - if: github.event.label.name == 'accepted' && github.event.issue.state == 'open' + # Run when: + # - accepted (with no ci-pending blocking), OR + # - ci-ready added (and accepted is already present) + # In all cases accepted must be present and ci-pending must not be. + if: >- + github.event.issue.state == 'open' + && contains(github.event.issue.labels.*.name, 'accepted') + && !contains(github.event.issue.labels.*.name, 'ci-pending') + && (github.event.label.name == 'accepted' || github.event.label.name == 'ci-ready') timeout-minutes: 90 env: SENTRY_DSN: "https://303a687befb64dc2b40ce4c96de507c5@o1.ingest.sentry.io/6183838"