Skip to content

feat(ci): publish per-PR test image to dotcms/dotcms-test on "PR: docker image" label#36332

Open
wezell wants to merge 11 commits into
mainfrom
feat/pr-docker-test-image
Open

feat(ci): publish per-PR test image to dotcms/dotcms-test on "PR: docker image" label#36332
wezell wants to merge 11 commits into
mainfrom
feat/pr-docker-test-image

Conversation

@wezell

@wezell wezell commented Jun 26, 2026

Copy link
Copy Markdown
Member

Closes #36331

What

Publishes a per-PR Docker test image to dotcms/dotcms-test for PRs labeled PR: docker image, as soon as the build artifact exists (in parallel with the test suite — not after it).

Tag = pr-<number>-<normalized-branch>, e.g. feat/bedrock-agentic-harness on PR #1234
dotcms/dotcms-test:pr-1234-feat-bedrock-agentic-harness (mutable) + ..._<sha7> (immutable).
A sticky PR comment lists the latest docker pull commands.

How

The image is not rebuilt here. The normal PR build (core-cicd/maven-job) already builds dotcms/dotcms-test:<version> once and uploads it as the docker-image artifact. This change promotes that exact artifact to Docker Hub, retagged for the PR — so what ships is what CI built and tested.

  • cicd_comp_publish-pr-test-image.yml (new, reusable) — loads the docker-image artifact, retags, pushes to dotcms/dotcms-test, upserts a sticky comment. Discovers the artifact by SHA when no run id is supplied.
  • cicd_1-pr.ymlpublish-test-image job (needs: build, label + internal-branch gated) calls the reusable workflow right after build with artifact_run_id: github.run_id, so publishing runs in parallel with tests.
  • cicd_publish-pr-test-image.yml — thin pull_request_target: [labeled] entry for the label-applied-to-an-existing-PR case; reuses the newest docker-image artifact for the head SHA.

Uses the existing DOCKER_USERNAME / DOCKER_TOKEN repo secrets — no new secret to provision.

Security note

DOCKER_TOKEN can push to dotcms/dotcms (production). The build-path job runs in cicd_1-pr.yml, which is PR-modifiable, so for internal branches the token is reachable by that workflow — the same risk class as the CI_MACHINE_TOKEN (pr-notifier) and SEMGREP_APP_TOKEN already used there. Fork PRs get no secrets. The label-applied path uses pull_request_target (runs from main), so the token stays out of PR-modifiable code on that path. Worth a maintainer review of this boundary.

Notes / limitations

  • Internal branches only — fork PRs get no secrets.
  • The label path reuses an existing artifact; it does not build. Labeling a PR with no prior docker-image artifact (e.g. a docs-only PR) publishes nothing until a build-producing commit lands.
  • amd64-only (the prebuilt artifact is amd64).

Files

  • .github/workflows/cicd_comp_publish-pr-test-image.yml — reusable publisher (new).
  • .github/workflows/cicd_1-pr.ymlpublish-test-image job (new).
  • .github/workflows/cicd_publish-pr-test-image.ymlpull_request_target label entry.

🤖 Generated with Claude Code


⚠️ Verified live on this PR — one prerequisite remains

The label path ran end-to-end on PR #36332: it reused the build artifact, loaded dotcms/dotcms-test:1.0.0-SNAPSHOT, and authenticated to Docker Hub (Login Succeeded). The push was denied:

The push refers to repository [docker.io/dotcms/dotcms-test]
denied: requested access to the resource is denied

dotcms/dotcms-test exists on Docker Hub, but the CI machine account (DOCKER_USERNAME) lacks write access to it (it can push dotcms/dotcms and -dev, but -test was only ever a local build tag).

Action (maintainer, one-time): grant the CI Docker account push/write access to dotcms/dotcms-test (add as collaborator with Write, or via a team). No workflow change needed — re-running publishes after that.

…36331)

