diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..585baee0 --- /dev/null +++ b/.dockerignore @@ -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 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..59d63ec6 --- /dev/null +++ b/.github/workflows/docker.yml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 716f3a54..4c62e446 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..22c556b1 --- /dev/null +++ b/Dockerfile @@ -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"]