feat: restrict Docker image publishing to releases only#37
Conversation
- Dockerfile: multi-stage build (builder + slim runner) - Stage 1 builds all packages from source via bun + npx nx - Stage 2 copies built artifacts + node_modules, exposes adt via PATH - .github/workflows/docker.yml: triggers on push/tags/PRs, pushes to GHCR - .dockerignore: excludes node_modules, dist, .git, dev tooling Co-authored-by: ThePlenkov <6381507+ThePlenkov@users.noreply.github.com>
- docker.yml: replace push/PR triggers with workflow_dispatch + workflow_call (mirrors publish.yml pattern); always push; remove branch/PR tag types; fail if no release exists (remove main fallback) - release.yml: add docker job that calls docker.yml after release (same pattern as publish job), skipped on dry runs Co-authored-by: ThePlenkov <6381507+ThePlenkov@users.noreply.github.com>
|
View your CI Pipeline Execution ↗ for commit 8524633
☁️ Nx Cloud last updated this comment at |
Review Summary by QodoAdd Docker image CI workflow and release-gated publishing
WalkthroughsDescription• Add Docker image CI workflow with release-gated publishing • Create multi-stage Dockerfile for optimized builds • Integrate Docker job into release workflow • Restrict Docker builds to explicit releases only Diagramflowchart LR
Release["Release triggered"]
Release -- "calls" --> Docker["docker.yml workflow"]
Docker -- "resolves" --> Ref["Release tag/version"]
Ref -- "builds" --> Image["Docker image"]
Image -- "pushes to" --> GHCR["GitHub Container Registry"]
File Changes1. Dockerfile
|
Code Review by Qodo
1. Plugins not enabled in image
|
| WORKDIR /app | ||
|
|
||
| # Copy the built workspace packages (dist/ directories are now populated) | ||
| COPY --from=builder /build/packages ./packages | ||
| # Copy the workspace node_modules so @abapify/* symlinks resolve correctly | ||
| # and third-party runtime deps (commander, axios, etc.) are present | ||
| COPY --from=builder /build/node_modules ./node_modules | ||
| # Copy the root package.json so npm workspace resolution works at runtime | ||
| COPY --from=builder /build/package.json ./ | ||
|
|
||
| # Expose workspace binaries (adt, adt-codegen, …) as global commands | ||
| ENV PATH="/app/node_modules/.bin:$PATH" | ||
|
|
||
| CMD ["adt", "--help"] |
There was a problem hiding this comment.
1. Plugins not enabled in image 🐞 Bug ✓ Correctness
The Docker runtime image does not include the repo’s adt.config.ts, so adt won’t auto-load the plugin commands (atc/export/codegen) even though the image claims they’re available. Users will get a reduced CLI feature set unless they provide their own config at runtime.
Agent Prompt
## Issue description
The built Docker runtime image omits the repository’s `adt.config.ts`, so `adt-cli` won’t load the plugin commands (atc/export/codegen) by default.
## Issue Context
`adt-cli` searches for `adt.config.ts` in the current directory/parents and uses it to register plugin commands. The repo root has a config enabling core plugins, but the final image only copies `packages/`, `node_modules/`, and `package.json`.
## Fix Focus Areas
- Dockerfile[30-43]
- adt.config.ts[10-20]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| - name: Resolve ref | ||
| id: resolve-ref | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| INPUT_VERSION: ${{ inputs.version }} | ||
| run: | | ||
| if [ -n "$INPUT_VERSION" ]; then | ||
| resolved="$INPUT_VERSION" | ||
| else | ||
| resolved=$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName -q .tagName) | ||
| fi | ||
| echo "Resolved ref: ${resolved}" | ||
| echo "ref=${resolved}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ steps.resolve-ref.outputs.ref }} | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
|
|
||
| - name: Log in to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Extract Docker metadata | ||
| id: meta | ||
| uses: docker/metadata-action@v5 | ||
| with: | ||
| images: ghcr.io/${{ github.repository }} | ||
| tags: | | ||
| type=semver,pattern={{version}} | ||
| type=semver,pattern={{major}}.{{minor}} | ||
| type=sha | ||
|
|
||
| - name: Build and push | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: . | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max |
There was a problem hiding this comment.
2. Arbitrary refs can be published 🐞 Bug ⛨ Security
docker.yml accepts an arbitrary version input and uses it directly as the checkout ref, while always pushing to GHCR. This means a maintainer can accidentally publish an image built from a branch/SHA (not a release), which undermines the PR’s “releases only” publishing intent.
Agent Prompt
## Issue description
The Docker publishing workflow still allows publishing from arbitrary git refs via the `version` input (branch names / SHAs), while unconditionally pushing to GHCR.
## Issue Context
This PR’s goal is “releases only” Docker publishing. However, `inputs.version` is used directly as the checkout ref with no validation.
## Fix Focus Areas
- .github/workflows/docker.yml[25-72]
- .github/workflows/release.yml[105-114]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Docker builds were triggering on every push to
mainand every PR, publishing unvalidated images automatically. The workflow should follow the same release-gated pattern aspublish.yml.docker.ymlpush/pull_requesttriggers withworkflow_dispatch+workflow_call(mirrorspublish.yml)mainfallback)push: trueunconditionally since the workflow is now explicit-onlyrelease.ymldockerjob that callsdocker.ymlviaworkflow_callafter the release job, using the released tag — runs on every non-dry-run release:Unlike
publish, the Docker job is not gated byinputs.publish— pushing an image is the natural outcome of any real release.🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.