Adds cicd_manual_build-pr-docker-image.yml: when a PR carries the
"PR: docker image" label, builds and pushes to dotcms/dotcms-test tagged
pr-<number>-<normalized-branch> (plus immutable _<sha>). Fires on label
apply and on pushes to an already-labeled PR. Reuses the modern build
phase + deploy-docker composite action.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wezell wezell requested a review from a team as a code owner June 26, 2026 16:44
@github-actions github-actions Bot added the Area : CI/CD PR changes GitHub Actions/workflows label Jun 26, 2026
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes .sdkmanrc exists and contains java= line; if missing or malformed, workflow fails with exit 1 and no recovery or fallback. No fallback Java version is specified, and no logging of the error beyond "No .sdkmanrc file found". This is a brittle dependency on a file that may not be present in all build contexts.
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes awk parsing of .sdkmanrc is safe; if the file contains multiple java= lines or non-standard formatting, behavior is undefined. No validation or error handling for malformed input.

Existing

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Prior finding still present: No fallback Java version is defined if .sdkmanrc is missing or invalid. This is a systemic gap in the workflow’s design, not introduced by this PR, but remains unaddressed.

Resolved

  • path/file:line — no resolved items

Run: #28252068151 · tokens: in: 2299 · out: 417 · total: 2716

@claude

claude Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Claude finished @wezell's task in 42s —— View job


Rollback Safety Analysis

  • Read rollback-unsafe categories reference
  • Get full PR diff
  • Analyze diff against unsafe categories
  • Apply appropriate label

Result: Safe to Rollback ✅

All changes are confined to GitHub Actions workflow files:

  • .github/workflows/cicd_1-pr.yml — adds a publish-test-image job
  • .github/workflows/cicd_comp_publish-pr-test-image.yml — new reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml — new pull_request_target entry

No changes to database schema, Elasticsearch mappings, content models, REST/GraphQL APIs, OSGi interfaces, VTL viewtools, or push publishing bundles. None of the rollback-unsafe categories (C-1 through M-4) apply.

Rolling back to the previous release simply means these CI workflows don't exist — no per-PR Docker image is published, but the application and its data are entirely unaffected.

Label applied: AI: Safe To Rollback

@wezell wezell added the PR: docker image Build & push a per-PR test image to dotcms/dotcms-test label Jun 26, 2026
After the image is pushed, upsert a single sticky comment (keyed on a
hidden marker) listing docker pull commands for the latest tags, so each
new push updates in place.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes .sdkmanrc exists and contains java= line; no fallback or error recovery if missing or malformed
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — awk parsing of .sdkmanrc is brittle and unvalidated; may break on malformed or multi-line java= entries
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — No fallback Java version defined if .sdkmanrc is missing or invalid

Existing

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes .sdkmanrc exists and contains java= line; no fallback or error recovery if missing or malformed
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — awk parsing of .sdkmanrc is brittle and unvalidated; may break on malformed or multi-line java= entries
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — No fallback Java version defined if .sdkmanrc is missing or invalid

Resolved

  • .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Prior findings still present; no change to address them

Run: #28252737890 · tokens: in: 2997 · out: 473 · total: 3470

)

