Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 28 additions & 33 deletions .github/workflows/ci-poller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,27 @@ jobs:
# (GITHUB_TOKEN events are suppressed by GitHub).
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
# Find all open issues with ci-pending label (include body to extract commit SHA)
# Only check issues that have BOTH ci-pending AND accepted labels.
# This avoids polling for abandoned releases that nobody approved.
issues=$(gh issue list -R "$GITHUB_REPOSITORY" \
--state open \
--label ci-pending \
--label accepted \
--limit 200 \
--json number,title,labels,body)

count=$(echo "$issues" | jq length)
if [[ "$count" == "0" ]]; then
echo "No ci-pending issues found."
echo "No ci-pending + accepted issues found."
exit 0
fi
echo "Found ${count} ci-pending issue(s)."
echo "Found ${count} ci-pending + accepted issue(s)."

# Check each issue's CI status
echo "$issues" | jq -c '.[]' | while read -r issue; do
number=$(echo "$issue" | jq -r '.number')
title=$(echo "$issue" | jq -r '.title')
Comment thread
sentry[bot] marked this conversation as resolved.
body=$(echo "$issue" | jq -r '.body')
has_accepted=$(echo "$issue" | jq '[.labels[].name] | any(. == "accepted")')

# Parse repo and version from title: "publish: owner/repo[/path]@version"
# Only take owner/repo (first two segments) — monorepos like
Expand Down Expand Up @@ -173,38 +174,31 @@ jobs:
gh issue comment "$number" -R "$GITHUB_REPOSITORY" --body "$comment"

elif [[ "$pending_checks" == "0" && "$unsuccessful_checks" != "0" ]]; then
# All checks completed but some failed — notify the author.
Comment thread
cursor[bot] marked this conversation as resolved.
# Only comment once per SHA to avoid spam on every poller tick.
marker="<!-- ci-failure-${sha} -->"
existing=$(gh issue view "$number" -R "$GITHUB_REPOSITORY" \
--json comments -q "[.comments[].body | select(contains(\"${marker}\"))] | length" 2>/dev/null || echo "0")

if [[ "$existing" == "0" ]]; then
echo " CI failed. Commenting on issue."
failed_names=$(echo "$all_checks" | jq -rs '[.[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "neutral" and .conclusion != "skipped") | .name] | join(", ")')
body="${marker}"$'\n'"CI checks **failed** for ${repo}@${version} (\`${sha:0:8}\`). Publishing is blocked until CI passes."$'\n\n'"Failed checks: ${failed_names}"$'\n\n'"[View check runs](https://github.com/${repo}/commit/${sha}/checks/)"
gh issue comment "$number" -R "$GITHUB_REPOSITORY" --body "$body"
else
echo " CI failed (already commented for this SHA)."
fi
# All checks completed but some failed.
# Swap ci-pending → ci-failed, remove accepted to stop polling.
# The author must fix CI and re-add accepted to retry.
echo " CI failed! Swapping ci-pending → ci-failed and removing accepted."
gh issue edit "$number" -R "$GITHUB_REPOSITORY" \
--remove-label "ci-pending" \
--remove-label "accepted" \
--add-label "ci-failed"

failed_names=$(echo "$all_checks" | jq -rs '[.[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "neutral" and .conclusion != "skipped") | .name] | join(", ")')
comment_body="CI checks **failed** for ${repo}@${version} (\`${sha:0:8}\`). Publishing is blocked."$'\n\n'"Failed checks: ${failed_names}"$'\n\n'"[View check runs](https://github.com/${repo}/commit/${sha}/checks/)"$'\n\n'"Re-add the **accepted** label once CI is fixed to retry."
gh issue comment "$number" -R "$GITHUB_REPOSITORY" --body "$comment_body"

elif [[ "$commit_status" == "failure" && "$pending_checks" == "0" && "$unsuccessful_checks" == "0" ]]; then
# All check runs passed but commit statuses reported a failure.
# Note: we check for "failure" explicitly, not just !status_ok,
# because "pending" statuses should fall through to retry next tick.
marker="<!-- ci-status-failure-${sha} -->"
existing=$(gh issue view "$number" -R "$GITHUB_REPOSITORY" \
--json comments -q "[.comments[].body | select(contains(\"${marker}\"))] | length" 2>/dev/null || echo "0")

