DAT-22270: Fix Release Drafter permissions and add release publish step#502
DAT-22270: Fix Release Drafter permissions and add release publish step#502
Conversation
Fix two bugs preventing proper release notes and publishing: 1. Grant `contents: write` permission to Release Drafter workflow so it can create/update draft releases (was `read`, causing silent failures) 2. Add `publish-release` job to create-release.yml that publishes the GitHub release after all Docker images are built and pushed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR fixes two bugs in GitHub Actions release automation: updating Release Drafter workflow permissions from Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Claude finished @jnewton03's task in 1m 17s —— View job Review in progress
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.github/workflows/release-drafter.yml (1)
9-11:contents: writeis correct for draft release creation but is overly broad for thelabel-prsjob.The permission change unblocks Release Drafter's ability to create/update draft releases — that's the right fix.
Minor least-privilege note:
contents: writeis declared at the workflow level and therefore also applies to thelabel-prsjob, which only needspull-requests: write. For fork PRs, GitHub silently restricts theGITHUB_TOKENto read-only regardless, so the practical risk is low. If you want to tighten it, movepermissionsto the job level:♻️ Optional: job-level permissions for least privilege
-permissions: - contents: write - pull-requests: write +permissions: {} jobs: label-prs: if: github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + pull-requests: write steps: ... draft-community: if: github.event_name == 'push' runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: ... draft-secure: if: github.event_name == 'push' runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: ...🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-drafter.yml around lines 9 - 11, The workflow-level permissions currently set "contents: write" apply to every job (including the "label-prs" job) which is broader than needed; update the YAML so that "contents: write" remains only on the Release Drafter job and move a least-privilege "permissions: pull-requests: write" into the "label-prs" job definition instead of leaving "contents: write" at the top level — keep using the "permissions" key but assign "contents: write" to the release-drafter job and "pull-requests: write" to the "label-prs" job so each job has only the permissions it requires.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/create-release.yml:
- Around line 556-562: The gh release edit step can fail if the draft release or
tag doesn't exist; update the Publish Release step to first check for the
release/tag and handle missing cases gracefully: use gh release view or gh
release list to verify that "${{ steps.release-tag.outputs.tag_name }}" exists
(or that the draft created by setup-update-draft-build exists) and only run gh
release edit when present, otherwise either create the release (gh release
create) or skip with a clear log message; also add the --latest=true flag to the
gh release edit invocation to explicitly set the release as latest.
- Around line 541-562: The publish-release job can run when no Dockerfile
changes occurred; add a job-level output named changes_made on the
update-dockerfiles job (propagate the existing flag that indicates whether files
were changed) so downstream jobs can inspect it, then add a guard to the
publish-release job (the job named "publish-release") changing its if to require
needs.update-dockerfiles.outputs.changes_made == 'true' in addition to the
existing dryRun check; also add the same changes_made guard to the "Create
GitHub Release" step in the setup-update-draft-build flow (the step that uses
softprops/action-gh-release) so it won't create an orphan lightweight tag when
no changes were made.
---
Nitpick comments:
In @.github/workflows/release-drafter.yml:
- Around line 9-11: The workflow-level permissions currently set "contents:
write" apply to every job (including the "label-prs" job) which is broader than
needed; update the YAML so that "contents: write" remains only on the Release
Drafter job and move a least-privilege "permissions: pull-requests: write" into
the "label-prs" job definition instead of leaving "contents: write" at the top
level — keep using the "permissions" key but assign "contents: write" to the
release-drafter job and "pull-requests: write" to the "label-prs" job so each
job has only the permissions it requires.
.github/workflows/create-release.yml
Outdated
| publish-release: | ||
| name: "Publish GitHub Release" | ||
| needs: [update-dockerfiles, setup-update-draft-build] | ||
| if: ${{ needs.update-dockerfiles.outputs.dryRun == 'false' }} | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Determine Release Tag | ||
| id: release-tag | ||
| run: | | ||
| if [[ "${{ needs.update-dockerfiles.outputs.releaseType }}" == "liquibase-secure-release" ]]; then | ||
| echo "tag_name=v${{ needs.update-dockerfiles.outputs.extensionVersion }}-SECURE" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "tag_name=v${{ needs.update-dockerfiles.outputs.extensionVersion }}" >> $GITHUB_OUTPUT | ||
| fi | ||
|
|
||
| - name: Publish Release | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| gh release edit "${{ steps.release-tag.outputs.tag_name }}" \ | ||
| --repo "${{ github.repository }}" \ | ||
| --draft=false |
There was a problem hiding this comment.
publish-release can publish an unintended release when no Dockerfile changes occurred.
The if condition only checks dryRun == 'false', with no guard on changes_made. When changes_made == 'false' (no Dockerfile bump needed):
Create and Push Tagis skipped (no annotated tag pushed), butCreate GitHub Releaseinsetup-update-draft-buildstill runs unconditionally (it has nochanges_madeguard either), andsoftprops/action-gh-releasewill auto-create a lightweight tag pointing to HEAD if none exists.publish-releasethen publishes that unintended draft.
What was previously a harmless "orphan draft" becomes a published release after this PR. This can happen on workflow re-runs or when the target version is already current.
The root fix requires two changes:
- Expose
changes_madeas a job-level output fromupdate-dockerfiles:
🛠️ Add `changes_made` to `update-dockerfiles` job outputs (lines 55-64)
outputs:
releaseType: ${{ steps.collect-data.outputs.releaseType }}
liquibaseVersion: ${{ steps.collect-data.outputs.liquibaseVersion }}
extensionVersion: ${{ steps.collect-data.outputs.extensionVersion }}
dryRun: ${{ steps.collect-data.outputs.dryRun }}
minorVersion: ${{ steps.collect-data.outputs.minorVersion }}
latestCommitSha: ${{ steps.get-latest-sha.outputs.latestCommitSha }}
pushDockerHub: ${{ steps.collect-data.outputs.pushDockerHub }}
pushGHCR: ${{ steps.collect-data.outputs.pushGHCR }}
pushECR: ${{ steps.collect-data.outputs.pushECR }}
+ changes_made: ${{ steps.update-dockerfiles.outputs.changes_made }}- Guard
publish-releasewith that output:
🛠️ Add `changes_made` guard to `publish-release` (line 544)
- if: ${{ needs.update-dockerfiles.outputs.dryRun == 'false' }}
+ if: ${{ needs.update-dockerfiles.outputs.dryRun == 'false' && needs.update-dockerfiles.outputs.changes_made == 'true' }}Ideally the same guard should also be added to the Create GitHub Release step in setup-update-draft-build (line 341) to prevent creating orphan drafts on no-change runs, but that's a pre-existing gap and can be addressed separately.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/create-release.yml around lines 541 - 562, The
publish-release job can run when no Dockerfile changes occurred; add a job-level
output named changes_made on the update-dockerfiles job (propagate the existing
flag that indicates whether files were changed) so downstream jobs can inspect
it, then add a guard to the publish-release job (the job named
"publish-release") changing its if to require
needs.update-dockerfiles.outputs.changes_made == 'true' in addition to the
existing dryRun check; also add the same changes_made guard to the "Create
GitHub Release" step in the setup-update-draft-build flow (the step that uses
softprops/action-gh-release) so it won't create an orphan lightweight tag when
no changes were made.
.github/workflows/create-release.yml
Outdated
| - name: Publish Release | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| gh release edit "${{ steps.release-tag.outputs.tag_name }}" \ | ||
| --repo "${{ github.repository }}" \ | ||
| --draft=false |
There was a problem hiding this comment.
gh release edit will fail hard if the release or tag doesn't exist — consider adding a check.
If the draft release was never created (e.g., due to a partial failure in setup-update-draft-build), gh release edit exits non-zero and fails the job with no actionable diagnostic. A pre-flight existence check or graceful fallback would improve resilience:
🛠️ Proposed defensive handling
- name: Publish Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- gh release edit "${{ steps.release-tag.outputs.tag_name }}" \
- --repo "${{ github.repository }}" \
- --draft=false
+ TAG="${{ steps.release-tag.outputs.tag_name }}"
+ if ! gh release view "${TAG}" --repo "${{ github.repository }}" &>/dev/null; then
+ echo "::warning::Release '${TAG}' not found — skipping publish."
+ exit 0
+ fi
+ gh release edit "${TAG}" \
+ --repo "${{ github.repository }}" \
+ --draft=false \
+ --latest=trueThe --latest=true also makes the "latest release" designation explicit rather than relying on GitHub's auto-detection, which is preferable for a release pipeline.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/create-release.yml around lines 556 - 562, The gh release
edit step can fail if the draft release or tag doesn't exist; update the Publish
Release step to first check for the release/tag and handle missing cases
gracefully: use gh release view or gh release list to verify that "${{
steps.release-tag.outputs.tag_name }}" exists (or that the draft created by
setup-update-draft-build exists) and only run gh release edit when present,
otherwise either create the release (gh release create) or skip with a clear log
message; also add the --latest=true flag to the gh release edit invocation to
explicitly set the release as latest.
1. Expose changes_made as a job output from update-dockerfiles and add it as a condition on publish-release to prevent publishing unintended releases when no Dockerfile changes occurred (e.g., workflow re-runs) 2. Add pre-flight existence check before gh release edit so partial failures in setup-update-draft-build produce a warning instead of a hard failure 3. Add --latest=true flag for explicit latest release designation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Claude finished @jnewton03's task in 1m 10s —— View job Review complete
LGTM. The follow-up commit (
One unaddressed nitpick: workflow-level |

Summary
contents: readtocontents: writein.github/workflows/release-drafter.ymlso Release Drafter can create/update draft releases (was silently failing withResource not accessible by integration)publish-releasejob in.github/workflows/create-release.ymlthat publishes the draft GitHub release after all Docker images are built and pushed to all registriesv5.1.0-SECURErelease has been manually updated with full release notes and publishedTest plan
mainand confirm the Release Drafter workflow succeeds without "Resource not accessible" errorsifcondition excludesdryRun == 'true')Jira
DAT-22270
🤖 Generated with Claude Code