Adds a discover job that looks for a docker-build-context artifact already
produced for the head SHA by another run (e.g. the PR's normal CI). When
found, the build job is skipped and deploy-docker pulls that run's artifact
via build_run_id, avoiding a redundant Maven compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes .sdkmanrc exists and contains java= line; no fallback or error recovery if missing or malformed
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — awk parsing of .sdkmanrc is brittle and unvalidated; may break on malformed or multi-line java= entries
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — No fallback Java version defined if .sdkmanrc is missing or invalid

Existing

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes .sdkmanrc exists and contains java= line; no fallback or error recovery if missing or malformed
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — awk parsing of .sdkmanrc is brittle and unvalidated; may break on malformed or multi-line java= entries
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — No fallback Java version defined if .sdkmanrc is missing or invalid

Resolved

  • .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Prior findings still apply; no changes made to address them

Run: #28252815836 · tokens: in: 3530 · out: 474 · total: 4004

The PR pipeline already builds dotcms/dotcms-test once and uploads it as
the docker-image artifact, but PR checks cannot use registry secrets. Move
publishing to a workflow_run-triggered job that runs from main (trusted)
and promotes that artifact to Docker Hub — load + retag + push, no second
build. A pull_request:labeled trigger covers applying the label to an
existing PR by reusing the latest docker-image artifact for the SHA
(building only if none exists). Drops the synchronize self-build that
duplicated the PR pipeline's image build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:185docker load -i /tmp/prebuilt/image.tar assumes the artifact contains exactly one image tarball; no validation that /tmp/prebuilt/image.tar exists or is a valid tar file — failure results in silent loaded="" and later docker tag fails with cryptic error
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:195docker login uses DOCKER_TOKEN as password without checking if it's empty or malformed — may log credentials if DOCKER_USERNAME is set but token is missing
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:210gh api calls use --jq to extract comment ID; if API returns non-JSON or empty array, id becomes empty string and comment creation fails silently without error logging
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:217echo "tags=$(echo ${pushed} | xargs)" >> "$GITHUB_OUTPUT" uses unquoted ${pushed} — word splitting on spaces in tag names (e.g., pr-1234-foo bar) will corrupt output

Existing

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — Assumes .sdkmanrc exists and contains java= line; no fallback or error recovery if missing or malformed
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — awk parsing of .sdkmanrc is brittle and unvalidated; may break on malformed or multi-line java= entries
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — No fallback Java version defined if .sdkmanrc is missing or invalid

Resolved

  • .github/workflows/cicd_manual_build-pr-docker-image.yml:85 — This file is new; prior findings about .sdkmanrc are irrelevant and no longer applicable to this PR

Run: #28254082866 · tokens: in: 4134 · out: 685 · total: 4819

Publish the per-PR test image as soon as the build artifact exists, in
parallel with tests, without putting DOCKER_* secrets in the PR pipeline:

- cicd_1-pr.yml: add a label-gated, internal-branch-only job that fires a
  repository_dispatch (pr-docker-image) right after build succeeds, using a
  minimal PR_DOCKER_DISPATCH_TOKEN (no registry creds).
- cicd_publish-pr-test-image.yml (renamed): trusted publisher running from
  main via repository_dispatch + pull_request_target(labeled). Downloads the
  docker-image artifact from the dispatched run, retags pr-N-branch (+_sha),
  pushes to dotcms/dotcms-test, and upserts a sticky comment. Re-validates
  the label and head SHA as defense in depth.

Requires a new repo secret PR_DOCKER_DISPATCH_TOKEN (fine-grained PAT/App,
contents:write only) to trigger the publisher.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_1-pr.yml:83gh api "repos/${REPO}/dispatches" uses unquoted ${REPO} — risk of shell injection if repo name contains spaces or shell metacharacters
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:148echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:185id=$(gh api ... --jq "...") fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:205for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation

Existing

  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:185 — docker load assumes artifact contains exactly one valid image tarball with no existence or validity check
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:195 — docker login uses DOCKER_TOKEN without validation — may log credentials if token is missing
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:210 — gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array
  • 🟡 Medium: .github/workflows/cicd_manual_build-pr-docker-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names

Resolved

  • .github/workflows/cicd_manual_build-pr-docker-image.yml:185 — replaced by new cicd_publish-pr-test-image.yml logic, which has same issue but is tracked above
  • .github/workflows/cicd_manual_build-pr-docker-image.yml:195 — replaced by new cicd_publish-pr-test-image.yml logic, which has same issue but is tracked above
  • .github/workflows/cicd_manual_build-pr-docker-image.yml:210 — replaced by new cicd_publish-pr-test-image.yml logic, which has same issue but is tracked above
  • .github/workflows/cicd_manual_build-pr-docker-image.yml:217 — replaced by new cicd_publish-pr-test-image.yml logic, which has same issue but is tracked above

Run: #28255022479 · tokens: in: 4400 · out: 1173 · total: 5573

@wezell wezell changed the title feat(ci): build per-PR Docker test image on "PR: docker image" label feat(ci): publish per-PR test image to dotcms/dotcms-test on "PR: docker image" label Jun 26, 2026
Without PR_DOCKER_DISPATCH_TOKEN the dispatch ran unauthenticated and
failed, showing a red check on every labeled PR. Guard on the token and
exit 0 when it's absent so the job is green until maintainers provision it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_1-pr.yml:83gh api "repos/${REPO}/dispatches" uses unquoted ${REPO} — risk of shell injection if repo name contains spaces or shell metacharacters (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:148echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:185id=$(gh api ... --jq "...") fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:195for t in "${TAG}" is quoted correctly, but echo ${pushed} | xargs in TAGS output and for t in ${TAGS} in comment generation (line 205) — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:205for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:185gh api to extract comment ID fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:210gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST (same as prior finding, still present)
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:217for t in ${TAGS} in comment body generation — unquoted variable causes word splitting on spaces in tag names (same as prior finding, still present)

Existing

  • 🟡 Medium: .github/workflows/cicd_1-pr.yml:83 — gh api "repos/${REPO}/dispatches" uses unquoted ${REPO} — risk of shell injection if repo name contains spaces or shell metacharacters
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:148 — echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:185 — id=$(gh api ... --jq "...") fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:205 — for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:210 — gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array
  • 🟡 Medium: .github/workflows/cicd_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names

Resolved

  • .github/workflows/cicd_publish-pr-test-image.yml:195for t in "${TAG}" is now quoted — fixed word-splitting for primary tag, but secondary use in comment body (for t in ${TAGS}) remains broken
  • .github/workflows/cicd_publish-pr-test-image.yml:217${pushed} is now quoted in echo "${pushed}" | xargs — but ${TAGS} in for t in ${TAGS} is still unquoted and vulnerable

Run: #28256218756 · tokens: in: 5010 · out: 1472 · total: 6482

… dispatch token (#36331)

Replace the repository_dispatch indirection (which needed a new PAT) with a
direct publish using the DOCKER_USERNAME/DOCKER_TOKEN secrets already in the
repo:

- cicd_comp_publish-pr-test-image.yml (new, reusable): loads the docker-image
  artifact, retags pr-N-branch (+_sha), pushes to dotcms/dotcms-test, sticky
  comment. Discovers the artifact by SHA when no run id is passed.
- cicd_1-pr.yml: publish-test-image job (needs build, label+internal gated)
  calls it right after build with artifact_run_id=github.run_id — publishes
  in parallel with tests, no dispatch token.
- cicd_publish-pr-test-image.yml: now a thin pull_request_target(labeled)
  entry for the label-applied case, calling the same reusable workflow.

Note: DOCKER_TOKEN can push to dotcms/dotcms, so the build-path job exposes it
to the PR-modifiable pipeline (internal branches only) — same risk class as the
existing CI_MACHINE_TOKEN/SEMGREP_APP_TOKEN usage there.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:122echo "${DOCKER_TOKEN}" | docker login -u "${DOCKER_USERNAME}" --password-stdin — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:140for t in ${TAGS}; do echo "docker pull ${t}"; done — unquoted ${TAGS} causes word splitting on spaces; tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") — fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... — uses unvalidated ${id}; if id is malformed or non-numeric, API may return 404 or 422 without clear error handling
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... — PR number from input is not validated for numeric format; non-numeric PR may cause API failure or unintended behavior

Existing

  • 🟡 Medium: .github/workflows/cicd_1-pr.yml:83 — gh api "repos/${REPO}/dispatches" uses unquoted ${REPO} — risk of shell injection if repo name contains spaces or shell metacharacters
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:185 — id=$(gh api ... --jq "...") fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205 — for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:210 — gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names

Resolved

  • .github/workflows/cicd_1-pr.yml:83 — no longer present; replaced by reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml:148 — no longer present; replaced by reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml:185 — no longer present; replaced by reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml:195 — no longer present; replaced by reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml:205 — no longer present; replaced by reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml:210 — no longer present; replaced by reusable workflow
  • .github/workflows/cicd_publish-pr-test-image.yml:217 — no longer present; replaced by reusable workflow

Run: #28256456873 · tokens: in: 4464 · out: 1691 · total: 6155

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... uses unvalidated ${id}; malformed ID may cause silent API failure
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... uses unvalidated ${PR}; non-numeric PR may cause API failure or unintended behavior
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:210gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation

Existing

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:122 — echo "${DOCKER_TOKEN}" | docker login -u "${DOCKER_USERNAME}" --password-stdin may prompt interactively or log empty credentials if DOCKER_TOKEN is empty or unset
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:140 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces; tag names with spaces will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155 — gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... uses unvalidated ${id}; malformed ID may cause silent API failure
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159 — gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... uses unvalidated PR number; non-numeric PR may cause API failure or unintended behavior
  • 🟡 Medium: .github/workflows/cicd_1-pr.yml:83 — gh api "repos/${REPO}/dispatches" uses unquoted ${REPO} — risk of shell injection if repo name contains spaces or shell metacharacters
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:185 — id=$(gh api ... --jq "...") fails silently if API returns non-JSON or empty array — no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205 — for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:210 — gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names

Resolved

  • .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — prior finding about id=$(gh api ...) still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:155 — prior finding about unvalidated ${id} still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:159 — prior finding about unvalidated ${PR} still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:185 — prior finding about id=$(gh api ...) still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — prior finding about unquoted ${TAGS} still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:205 — prior finding about unquoted ${TAGS} in echo still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:210 — prior finding about gh api --jq still present; no fix applied
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — prior finding about unquoted ${pushed} still present; no fix applied

Run: #28257509679 · tokens: in: 5072 · out: 1945 · total: 7017

…6331)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... uses unvalidated ${id}; malformed ID may cause silent API failure
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... uses unvalidated ${PR}; non-numeric PR may cause API failure or unintended behavior
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — `echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation

Existing

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155 — gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... uses unvalidated ${id}; malformed ID may cause silent API failure
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159 — gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... uses unvalidated ${PR}; non-numeric PR may cause API failure or unintended behavior
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:210 — gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205 — for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation

Resolved

  • .github/workflows/cicd_comp_publish-pr-test-image.yml:210 — no longer applicable; replaced by new logic at line 148
  • .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — duplicate entry; now consolidated with new logic

Run: #28258559961 · tokens: in: 4620 · out: 1856 · total: 6476

gh api has no @file syntax for field values, so -F body=@body.md sent an
empty body (HTTP 422 "body wasn't supplied"). Build the JSON with
jq --rawfile and POST/PATCH via --input -. The image push itself already
worked; this only fixes the trailing sticky-comment step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — qwen.qwen3-next-80b-a3b

New Issues

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... uses unvalidated ${id}; malformed ID may cause silent API failure
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... uses unvalidated ${PR}; non-numeric PR may cause API failure or unintended behavior
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217echo ${pushed} | xargs in echo "tags=$(echo ${pushed} | xargs)" >> "$GITHUB_OUTPUT" causes word splitting if tag names contain spaces
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205for t in ${TAGS}; do echo "docker pull ${t}"; done uses unquoted ${TAGS} — word splitting risk in comment body generation
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148echo "${DOCKER_TOKEN}" | docker login -u "${DOCKER_USERNAME}" --password-stdin — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs

Existing

  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — id=$(gh api "repos/${REPO}/issues/${PR}/comments" ... --jq "...") fails silently if API returns non-JSON or empty array; no fallback or validation before use in PATCH/POST
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:155 — gh api -X PATCH "repos/${REPO}/issues/comments/${id}" ... uses unvalidated ${id}; malformed ID may cause silent API failure
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:159 — gh api -X POST "repos/${REPO}/issues/${PR}/comments" ... uses unvalidated ${PR}; non-numeric PR may cause API failure or unintended behavior
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:217 — unquoted ${pushed} in GITHUB_OUTPUT causes word splitting on spaces in tag names
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:148 — echo "${DOCKER_TOKEN}" | docker login — if DOCKER_TOKEN is empty or unset, docker login may prompt interactively or log empty credentials, risking credential leakage in logs
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:195 — unquoted ${TAGS} in for t in ${TAGS} causes word splitting on spaces — tag names with spaces (e.g., pr-1234-foo bar) will break
  • 🟡 Medium: .github/workflows/cicd_comp_publish-pr-test-image.yml:205 — for t in ${TAGS} used in echo without quoting — same word-splitting risk in comment body generation

Resolved

  • .github/workflows/cicd_comp_publish-pr-test-image.yml:210 — gh api --jq to extract comment ID fails silently if API returns non-JSON or empty array — removed: replaced with --jq "map(select(...)) | .[0].id // empty" which returns empty string safely

Run: #28259512151 · tokens: in: 5477 · out: 1711 · total: 7188

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 dotBot Review (Bedrock)

Reviewed 3 file(s); 0 candidate(s) → 0 confirmed, 0 uncertain (unverified, kept for review).

✅ No issues found after verification.


us.deepseek.r1-v1:0 · Run: #28270473817 · tokens: in: 13232 · out: 3945 · total: 17177 · calls: 3 · est. ~$0.039

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : CI/CD PR changes GitHub Actions/workflows PR: docker image Build & push a per-PR test image to dotcms/dotcms-test

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

CI: build per-PR Docker test image on demand via label

1 participant