-
Notifications
You must be signed in to change notification settings - Fork 17
chore: unify build/lint/tests PR comments into one #9617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
8166015
chore: unify build/lint/tests PR comments into one
dalkia 86a3c6f
chore: fold build-pending workflow into pr-comment-artifact-url
dalkia a7b40db
fix: grant actions:read so the lint warning-result download works
dalkia 1a2cdd7
fix: harden CI status comment against marker injection and non-conver…
dalkia 466e280
chore: pin PR-comment checkouts to @v6 and drop persisted credentials
dalkia 33aac9b
fix: JSON-escape fork-controlled fields in the perf-test dispatch pay…
dalkia 8f65fa9
Update .github/actions/ci-status-comment/upsert-ci-status.sh
dalkia d7e0b69
Update .github/actions/ci-status-comment/upsert-ci-status.sh
dalkia d51f3d4
Update .github/actions/ci-status-comment/upsert-ci-status.sh
dalkia 3a78259
Update .github/actions/ci-status-comment/upsert-ci-status.sh
dalkia 0b72bb7
Merge branch 'dev' into chore/unify-ci-status-comment
dalkia cfb643e
Merge branch 'dev' into chore/unify-ci-status-comment
dalkia 3a74619
Merge branch 'dev' into chore/unify-ci-status-comment
dalkia 70dedcf
Merge branch 'dev' into chore/unify-ci-status-comment
dalkia 72905d1
fix: flatten paginated recheck read and scrub .line in warning comment
dalkia 6e857e7
Merge branch 'dev' into chore/unify-ci-status-comment
dalkia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| name: Upsert CI Status Comment | ||
| description: >- | ||
| Create or update the single unified CI status comment on a PR, replacing only | ||
| the given section (build | lint | tests). Seeds a skeleton with all three | ||
| sections the first time it runs, and re-reads/retries so concurrent writers | ||
| (build vs. Unity Test) never clobber each other's section. | ||
|
|
||
| inputs: | ||
| pr-number: | ||
| description: Pull request number to comment on. | ||
| required: true | ||
| section: | ||
| description: Which section to replace — one of build, lint, tests. | ||
| required: true | ||
| body: | ||
| description: Markdown for this section (inline badge + message). Rendered as-is between the section markers. | ||
| required: true | ||
| github-token: | ||
| description: Token with pull-requests:write used to read and upsert the comment. | ||
| required: true | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Upsert unified CI status comment | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ inputs.github-token }} | ||
| REPO: ${{ github.repository }} | ||
| PR_NUMBER: ${{ inputs.pr-number }} | ||
| SECTION: ${{ inputs.section }} | ||
| SECTION_BODY: ${{ inputs.body }} | ||
| run: bash "$GITHUB_ACTION_PATH/upsert-ci-status.sh" |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| #!/usr/bin/env bash | ||
| # Create or update the single unified CI status comment on a PR, replacing only | ||
| # one section (build | lint | tests). All four CI comment workflows call this | ||
| # through the ci-status-comment composite action, so the three separate bot | ||
| # comments collapse into one. | ||
|
dalkia marked this conversation as resolved.
|
||
| # | ||
| # The comment is keyed by the hidden <!-- ci-status --> marker and holds three | ||
| # sections, each fenced by its own start/end markers: | ||
| # | ||
| # <!-- ci-status --> | ||
| # ### 🚦 CI Status | ||
| # <!-- ci:build:start --> …build… <!-- ci:build:end --> | ||
| # <!-- ci:lint:start --> …lint… <!-- ci:lint:end --> | ||
| # <!-- ci:tests:start --> …tests… <!-- ci:tests:end --> | ||
| # | ||
| # Build and Unity Test run as independent workflows whose comment writers can | ||
| # fire at the same time, so a plain read-modify-write would drop a section or | ||
| # create a duplicate comment. Each attempt collapses any duplicates (keeping the | ||
| # oldest), rewrites only its own section on that comment, then re-reads to | ||
| # confirm the section landed and no duplicate slipped in — retrying otherwise. | ||
| set -euo pipefail | ||
|
|
||
| MARKER="<!-- ci-status -->" | ||
| HEADER="### 🚦 CI Status" | ||
| BOT="github-actions[bot]" | ||
| START="<!-- ci:${SECTION}:start -->" | ||
| END="<!-- ci:${SECTION}:end -->" | ||
|
dalkia marked this conversation as resolved.
|
||
|
|
||
| # Neutral "waiting" placeholder for a section that has not reported yet. Used | ||
|
dalkia marked this conversation as resolved.
|
||
| # only when seeding a brand-new comment; a real run always overwrites its own. | ||
| section_default() { | ||
| case "$1" in | ||
| build) printf '\n\n_Waiting for the build to start…_' ;; | ||
| lint) printf '\n\n_Waiting for lint to start…_' ;; | ||
| tests) printf '\n\n_Waiting for tests to start…_' ;; | ||
| esac | ||
| } | ||
|
|
||
| # One section, fenced by its start/end markers. | ||
| wrap_section() { printf '<!-- ci:%s:start -->\n%s\n<!-- ci:%s:end -->' "$1" "$2" "$1"; } | ||
|
|
||
| # A fresh comment with every section defaulted to "waiting". | ||
| skeleton() { | ||
| printf '%s\n%s\n\n%s\n\n%s\n\n%s\n' \ | ||
| "$MARKER" "$HEADER" \ | ||
| "$(wrap_section build "$(section_default build)")" \ | ||
| "$(wrap_section lint "$(section_default lint)")" \ | ||
| "$(wrap_section tests "$(section_default tests)")" | ||
| } | ||
|
|
||
| # Emit the section body for this run to a file so awk can splice it verbatim, | ||
| # free of shell quoting concerns. | ||
| printf '%s\n' "$SECTION_BODY" > section_body.md | ||
|
dalkia marked this conversation as resolved.
Outdated
|
||
| WANT="$(cat section_body.md)" | ||
|
|
||
| # Replace the content between START and END in $1 with section_body.md. | ||
| replace_section() { | ||
| awk -v s="$START" -v e="$END" -v f="section_body.md" ' | ||
| $0==s { print; while ((getline line < f) > 0) print line; close(f); skip=1; next } | ||
| $0==e { print; skip=0; next } | ||
| skip { next } | ||
| { print } | ||
| ' <<< "$1" | ||
| } | ||
|
|
||
| # Trimmed content currently between START and END in $1 (for the survive check). | ||
| extract_section() { | ||
| awk -v s="$START" -v e="$END" ' | ||
| $0==s { grab=1; next } | ||
| $0==e { grab=0; next } | ||
| grab { print } | ||
| ' <<< "$1" | ||
| } | ||
|
|
||
| # IDs of every marker-bearing bot comment on the PR, oldest first. | ||
| marker_ids() { | ||
| jq -r --arg m "$MARKER" --arg bot "$BOT" \ | ||
| '[.[] | select(.user.login==$bot and (.body|contains($m)))] | sort_by(.id) | .[].id' <<< "$1" | ||
| } | ||
|
|
||
| for attempt in 1 2 3 4 5; do | ||
| COMMENTS=$(gh api "/repos/$REPO/issues/$PR_NUMBER/comments" --paginate) | ||
| IDS=() | ||
| while IFS= read -r line; do [ -n "$line" ] && IDS+=("$line"); done <<< "$(marker_ids "$COMMENTS")" | ||
| COMMENT_ID="${IDS[0]:-}" | ||
|
|
||
| # Collapse accidental duplicates from a create race: keep the oldest, drop the rest. | ||
| if [ "${#IDS[@]}" -gt 1 ]; then | ||
| for extra in "${IDS[@]:1}"; do | ||
| echo "Deleting duplicate CI status comment $extra." | ||
| gh api -X DELETE "/repos/$REPO/issues/comments/$extra" >/dev/null || true | ||
| done | ||
| fi | ||
|
dalkia marked this conversation as resolved.
|
||
|
|
||
| if [ -n "$COMMENT_ID" ]; then | ||
| CURRENT_BODY=$(jq -r --arg id "$COMMENT_ID" '.[] | select(.id==($id|tonumber)) | .body' <<< "$COMMENTS") | ||
|
dalkia marked this conversation as resolved.
Outdated
|
||
| else | ||
| CURRENT_BODY="" | ||
| fi | ||
|
|
||
| # No unified comment yet, or one missing our section markers: start clean so | ||
| # all three sections are always present. | ||
| if [ -z "$CURRENT_BODY" ] || ! grep -qF "$START" <<< "$CURRENT_BODY"; then | ||
| CURRENT_BODY="$(skeleton)" | ||
| fi | ||
|
|
||
| NEW_BODY="$(replace_section "$CURRENT_BODY")" | ||
|
|
||
| if [ -z "$COMMENT_ID" ]; then | ||
| RESULT=$(jq -n --arg b "$NEW_BODY" '{body:$b}' \ | ||
| | gh api -X POST "/repos/$REPO/issues/$PR_NUMBER/comments" --input -) | ||
| COMMENT_ID=$(jq -r '.id' <<< "$RESULT") | ||
| else | ||
| jq -n --arg b "$NEW_BODY" '{body:$b}' \ | ||
| | gh api -X PATCH "/repos/$REPO/issues/comments/$COMMENT_ID" --input - >/dev/null | ||
| fi | ||
|
|
||
| # Re-read and confirm our section landed on the surviving comment, and that no | ||
| # concurrent writer left a duplicate behind. | ||
| sleep 1 | ||
| RECHECK=$(gh api "/repos/$REPO/issues/$PR_NUMBER/comments" --paginate) | ||
| RIDS=() | ||
| while IFS= read -r line; do [ -n "$line" ] && RIDS+=("$line"); done <<< "$(marker_ids "$RECHECK")" | ||
| LIVE_BODY=$(jq -r --arg id "$COMMENT_ID" '.[] | select(.id==($id|tonumber)) | .body' <<< "$RECHECK") | ||
|
|
||
| if [ "${#RIDS[@]}" -le 1 ] && [ "$(extract_section "$LIVE_BODY")" = "$WANT" ]; then | ||
| echo "CI status '$SECTION' section updated (attempt $attempt)." | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "Section '$SECTION' not settled (attempt $attempt); retrying." | ||
| sleep $((attempt * 2)) | ||
| done | ||
|
|
||
| echo "::warning::Could not confirm the '$SECTION' CI status section after 5 attempts." | ||
| exit 0 | ||
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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.