Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Build artifacts and caches
.nx/
node_modules/
**/node_modules/
**/dist/

# Source control
.git/
.gitmodules

# CI/CD configuration (not needed inside the image)
.github/
.gitlab-ci.yml

# Dev tooling
.devcontainer/
.vscode/
.windsurf/
.husky/
.agents/
.kilocode/

# Documentation and local scratch
docs/
tmp/

# Lockfiles other than bun.lock (only bun.lock is used by the builder stage)
package-lock.json
yarn.lock
pnpm-lock.yaml

# Miscellaneous
*.log
.prettierrc
.prettierignore
.nxignore
eslint.config.mjs
jest.config.ts
jest.preset.js
vitest.config.ts
knip.json
CHANGELOG.md
README.md
AGENTS.md
72 changes: 72 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Docker

on:
workflow_dispatch:
inputs:
version:
description: 'Release version tag to build (e.g. v1.2.3), defaults to latest release'
required: false
type: string
workflow_call:
inputs:
version:
description: 'Release version tag to build (e.g. v1.2.3), defaults to latest release'
required: false
type: string

jobs:
docker:
name: Build and push Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # needed to push to GHCR
steps:
- 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
Comment on lines +25 to +72

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

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

11 changes: 11 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,14 @@ jobs:
permissions:
contents: read
id-token: write

docker:
name: Build and push Docker image
needs: release
if: ${{ !inputs.dry_run }}
uses: ./.github/workflows/docker.yml
with:
version: ${{ needs.release.outputs.tag }}
permissions:
contents: read
packages: write
43 changes: 43 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# ── Stage 1: builder ─────────────────────────────────────────────────────────
# Installs all dependencies and builds every workspace package from source.
# Nothing is downloaded from the npm registry for @abapify/* packages.
FROM node:24-bookworm AS builder

# Install bun (matches the version used in CI)
RUN npm install -g bun@1.2.9

WORKDIR /build

# Copy workspace manifests first for better layer caching
COPY package.json bun.lock nx.json tsconfig.base.json tsconfig.json ./

# Copy all workspace members required for the build
COPY packages/ ./packages/
COPY tools/ ./tools/
COPY samples/ ./samples/

# Install all dependencies (including dev deps needed for the build)
RUN bun install --frozen-lockfile

# Build every package (Nx respects the dependency graph, so output is correct)
RUN npx nx run-many -t build --all --parallel=4

# ── Stage 2: runner ──────────────────────────────────────────────────────────
# Lean image that ships only the built artifacts and their runtime deps.
# The adt CLI and all plugins are available without any npm registry access.
FROM node:24-bookworm-slim

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"]
Comment on lines +30 to +43

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

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