if [[ "$existing" == "0" ]]; then
echo " CI failed (commit status). Commenting on issue."
failed_contexts=$(gh api "repos/${repo}/commits/${sha}/status" \
--jq '[.statuses[] | select(.state == "failure" or .state == "error")] | map(.context + " (" + .state + ")") | join(", ")')
body="${marker}"$'\n'"CI **commit status** checks failed for ${repo}@${version} (\`${sha:0:8}\`). Publishing is blocked until CI passes."$'\n\n'"Failed status checks: ${failed_contexts}"$'\n\n'"[View check runs](https://github.com/${repo}/commit/${sha}/checks/)"
gh issue comment "$number" -R "$GITHUB_REPOSITORY" --body "$body"
else
echo " CI failed via commit status (already commented for this SHA)."
fi
echo " CI failed (commit status)! Swapping ci-pending → ci-failed and removing accepted."
gh issue edit "$number" -R "$GITHUB_REPOSITORY" \
--remove-label "ci-pending" \
--remove-label "accepted" \
--add-label "ci-failed"

failed_contexts=$(gh api "repos/${repo}/commits/${sha}/status" \
--jq '[.statuses[] | select(.state == "failure" or .state == "error")] | map(.context + " (" + .state + ")") | join(", ")')
comment_body="CI **commit status** checks failed for ${repo}@${version} (\`${sha:0:8}\`). Publishing is blocked."$'\n\n'"Failed status checks: ${failed_contexts}"$'\n\n'"[View check runs](https://github.com/${repo}/commit/${sha}/checks/)"$'\n\n'"Re-add the **accepted** label once CI is fixed to retry."
gh issue comment "$number" -R "$GITHUB_REPOSITORY" --body "$comment_body"
fi
done

Expand All @@ -220,6 +214,7 @@ jobs:
count=$(gh issue list -R "$GITHUB_REPOSITORY" \
--state open \
--label ci-pending \
--label accepted \
--limit 1 \
--json number -q 'length')
echo "count=${count}" >> "$GITHUB_OUTPUT"
Comment thread
BYK marked this conversation as resolved.
Expand Down
44 changes: 39 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,69 @@ permissions:
packages: write

jobs:
# Lightweight job: comment when approved but CI hasn't finished yet
# When accepted is added but CI isn't ready yet, comment and trigger the poller.
# Also handles the ci-failed → ci-pending retry flow.
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')
&& (contains(github.event.issue.labels.*.name, 'ci-pending')
|| contains(github.event.issue.labels.*.name, 'ci-failed'))
steps:
- name: Get auth token
id: token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.SENTRY_INTERNAL_APP_ID }}
private-key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }}

# If the issue has ci-failed (retry after fix), swap back to ci-pending.
- name: Reset ci-failed to ci-pending
if: contains(github.event.issue.labels.*.name, 'ci-failed')
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh issue edit "${{ github.event.issue.number }}" \
-R "$GITHUB_REPOSITORY" \
--remove-label "ci-failed" \
--add-label "ci-pending"

- name: Comment on issue
env:
GH_TOKEN: ${{ github.token }}
run: |
if [[ "${{ contains(github.event.issue.labels.*.name, 'ci-failed') }}" == "true" ]]; then
body="Retrying — CI was previously failed. Checking CI status now."
else
body="Approved, but CI is still running on the release branch. Publishing will start automatically when CI passes."
fi
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."
--body "$body"

# Trigger the CI poller immediately instead of waiting for the next cron tick.
# Uses the app token — GITHUB_TOKEN workflow_dispatch events are suppressed.
- name: Trigger CI poller
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY"

publish:
runs-on: ubuntu-latest
environment: production
name: Publish a new version
# Run when:
# - accepted (with no ci-pending blocking), OR
# - accepted (with no ci-pending/ci-failed blocking), OR
# - ci-ready added (and accepted is already present)
# In all cases accepted must be present and ci-pending must not be.
# In all cases accepted must be present and ci-pending/ci-failed must not be.
if: >-
github.event.issue.state == 'open'
&& contains(github.event.issue.labels.*.name, 'accepted')
&& !contains(github.event.issue.labels.*.name, 'ci-pending')
&& !contains(github.event.issue.labels.*.name, 'ci-failed')
&& (github.event.label.name == 'accepted' || github.event.label.name == 'ci-ready')
timeout-minutes: 90
env:
Expand Down
Loading