Conversation
|
| - name: Create or reuse draft release | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| TAG_NAME: ${{ inputs.tag_name }} | ||
| run: | | ||
| if git ls-remote --exit-code --tags origin "$TAG_NAME" > /dev/null 2>&1; then | ||
| echo "Tag '$TAG_NAME' already exists on origin. To retry, clean up the partial release first:" | ||
| echo " 1. Delete the tag: git push origin :refs/tags/$TAG_NAME" | ||
| echo " 2. If a draft GitHub release exists for '$TAG_NAME', delete it before re-dispatching." | ||
| exit 1 | ||
| set -euo pipefail | ||
| if release_details="$(gh release view "$TAG_NAME" --json id,isDraft 2>/dev/null)"; then | ||
| release_is_draft=$(jq -r '.isDraft' <<< "$release_details") | ||
| if [[ "$release_is_draft" == "true" ]]; then | ||
| echo "Reusing existing draft release $TAG_NAME" | ||
| else | ||
| echo "::error::Release $TAG_NAME already exists and is NOT a draft. Aborting to avoid mutating an immutable release." | ||
| exit 1 | ||
| fi | ||
| else |
There was a problem hiding this comment.
⚠️ Bug: Draft reuse/create never validates the release target commit
The step only reads isDraft, so two cases silently publish a release at the wrong commit. (a) A git tag already exists without a release (exactly the state the old pre-flight check guarded against — e.g. an old attempt that pushed the tag, or a manually pushed tag): gh release create --draft --target "$GITHUB_SHA" succeeds, but GitHub ignores target_commitish when the tag ref already exists, so the final gh release edit --draft=false publishes against the pre-existing tag/commit instead of $GITHUB_SHA. (b) On the reuse path a draft left over from an earlier dispatch keeps its original targetCommitish, so re-dispatching after new commits publishes the old commit while the log just says "Reusing existing draft release". Query targetCommitish and compare it with $GITHUB_SHA, and fail fast if a tag ref for $TAG_NAME already exists on origin.
Fail fast on a pre-existing tag ref and on a draft whose target does not match the dispatched SHA:
set -euo pipefail
if git ls-remote --exit-code --tags origin "$TAG_NAME" > /dev/null 2>&1; then
echo "::error::Tag $TAG_NAME already exists on origin; publishing would release that ref, not $GITHUB_SHA. Delete it first: git push origin :refs/tags/$TAG_NAME"
exit 1
fi
if release_details="$(gh release view "$TAG_NAME" --json isDraft,targetCommitish 2>/dev/null)"; then
if [[ "$(jq -r '.isDraft' <<< "$release_details")" != "true" ]]; then
echo "::error::Release $TAG_NAME already exists and is NOT a draft. Aborting to avoid mutating an immutable release."
exit 1
fi
draft_target=$(jq -r '.targetCommitish' <<< "$release_details")
if [[ "$draft_target" != "$GITHUB_SHA" ]]; then
echo "::error::Existing draft $TAG_NAME targets $draft_target but this run is $GITHUB_SHA. Delete the draft or re-dispatch from $draft_target."
exit 1
fi
echo "Reusing existing draft release $TAG_NAME"
else
gh release create "$TAG_NAME" --draft --title "Release $TAG_NAME" --target "$GITHUB_SHA"
fi
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| if release_details="$(gh release view "$TAG_NAME" --json id,isDraft 2>/dev/null)"; then | ||
| release_is_draft=$(jq -r '.isDraft' <<< "$release_details") | ||
| if [[ "$release_is_draft" == "true" ]]; then | ||
| echo "Reusing existing draft release $TAG_NAME" | ||
| else | ||
| echo "::error::Release $TAG_NAME already exists and is NOT a draft. Aborting to avoid mutating an immutable release." | ||
| exit 1 | ||
| fi | ||
| else | ||
| gh release create "$TAG_NAME" \ | ||
| --draft \ | ||
| --title "Release $TAG_NAME" \ | ||
| --target "$GITHUB_SHA" | ||
| echo "Created draft release $TAG_NAME" |
There was a problem hiding this comment.
💡 Bug: Non-404 gh release view failures create a duplicate draft
2>/dev/null plus a bare exit-status test treats every gh release view failure — network blip, 5xx, rate limit, auth/repo-resolution error — as "release does not exist", so the script falls through to gh release create --draft. Because draft releases have no tag ref, GitHub happily accepts a second draft with the same tag name, and the later gh release upload (gh-action_sbom) and gh release edit --draft=false each resolve the tag to whichever draft the API returns first, so the SBOM can be attached to one draft while a different, empty one gets published. Capture stderr and only take the create path when gh reports the release as not found, otherwise re-raise the error.
Only treat an explicit "release not found" as absent:
set -euo pipefail
view_err=$(mktemp)
if release_details="$(gh release view "$TAG_NAME" --json id,isDraft,targetCommitish 2>"$view_err")"; then
: # handled below
elif grep -qi 'release not found' "$view_err"; then
release_details=""
else
echo "::error::Failed to query release $TAG_NAME:"; cat "$view_err"; exit 1
fi
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| - name: Create or reuse draft release | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| TAG_NAME: ${{ inputs.tag_name }} | ||
| run: | | ||
| if git ls-remote --exit-code --tags origin "$TAG_NAME" > /dev/null 2>&1; then | ||
| echo "Tag '$TAG_NAME' already exists on origin. To retry, clean up the partial release first:" | ||
| echo " 1. Delete the tag: git push origin :refs/tags/$TAG_NAME" | ||
| echo " 2. If a draft GitHub release exists for '$TAG_NAME', delete it before re-dispatching." | ||
| exit 1 | ||
| set -euo pipefail | ||
| if release_details="$(gh release view "$TAG_NAME" --json id,isDraft 2>/dev/null)"; then | ||
| release_is_draft=$(jq -r '.isDraft' <<< "$release_details") | ||
| if [[ "$release_is_draft" == "true" ]]; then | ||
| echo "Reusing existing draft release $TAG_NAME" | ||
| else | ||
| echo "::error::Release $TAG_NAME already exists and is NOT a draft. Aborting to avoid mutating an immutable release." | ||
| exit 1 | ||
| fi | ||
| else |
There was a problem hiding this comment.
💡 Quality: DEVELOPER.md release/recovery procedure is now wrong
The release runbook still describes the removed behaviour: it says the workflow "creates and pushes the git tag at HEAD of the dispatched branch" (the tag is now only created when the draft is published in the last step) and tells operators that "re-dispatching with the same tag will fail at the pre-flight check" and that they must delete the remote tag and the draft release to recover. With the draft-first flow a retry is expected to reuse the draft, and there is no tag to delete, so an operator following this section during a failed release takes unnecessary destructive steps. Update the Releasing / Recovering sections to describe draft-first tag creation and retry-by-reuse.
Rewrite the two stale passages in DEVELOPER.md:
The workflow validates the tag format, creates (or reuses) a draft GitHub release targeting the dispatched commit, generates the SBOM, promotes the staged Docker image, pushes it to Docker Hub, and finally publishes the GitHub release — which is what creates the git tag.
### Recovering from a failed release
If the workflow fails before the release is published, simply re-dispatch with the same tag: the existing draft release is reused and no tag exists yet. If the release was already published, the tag and release are immutable — release a new tag instead.
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
Code Review
|
| Auto-apply | Compact | Unblock |
|
|
|
Was this helpful? React with 👍 / 👎 | Gitar
|
@sonarsource/code-orchestration-ci-experience-squad @antoine-vinot-sonarsource could you review this? It unblocks the scanner CLI Docker release (PREQ-8689 / tag |
| - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 | ||
| - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 | ||
| with: | ||
| repository: SonarSource/sonar-scanning-examples | ||
| path: target_repository |
There was a problem hiding this comment.
This was not changed in this PR; but its very suspicious. The checkout action appear twice and the repository is set to 'sonar-scanning-examples' ?
antoine-vinot-sonarsource
left a comment
There was a problem hiding this comment.
@tomverin I'm good to give this a try. What about Gitar comments? Do they make sense?





Summary
sonar-scanner-cli-dockerfails at Create and push release tag withGH013: Cannot create ref due to creations being restricted(git tag+git pushof12.2.0.3249_8.1.0). The tag was never created.gh release create --draft --target "$GITHUB_SHA"(same pattern as gh-action_release v7). Existing drafts are reused so a later step failure can be retried; a published immutable release is rejected.gh-action_sbom@v3still attaches the SBOM to the draft;gh release edit --draft=falsestill publishes.Jira: PREQ-8689
Test plan
12.2.0.3249_8.1.0(none after the failed run).tag_name=12.2.0.3249_8.1.0.$GITHUB_SHA.