diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 9067797..0d8f852 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -10,6 +10,8 @@ env: IMAGE: registry.traberph.de/public/homepage # Baked in at build time (canonical URLs); override with a repository variable. SITE_URL: ${{ vars.SITE_URL || 'https://traberph.de' }} + # Default Harbor instance baked into the image as an env var (overridable at runtime). + HARBOR_URL: ${{ vars.HARBOR_URL || 'https://registry.traberph.de' }} jobs: image: @@ -50,9 +52,9 @@ jobs: platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.tags.outputs.tags }} - # Harbor settings are runtime env vars, so only the site URL is a build arg. build-args: | SITE_URL=${{ env.SITE_URL }} + HARBOR_URL=${{ env.HARBOR_URL }} labels: | org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ steps.tags.outputs.sha }} diff --git a/AGENTS.md b/AGENTS.md index 5ab7f39..dfb0ab5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,7 +27,7 @@ Consult these guides before working on related tasks: - Node adapter (standalone), started via `server.mjs` (adds security headers). Pages are prerendered by default; `/registry/…` and `404` use `prerender = false`. - Harbor data is live: `src/live.config.ts` + live loader `src/loaders/harbor.ts`, queried with `getLiveCollection()`/`getLiveEntry()`. Rendered pages are cached with `Astro.cache` (`memoryCache()`; `REGISTRY_CACHE` in `src/consts.ts`). -- Harbor config comes from `astro:env/server` (all `secret`, so read at runtime, never inlined). Anonymous Harbor returns 401 for single-repo GETs; look repos up via the listing with `?q=name=…`. +- Harbor config comes from `astro:env/server` (all `secret`, so read at runtime, never inlined). The Docker image sets a default `HARBOR_URL` env var from a build arg. Anonymous Harbor returns 401 for single-repo GETs; look repos up via the listing with `?q=name=…`. - Runtime deps must be listed in `vite.ssr.noExternal` (the Docker image ships no `node_modules`). - Zod comes from `astro/zod` (Zod 4). - `astro check` needs TypeScript 6 (TS 7 is unsupported), so keep `typescript@^6`. diff --git a/Dockerfile b/Dockerfile index cb8637d..16717fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1.10 # The build output is platform-independent, so build natively (no QEMU) for multi-arch images. -FROM --platform=$BUILDPLATFORM node:22-alpine AS build +FROM --platform=$BUILDPLATFORM node:24-alpine AS build WORKDIR /app RUN corepack enable ENV ASTRO_TELEMETRY_DISABLED=1 @@ -9,13 +9,16 @@ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ pnpm install --frozen-lockfile COPY . . -# Only the canonical site URL is baked in; Harbor settings are read at runtime. +# The canonical site URL is compiled in; Harbor settings are read at runtime (see below). ARG SITE_URL RUN pnpm build -FROM node:22-alpine +FROM node:24-alpine WORKDIR /app ENV NODE_ENV=production HOST=0.0.0.0 PORT=8080 +# Default Harbor instance; still overridable with `-e HARBOR_URL=...` at runtime. +ARG HARBOR_URL +ENV HARBOR_URL=${HARBOR_URL} # The server build is self-contained (see `vite.ssr.noExternal`), so no node_modules. COPY --from=build /app/dist ./dist COPY package.json server.mjs ./ diff --git a/README.md b/README.md index acf7af7..e5ceb6d 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,12 @@ Harbor settings are passed to the container at runtime, so changing them needs a ## Container (plain Docker) ```sh -docker build -t homepage --build-arg SITE_URL=https://example.com . -docker run -p 8080:8080 \ - -e HARBOR_URL=https://registry.example.com \ - homepage +docker build -t homepage \ + --build-arg SITE_URL=https://example.com \ + --build-arg HARBOR_URL=https://registry.example.com \ + . +docker run -p 8080:8080 homepage +# HARBOR_URL is baked in as a default env var; override it with -e HARBOR_URL=... if needed. # optional robot account for non-public projects: # -e HARBOR_USERNAME='robot$showcase' -e HARBOR_PASSWORD=... ``` diff --git a/compose.yaml b/compose.yaml index ff65da4..4a9171d 100644 --- a/compose.yaml +++ b/compose.yaml @@ -9,6 +9,7 @@ services: context: . args: SITE_URL: ${SITE_URL:-} + HARBOR_URL: ${HARBOR_URL:-} image: homepage:latest restart: unless-stopped ports: diff --git a/package.json b/package.json index 200ec21..60a94aa 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@astrojs/check": "^0.9.10", - "@types/node": "^22.20.4", + "@types/node": "^24.19.0", "typescript": "^6.0.3" }, "private": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7a61f5..3a8a954 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,23 +10,23 @@ importers: dependencies: '@astrojs/node': specifier: ^11.1.6 - version: 11.1.6(astro@7.3.5(@types/node@22.20.4)(yaml@2.9.1)) + version: 11.1.6(astro@7.3.5(@types/node@24.19.0)(yaml@2.9.1)) astro: specifier: ^7.3.5 - version: 7.3.5(@types/node@22.20.4)(yaml@2.9.1) + version: 7.3.5(@types/node@24.19.0)(yaml@2.9.1) marked: specifier: ^18.0.14 version: 18.0.14 sharp: specifier: ^0.35.5 - version: 0.35.5(@types/node@22.20.4) + version: 0.35.5(@types/node@24.19.0) devDependencies: '@astrojs/check': specifier: ^0.9.10 version: 0.9.10(@emnapi/runtime@1.11.3)(prettier@3.9.9)(typescript@6.0.3) '@types/node': - specifier: ^22.20.4 - version: 22.20.4 + specifier: ^24.19.0 + version: 24.19.0 typescript: specifier: ^6.0.3 version: 6.0.3 @@ -747,8 +747,8 @@ packages: '@types/nlcst@2.0.3': resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} - '@types/node@22.20.4': - resolution: {integrity: sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA==} + '@types/node@24.19.0': + resolution: {integrity: sha512-zY+5tKxXdhGh1PYI0ac+7juvEu4OI6vWtVVoj5i2m42jxAY1U+zHGt6QCyOFwykdP62sM3MJ9stoYYUw5aCWew==} '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -817,8 +817,8 @@ packages: resolution: {integrity: sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==} hasBin: true - ansi-regex@6.3.0: - resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} + ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} engines: {node: '>=12'} ansi-styles@6.2.3: @@ -1248,8 +1248,8 @@ packages: micromark-util-symbol@2.0.1: resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} - micromark-util-types@2.0.2: - resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + micromark-util-types@2.0.3: + resolution: {integrity: sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==} mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} @@ -1532,8 +1532,8 @@ packages: uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} undici@8.11.2: resolution: {integrity: sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==} @@ -1949,10 +1949,10 @@ snapshots: github-slugger: 2.0.0 satteri: 0.10.5 - '@astrojs/node@11.1.6(astro@7.3.5(@types/node@22.20.4)(yaml@2.9.1))': + '@astrojs/node@11.1.6(astro@7.3.5(@types/node@24.19.0)(yaml@2.9.1))': dependencies: '@astrojs/internal-helpers': 0.11.0 - astro: 7.3.5(@types/node@22.20.4)(yaml@2.9.1) + astro: 7.3.5(@types/node@24.19.0)(yaml@2.9.1) send: 1.2.1 server-destroy: 1.0.1 transitivePeerDependencies: @@ -2397,9 +2397,9 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/node@22.20.4': + '@types/node@24.19.0': dependencies: - undici-types: 6.21.0 + undici-types: 7.24.6 '@types/unist@3.0.3': {} @@ -2480,7 +2480,7 @@ snapshots: dependencies: process-ancestry: 0.1.0 - ansi-regex@6.3.0: {} + ansi-regex@6.4.0: {} ansi-styles@6.2.3: {} @@ -2493,7 +2493,7 @@ snapshots: aria-query@5.3.2: {} - astro@7.3.5(@types/node@22.20.4)(yaml@2.9.1): + astro@7.3.5(@types/node@24.19.0)(yaml@2.9.1): dependencies: '@astrojs/compiler-rs': 0.5.1 '@astrojs/internal-helpers': 0.11.0 @@ -2543,13 +2543,13 @@ snapshots: unifont: 0.7.5 unstorage: 1.17.5 verkit: 0.4.1 - vite: 8.3.1(@types/node@22.20.4)(esbuild@0.28.2)(yaml@2.9.1) - vitefu: 1.1.3(vite@8.3.1(@types/node@22.20.4)(esbuild@0.28.2)(yaml@2.9.1)) + vite: 8.3.1(@types/node@24.19.0)(esbuild@0.28.2)(yaml@2.9.1) + vitefu: 1.1.3(vite@8.3.1(@types/node@24.19.0)(esbuild@0.28.2)(yaml@2.9.1)) xxhash-wasm: 1.1.0 yargs-parser: 22.0.0 zod: 4.6.5 optionalDependencies: - sharp: 0.35.5(@types/node@22.20.4) + sharp: 0.35.5(@types/node@24.19.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -2937,7 +2937,7 @@ snapshots: micromark-util-character@2.1.1: dependencies: micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 micromark-util-encode@2.0.1: {} @@ -2949,7 +2949,7 @@ snapshots: micromark-util-symbol@2.0.1: {} - micromark-util-types@2.0.2: {} + micromark-util-types@2.0.3: {} mime-db@1.54.0: {} @@ -3134,7 +3134,7 @@ snapshots: setprototypeof@1.2.0: {} - sharp@0.35.5(@types/node@22.20.4): + sharp@0.35.5(@types/node@24.19.0): dependencies: '@img/colour': 1.1.0 detect-libc: 2.1.2 @@ -3165,7 +3165,7 @@ snapshots: '@img/sharp-win32-arm64': 0.35.5 '@img/sharp-win32-ia32': 0.35.5 '@img/sharp-win32-x64': 0.35.5 - '@types/node': 22.20.4 + '@types/node': 24.19.0 shiki@4.4.3: dependencies: @@ -3206,7 +3206,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.3.0 + ansi-regex: 6.4.0 svgo@4.1.0: dependencies: @@ -3251,7 +3251,7 @@ snapshots: uncrypto@0.1.3: {} - undici-types@6.21.0: {} + undici-types@7.24.6: {} undici@8.11.2: {} @@ -3317,7 +3317,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@8.3.1(@types/node@22.20.4)(esbuild@0.28.2)(yaml@2.9.1): + vite@8.3.1(@types/node@24.19.0)(esbuild@0.28.2)(yaml@2.9.1): dependencies: lightningcss: 1.33.0 picomatch: 4.0.7 @@ -3325,14 +3325,14 @@ snapshots: rolldown: 1.2.11 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 22.20.4 + '@types/node': 24.19.0 esbuild: 0.28.2 fsevents: 2.3.3 yaml: 2.9.1 - vitefu@1.1.3(vite@8.3.1(@types/node@22.20.4)(esbuild@0.28.2)(yaml@2.9.1)): + vitefu@1.1.3(vite@8.3.1(@types/node@24.19.0)(esbuild@0.28.2)(yaml@2.9.1)): optionalDependencies: - vite: 8.3.1(@types/node@22.20.4)(esbuild@0.28.2)(yaml@2.9.1) + vite: 8.3.1(@types/node@24.19.0)(esbuild@0.28.2)(yaml@2.9.1) volar-service-css@0.0.71(@volar/language-service@2.4.28(typescript@6.0.3)): dependencies: