From dff68fd83414c1efe0d9d44f676c8da6e086d293 Mon Sep 17 00:00:00 2001 From: Iain Lane Date: Wed, 9 Jul 2025 17:44:52 +0100 Subject: [PATCH] refactor(lint-pr-title): modernise Dockerfile The previous Dockerfile was overly complex and inefficient, a result of adapting an older style to a workspace environment. The multi-stage build was difficult to read and did not use modern Docker features for caching. To fix these problems, we simplify the build process into a more readable multi-stage build. We introduce Docker cache mounts for dependency installation, which will result in significantly faster builds. The COPY commands are now more specific to avoid copying unnecessary files into the image. Tests continue to be run as a non-root user to ensure file permission tests work correctly, but in a more streamlined way. --- actions/lint-pr-title/Dockerfile | 74 +++++++++++++++++--------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/actions/lint-pr-title/Dockerfile b/actions/lint-pr-title/Dockerfile index a88b935e6..5a55c9240 100644 --- a/actions/lint-pr-title/Dockerfile +++ b/actions/lint-pr-title/Dockerfile @@ -1,48 +1,52 @@ # This file must be built from the root of the repository. # Example: docker build . -f actions/lint-pr-title/Dockerfile + FROM oven/bun:1.2.18@sha256:2cdd9c93006af1b433c214016d72a3c60d7aa2c75691cb44dfd5250aa379986b AS base -# Create a non-root user with a home directory -# Run tests as non-root user because one test expects EACCES when writing to a -# read-only file, and this will not fail as root. -RUN useradd -ms /bin/bash -d /home/newuser newuser +WORKDIR /usr/src/app + +# Create a non-root user to run the tests. Run tests as non-root user because +# one test expects EACCES when writing to a read-only file, and this will not +# fail as root. +RUN useradd -ms /bin/bash newuser + +# Install dependencies +FROM base AS deps + +COPY package.json bun.lock ./ +COPY actions/dependabot-auto-triage/package.json ./actions/dependabot-auto-triage/ + +# Because we use bun's workspaces, we need to have all package.json files +# available, even if they're not used. (We filter to one workspace.) +COPY actions/get-latest-workflow-artifact/package.json ./actions/get-latest-workflow-artifact/ +COPY actions/lint-pr-title/package.json ./actions/lint-pr-title/ + +RUN --mount=type=cache,target=/root/.bun/install/cache \ + bun install --frozen-lockfile --filter lint-pr-title + +# Run tests +FROM base AS test + +COPY --from=deps /usr/src/app/node_modules ./node_modules +COPY --chown=newuser:newuser actions/lint-pr-title/ ./actions/lint-pr-title/ USER newuser -WORKDIR /home/newuser - -FROM base AS install -RUN mkdir -p temp/dev -WORKDIR /home/newuser/temp/dev -COPY --chown=newuser:newuser package.json bun.lock ./ -COPY --chown=newuser:newuser actions/dependabot-auto-triage/package.json ./actions/dependabot-auto-triage/ -COPY --chown=newuser:newuser actions/get-latest-workflow-artifact/package.json ./actions/get-latest-workflow-artifact/ -COPY --chown=newuser:newuser actions/lint-pr-title/package.json ./actions/lint-pr-title/ -RUN bun install --frozen-lockfile --filter lint-pr-title - -# install with --production (exclude devDependencies) -RUN mkdir -p temp/prod -WORKDIR /home/newuser/temp/prod -COPY --chown=newuser:newuser package.json bun.lock ./ -COPY --chown=newuser:newuser actions/dependabot-auto-triage/package.json ./actions/dependabot-auto-triage/ -COPY --chown=newuser:newuser actions/get-latest-workflow-artifact/package.json ./actions/get-latest-workflow-artifact/ -COPY --chown=newuser:newuser actions/lint-pr-title/package.json ./actions/lint-pr-title/ -RUN bun install --frozen-lockfile --production --filter lint-pr-title - -FROM base AS prerelease -WORKDIR /home/newuser/app -COPY --from=install /home/newuser/temp/dev/node_modules ./node_modules -COPY --chown=newuser:newuser . . - -# Install dev dependencies to run the tests + ENV NODE_ENV=development + RUN bun run --filter lint-pr-title test -FROM base AS release +# Assemble final image from a clean stage +FROM base + USER root + WORKDIR /usr/src/app -COPY --from=install /home/newuser/temp/prod/node_modules ./node_modules -COPY --from=prerelease /home/newuser/app/actions/lint-pr-title/src ./actions/lint-pr-title/src -COPY --from=prerelease /home/newuser/app/actions/lint-pr-title/package.json ./actions/lint-pr-title/ -COPY --from=prerelease /home/newuser/app/actions/lint-pr-title/commitlint.config.js ./actions/lint-pr-title/ + +COPY --from=deps /usr/src/app/node_modules ./node_modules +COPY actions/lint-pr-title/src ./actions/lint-pr-title/src +COPY actions/lint-pr-title/package.json ./actions/lint-pr-title/ +COPY actions/lint-pr-title/commitlint.config.js ./actions/lint-pr-title/ WORKDIR /usr/src/app/actions/lint-pr-title + ENTRYPOINT [ "bun", "run", "src/index.ts" ]