Update Docker Hub auth and add release promotion workflow#879
Update Docker Hub auth and add release promotion workflow#879nevil-mathew merged 5 commits intomasterfrom
Conversation
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
WalkthroughThis PR replaces Docker Hub basic auth in the docker-image workflow with a JSON POST login flow and adds a new "Promote RC to Production Release" GitHub Actions workflow that validates tags, verifies commit reachability, retags RC images to production using docker buildx imagetools, and creates a production git tag. Changes
Sequence Diagram(s)sequenceDiagram
participant GH as GitHub Actions
participant Git as Git Repository
participant DH as Docker Hub API
participant IT as imagetools
GH->>GH: receive RC tag input & validate format
GH->>Git: checkout repo (full history) and verify RC tag commit is in main
GH->>DH: POST /users/login (JSON creds) -> receive token
GH->>DH: check RC image manifest exists (token auth)
GH->>DH: ensure production tag does not exist (token auth)
GH->>IT: imagetools create rc-image:rc-tag -> prod-image:prod-tag
IT->>DH: push/update multi-arch manifest for prod tag
GH->>Git: create and push production git tag
GH->>GH: inspect remote digest, set workflow outputs
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~35 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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 |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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/docker-image.yml:
- Around line 67-72: The curl JSON payload construction is unsafe for secrets
with quotes/backslashes/newlines; update the LOGIN_RESPONSE assignment to build
the JSON with jq (using jq -n --arg username "$DOCKERHUB_USERNAME" --arg
password "$DOCKERHUB_TOKEN" '{username:$username,password:$password}') and pipe
or pass that output to curl (e.g., --data `@-` or --data-binary `@-`) instead of
inline -d, ensuring the GitHub Actions secrets are exported into environment
variables first and the curl invocation that sets LOGIN_RESPONSE uses the
jq-generated JSON.
In @.github/workflows/prod-release.yml:
- Around line 64-68: The curl JSON payload assignment to LOGIN_RESPONSE is
vulnerable to special characters in secrets; change the POST body construction
to build safe JSON with jq (or an equivalent safe encoder) and pipe it into curl
with -d `@-` so that the username and token are passed via jq --arg (or
equivalent) instead of inline string interpolation; update the LOGIN_RESPONSE
assignment and the curl invocation (the variable and command around
LOGIN_RESPONSE and the POST to "https://hub.docker.com/v2/users/login") to use
jq to produce {"username":..., "password":...} and feed that to curl.
- Around line 109-123: The current steps "Pull RC image", "Retag image for
production", and "Push production image" use docker pull/tag/push which only
moves the amd64 manifest; instead use docker buildx imagetools create to copy
the multi-arch manifest from the RC tag to the release tag without pulling
layers. Replace the three-step pull/tag/push sequence with a single imagetools
create invocation that references the same image identifiers (use ${{
env.DOCKER_REGISTRY }}/${{ env.DOCKER_NAMESPACE }}/${{ env.DOCKER_IMAGE_NAME
}}:${{ steps.version.outputs.rc }} as the source and ...:${{
steps.version.outputs.release }} as the target), ensuring the multi-arch
manifest is preserved. Ensure the runner has buildx available or set up a step
to enable docker buildx before running imagetools create.
- Around line 138-146: The current Job summary uses docker inspect to set DIGEST
which will fail if images are created with buildx imagetools (image not local);
update the DIGEST extraction to query the remote image via imagetools instead —
replace the docker inspect block that sets DIGEST with a command using docker
buildx imagetools inspect (targeting ${{ env.DOCKER_REGISTRY }}/${{
env.DOCKER_NAMESPACE }}/${{ env.DOCKER_IMAGE_NAME }}:${{
steps.version.outputs.release }}) and parse its output to capture the image
digest, then keep the rest of the summary writes intact (references: the DIGEST
variable assignment and the Job summary block that echoes DIGEST).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e8903936-ad4e-483d-b33c-920dd4977fe8
📒 Files selected for processing (2)
.github/workflows/docker-image.yml.github/workflows/prod-release.yml
| LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" \ | ||
| -u "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" \ | ||
| -X POST \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{"username": "${{ secrets.DOCKERHUB_USERNAME }}", "password": "${{ secrets.DOCKERHUB_TOKEN }}"}' \ | ||
| "https://hub.docker.com/v2/users/login") |
There was a problem hiding this comment.
JSON payload is vulnerable to breakage if secrets contain special characters.
If DOCKERHUB_USERNAME or DOCKERHUB_TOKEN contains characters like ", \, or newlines, the JSON will be malformed, causing authentication failures. Consider using jq to safely construct the payload.
🛡️ Proposed fix using jq for safe JSON construction
- LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" \
- -X POST \
- -H "Content-Type: application/json" \
- -d '{"username": "${{ secrets.DOCKERHUB_USERNAME }}", "password": "${{ secrets.DOCKERHUB_TOKEN }}"}' \
- "https://hub.docker.com/v2/users/login")
+ LOGIN_PAYLOAD=$(jq -n \
+ --arg user "${{ secrets.DOCKERHUB_USERNAME }}" \
+ --arg pass "${{ secrets.DOCKERHUB_TOKEN }}" \
+ '{username: $user, password: $pass}')
+ LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" \
+ -X POST \
+ -H "Content-Type: application/json" \
+ -d "$LOGIN_PAYLOAD" \
+ "https://hub.docker.com/v2/users/login")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" \ | |
| -u "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" \ | |
| -X POST \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"username": "${{ secrets.DOCKERHUB_USERNAME }}", "password": "${{ secrets.DOCKERHUB_TOKEN }}"}' \ | |
| "https://hub.docker.com/v2/users/login") | |
| LOGIN_PAYLOAD=$(jq -n \ | |
| --arg user "${{ secrets.DOCKERHUB_USERNAME }}" \ | |
| --arg pass "${{ secrets.DOCKERHUB_TOKEN }}" \ | |
| '{username: $user, password: $pass}') | |
| LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" \ | |
| -X POST \ | |
| -H "Content-Type: application/json" \ | |
| -d "$LOGIN_PAYLOAD" \ | |
| "https://hub.docker.com/v2/users/login") |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/docker-image.yml around lines 67 - 72, The curl JSON
payload construction is unsafe for secrets with quotes/backslashes/newlines;
update the LOGIN_RESPONSE assignment to build the JSON with jq (using jq -n
--arg username "$DOCKERHUB_USERNAME" --arg password "$DOCKERHUB_TOKEN"
'{username:$username,password:$password}') and pipe or pass that output to curl
(e.g., --data `@-` or --data-binary `@-`) instead of inline -d, ensuring the GitHub
Actions secrets are exported into environment variables first and the curl
invocation that sets LOGIN_RESPONSE uses the jq-generated JSON.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.github/workflows/prod-release.yml (1)
40-52: Consider explicit error handling for missing RC tag.If the RC tag doesn't exist in the repository,
git rev-list -n 1 "$RC_TAG"on line 44 will fail with a generic git error rather than a clear message. Consider adding explicit existence check:💡 Optional: Clearer error for missing tag
- name: Verify RC commit exists in main run: | RC_TAG="${{ steps.version.outputs.rc }}" git fetch origin main --tags + if ! git rev-parse "$RC_TAG" >/dev/null 2>&1; then + echo "Error: RC tag $RC_TAG does not exist in the repository" + exit 1 + fi RC_COMMIT=$(git rev-list -n 1 "$RC_TAG")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/prod-release.yml around lines 40 - 52, The script uses git rev-list -n 1 "$RC_TAG" without verifying the tag exists, so add an explicit existence check for RC_TAG before calling git rev-list (e.g., test `git rev-parse --verify "refs/tags/$RC_TAG"` or `git show-ref --tags --quiet --verify "refs/tags/$RC_TAG"`), and if the tag is missing emit a clear error like "Error: RC tag '$RC_TAG' does not exist" and exit 1; maintain the subsequent RC_COMMIT and merge-base check only when the tag existence check passes (refer to RC_TAG and RC_COMMIT in the existing block).
🤖 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/prod-release.yml:
- Around line 23-34: The Validate RC tag step currently interpolates `${{
github.event.inputs.rc_tag }}` directly into the run script (creating a
command-injection vector); instead pass the input into the step's env (e.g.,
RC_TAG: ${{ github.event.inputs.rc_tag }}) and then reference the safe shell
variable $RC_TAG inside the run block when doing the regex check, RELEASE_TAG
extraction, and writes to $GITHUB_OUTPUT; ensure the variable is always quoted
(e.g., "$RC_TAG") when tested and used.
---
Nitpick comments:
In @.github/workflows/prod-release.yml:
- Around line 40-52: The script uses git rev-list -n 1 "$RC_TAG" without
verifying the tag exists, so add an explicit existence check for RC_TAG before
calling git rev-list (e.g., test `git rev-parse --verify "refs/tags/$RC_TAG"` or
`git show-ref --tags --quiet --verify "refs/tags/$RC_TAG"`), and if the tag is
missing emit a clear error like "Error: RC tag '$RC_TAG' does not exist" and
exit 1; maintain the subsequent RC_COMMIT and merge-base check only when the tag
existence check passes (refer to RC_TAG and RC_COMMIT in the existing block).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6dea12db-7680-4563-a509-138af273112e
📒 Files selected for processing (1)
.github/workflows/prod-release.yml
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/prod-release.yml:
- Around line 15-20: Add a top-level concurrency stanza to the GitHub Actions
workflow to serialize runs of the promote job: under the workflow root (above
jobs) add a concurrency block (e.g., group: "promote" and cancel-in-progress:
false) so that the promote job cannot run concurrently and promotions are
queued, preventing the race when creating Docker/Git tags; ensure the group name
is stable (e.g., "promote" or include repo/workflow identifiers) and reference
the existing promote job in your mental mapping.
- Around line 41-52: The RC commit validated in the "Verify RC commit exists in
main" step (RC_COMMIT) is not persisted and the later git tag uses the workflow
checkout HEAD; change the step to set RC_COMMIT as a step output (e.g.,
outputs.rc_commit) after computing RC_COMMIT and then in the tagging step use
that output (steps.<verify-step-id>.outputs.rc_commit) when running git tag -a
or git tag <RC_TAG> <RC_COMMIT> so the production tag explicitly points to the
validated commit rather than the current checkout head.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b0acde60-30b2-46f7-8415-d02529c90881
📒 Files selected for processing (1)
.github/workflows/prod-release.yml
Summary by CodeRabbit
Release Notes