From b02ded1d7e40bf0dc74cc0b311246b26ad2ac4c5 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sat, 31 May 2025 22:28:26 +0200 Subject: [PATCH 01/13] use smaller alpine image for asset building --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index fe0a303322..36e2d3f1fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ ################### Asset Builder -FROM node:22 AS build-assets -SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] +FROM node:24-alpine AS build-assets ENV NO_UPDATE_NOTIFIER=1 +SHELL [ "/bin/sh", "-euo", "pipefail", "-c" ] WORKDIR /build/ From 4ec1f51bed3c0ec866dbc37fa20c9846d9630c70 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sat, 31 May 2025 22:30:46 +0200 Subject: [PATCH 02/13] use timestamp tag for metacpan-base rather than 'latest' --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 36e2d3f1fb..981c3ee1da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,7 @@ EOT HEALTHCHECK CMD [ "test", "-e", "root/assets/assets.json" ] ################### Web Server -# hadolint ignore=DL3007 -FROM metacpan/metacpan-base:latest AS server +FROM metacpan/metacpan-base:main-20250531-090128 AS server SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] RUN \ From 5971677024ad16e43a6c2cda32a6f3554002cf2b Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Mon, 2 Jun 2025 18:43:05 +0200 Subject: [PATCH 03/13] separate CPAN building to separate stage in Dockerfile Using a separate build stage allows Docker to cache the build results separately from the rest of the build. It also can allow the CPAN building and the main server image to use separate base images. --- Dockerfile | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 981c3ee1da..5e09f51050 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,8 +24,11 @@ EOT HEALTHCHECK CMD [ "test", "-e", "root/assets/assets.json" ] -################### Web Server -FROM metacpan/metacpan-base:main-20250531-090128 AS server +################### Web Server Base +FROM metacpan/metacpan-base:main-20250531-090128 AS server-base + +################### CPAN Prereqs +FROM server-base AS build-cpan-prereqs SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] RUN \ @@ -45,14 +48,31 @@ RUN \ cpm install --show-build-log-on-failure --resolver=snapshot EOT -ENV PERL5LIB="/app/local/lib/perl5" -ENV PATH="/app/local/bin:${PATH}" +################### Web Server +FROM server-base AS server +SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] + +RUN \ + --mount=type=cache,target=/var/cache/apt,sharing=private \ + --mount=type=cache,target=/var/lib/apt/lists,sharing=private \ +<= 0.30.2)' +EOT + +WORKDIR /app/ COPY *.md app.psgi log4perl* metacpan_web.* metacpan_web_local.* ./ COPY bin bin COPY lib lib COPY root root + COPY --from=build-assets /build/root/assets root/assets +COPY --from=build-cpan-prereqs /app/local local + +ENV PERL5LIB="/app/local/lib/perl5" +ENV PATH="/app/local/bin:${PATH}" +ENV METACPAN_WEB_HOME=/app CMD [ \ "/uwsgi.sh", \ @@ -71,6 +91,8 @@ ENV PLACK_ENV=development USER root +COPY cpanfile cpanfile.snapshot ./ + RUN \ --mount=type=cache,target=/root/.perl-cpm \ < Date: Mon, 2 Jun 2025 18:45:17 +0200 Subject: [PATCH 04/13] Docker: allow a slim build Slim builds don't incude a compiler or other development tools. The tag name of the slim build may not match the non-slim build exactly, so we need to list both. Installing the CPAN prereqs still needs the non-slim build. --- Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5e09f51050..ae92537947 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,7 @@ +ARG SLIM_BUILD +ARG MAYBE_BASE_BUILD=${SLIM_BUILD:+server-base-slim} +ARG BASE_BUILD=${MAYBE_BASE_BUILD:-server-base} + ################### Asset Builder FROM node:24-alpine AS build-assets @@ -26,6 +30,7 @@ HEALTHCHECK CMD [ "test", "-e", "root/assets/assets.json" ] ################### Web Server Base FROM metacpan/metacpan-base:main-20250531-090128 AS server-base +FROM metacpan/metacpan-base:main-20250531-090129-slim AS server-base-slim ################### CPAN Prereqs FROM server-base AS build-cpan-prereqs @@ -49,7 +54,9 @@ RUN \ EOT ################### Web Server -FROM server-base AS server +# false positive +# hadolint ignore=DL3006 +FROM ${BASE_BUILD} AS server SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] RUN \ From 1e719d5acb635dc8eb2d6ef0556b32e15c4e9f88 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sun, 1 Jun 2025 15:24:38 +0200 Subject: [PATCH 05/13] upgrade node and npm versions for dev tools in docker --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index ae92537947..9de08c7c62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -122,10 +122,10 @@ RUN \ --mount=type=cache,target=/var/lib/apt/lists,sharing=private \ --mount=type=cache,target=/root/.npm,sharing=private \ <= 21.6.1)' - npm install -g npm@^10.4.0 + apt-get satisfy -y -f --no-install-recommends 'nodejs (>= 24.1.0)' + npm install -g npm@^11.4.1 EOT COPY package.json package-lock.json ./ From b7e4c6fa3168b20f0a94081b45a5f761e187aed2 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sun, 1 Jun 2025 15:25:50 +0200 Subject: [PATCH 06/13] add docker updates to dependabot --- .github/dependabot.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c84846ad24..fe0dde28aa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,12 +1,14 @@ ---- version: 2 updates: - - package-ecosystem: 'github-actions' - directory: '/' + - package-ecosystem: github-actions + directory: / schedule: - # Check for updates to GitHub Actions every week - interval: 'weekly' + interval: weekly - package-ecosystem: npm - directory: '/' + directory: / schedule: - interval: 'weekly' + interval: weekly + - package-ecosystem: docker + directory: / + schedule: + interval: daily From 87198f3ac5a0745cab92eb6d7dc55d7a766dac05 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sun, 1 Jun 2025 15:26:02 +0200 Subject: [PATCH 07/13] better name for automerge workflow --- .github/workflows/automerge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 6ae1b665fa..a9b56fc7ec 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,4 +1,4 @@ -name: Enable Auto-Merge For metacpan-automation +name: Enable Auto-Merge For bots on: pull_request_target: types: [opened] From 93f1f03ed40cb3ceb879fa54bdcf1dc8d75948d1 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sun, 1 Jun 2025 15:26:33 +0200 Subject: [PATCH 08/13] rebuild asset builder when files change --- docker-compose.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 8f7bfd50e8..aa25a47278 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,12 @@ services: - './root/static/:/build/root/static/' - 'web-assets:/build/root/assets/' command: ['./build-assets.mjs', '--watch'] + develop: + watch: + - path: ./build-assets.mjs + action: rebuild + - path: ./package.json + action: rebuild web-server: build: context: . From 096d003ca77f5ff4dd3ebd1a249212e5d8bb1ec9 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sun, 1 Jun 2025 15:26:59 +0200 Subject: [PATCH 09/13] use port 8000 for server inside docker by default --- .github/workflows/test.yml | 2 +- Dockerfile | 6 +++--- docker-compose.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a4b17f4282..256766273c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,7 +77,7 @@ jobs: load: true - name: Run Perl tests run: > - docker run -d -i -p 5001:80 + docker run -d -i -p 5001:8000 ${{ steps.docker-build-test.outputs.imageid }} - uses: actions/setup-node@v4 with: diff --git a/Dockerfile b/Dockerfile index 9de08c7c62..d634971237 100644 --- a/Dockerfile +++ b/Dockerfile @@ -83,12 +83,12 @@ ENV METACPAN_WEB_HOME=/app CMD [ \ "/uwsgi.sh", \ - "--http-socket", ":80" \ + "--http-socket", ":8000" \ ] -EXPOSE 80 +EXPOSE 8000 -HEALTHCHECK --start-period=3s CMD [ "curl", "--fail", "http://localhost/healthcheck" ] +HEALTHCHECK --start-period=3s CMD [ "curl", "--fail", "http://localhost:8000/healthcheck" ] ################### Development Server FROM server AS develop diff --git a/docker-compose.yml b/docker-compose.yml index aa25a47278..07b1cffea8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,7 +22,7 @@ services: - 'web-assets:/app/root/assets/' - '/app/local' ports: - - '5001:80' + - '5001:8000' environment: # default is 120, shorten to work with compose label COLUMNS: 96 From ba1299a120d1a2b931ac4bcf351ad7d305d5a333 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Sun, 1 Jun 2025 15:35:56 +0200 Subject: [PATCH 10/13] use fully qualified name when creating tag for docker hub --- .github/workflows/build-container.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 3832540521..e23dfd1ce2 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -53,7 +53,7 @@ jobs: uses: docker/metadata-action@v5 with: images: | - ${{ github.repository }} + docker.io/${{ github.repository }} ghcr.io/${{ github.repository }} flavor: | latest=false @@ -72,7 +72,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} annotations: ${{ steps.meta.outputs.annotations }} - name: Update deployed image - if: ${{ contains( fromJSON(steps.meta.outputs.json).tags, format('{0}:latest', github.repository)) }} + if: contains( format(',{0},', join( fromJSON(steps.meta.outputs.json).tags, ',' ) ), ':latest,' ) uses: benc-uk/workflow-dispatch@v1 with: repo: metacpan/metacpan-k8s From 9fb779033bc7d9555000d5e05321705ee5da4bb8 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Mon, 2 Jun 2025 18:35:58 +0200 Subject: [PATCH 11/13] Dockerfile: add redundant SHELL command to satiate hadolint --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index d634971237..2ca4df520c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -92,6 +92,7 @@ HEALTHCHECK --start-period=3s CMD [ "curl", "--fail", "http://localhost:8000/hea ################### Development Server FROM server AS develop +SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] ENV COLUMNS=120 ENV PLACK_ENV=development @@ -111,6 +112,7 @@ USER metacpan ################### Test Runner FROM develop AS test +SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] ENV NO_UPDATE_NOTIFIER=1 ENV PLACK_ENV= From d0aab37d89e03c65f318f26add88cd34eb5718cd Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Mon, 2 Jun 2025 18:39:45 +0200 Subject: [PATCH 12/13] simplify code for providing a default COLUMNS Catalyst no longer warns about Term::Size::Any being missing if COLUMNS is set. --- lib/MetaCPAN/Web.pm | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/MetaCPAN/Web.pm b/lib/MetaCPAN/Web.pm index 1e58e93ae7..c5d76aa7d6 100644 --- a/lib/MetaCPAN/Web.pm +++ b/lib/MetaCPAN/Web.pm @@ -43,14 +43,7 @@ __PACKAGE__->config( __PACKAGE__->log( Log::Log4perl::Catalyst->new( undef, autoflush => 1 ) ); -# Squash warnings when not in a terminal (like when running under Docker) -# Catalyst throws warnings if it can't detect the size, even if $ENV{COLUMNS} -# exists. Just lie to it to shut it up. -use Term::Size::Perl (); -if ( !Term::Size::Perl::chars() ) { - no warnings 'once', 'redefine'; - *Term::Size::Perl::chars = sub { $ENV{COLUMNS} || 80 }; -} +$ENV{COLUMNS} ||= 80; after prepare_action => sub { my ($self) = @_; From ab6d690b3f455b04f1d19e3810ad7ffe673f1eda Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Mon, 2 Jun 2025 18:40:10 +0200 Subject: [PATCH 13/13] remove redundant app name from config --- metacpan_web.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/metacpan_web.yaml b/metacpan_web.yaml index 534b1a2716..55250b9ea1 100644 --- a/metacpan_web.yaml +++ b/metacpan_web.yaml @@ -1,5 +1,3 @@ -name: MetaCPAN::Web - api: https://api.metacpan.org/v1 source_host: https://st.aticpan.org web_host: https://metacpan.org