javi-forge 1.21.2 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- FROM node:22-slim
1
+ FROM node:22-slim@sha256:689c11043dad91472750cd824c97dd5e2318e9dd6f954e492fe7af0135d33ceb
2
2
  RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
3
3
  RUN npm install -g pnpm@10
4
4
  RUN useradd -m -s /bin/bash runner
@@ -139,6 +139,26 @@ async function buildCICommands(stack, buildTool, projectDir) {
139
139
  return { lintCmd: null, compileCmd: null, testCmd: null };
140
140
  }
141
141
  }
142
+ /**
143
+ * Prefer the REPO-LOCAL `ci-local/docker/` over the CLI's bundled Dockerfiles.
144
+ *
145
+ * A globally-installed javi-forge bundles its own `ci-local/docker/*.Dockerfile`,
146
+ * which can lag the fixes committed in the repo being CI'd (the stale-global
147
+ * pnpm-11 image incident). When the project ships its OWN Dockerfile for the
148
+ * detected stack, that committed file must win.
149
+ *
150
+ * Resolution is PER-STACK on purpose: the repo dir is returned ONLY when
151
+ * `ci-local/docker/${stack}.Dockerfile` actually exists. If the repo has the
152
+ * directory but not the specific stack Dockerfile, this returns `undefined` so
153
+ * `ensureImage` falls back to the bundled dir — which avoids `ensureImage`'s
154
+ * first-run write-through (docker.ts) generating a Dockerfile INTO the user's
155
+ * repo. `undefined` means "use the bundled default", exactly as before.
156
+ */
157
+ async function resolveRepoDockerfilesDir(projectDir, stack) {
158
+ const repoDockerDir = path.join(projectDir, "ci-local", "docker");
159
+ const stackDockerfile = path.join(repoDockerDir, `${stack}.Dockerfile`);
160
+ return (await fs.pathExists(stackDockerfile)) ? repoDockerDir : undefined;
161
+ }
142
162
  function freezeRunner(runner) {
143
163
  return Object.freeze({
144
164
  ...runner,
@@ -398,9 +418,11 @@ export async function runCI(options, onStep, onGateOutcome) {
398
418
  });
399
419
  }
400
420
  else {
421
+ const dockerfilesDir = await resolveRepoDockerfilesDir(projectDir, stackInfo.stackType);
401
422
  shellImage = await ensureImage({
402
423
  stack: stackInfo.stackType,
403
424
  javaVersion: stackInfo.javaVersion,
425
+ ...(dockerfilesDir ? { dockerfilesDir } : {}),
404
426
  });
405
427
  }
406
428
  report(onStep, "docker-image", "Docker image ready", "done");
@@ -435,9 +457,11 @@ export async function runCI(options, onStep, onGateOutcome) {
435
457
  const stepImage = "docker-image";
436
458
  report(onStep, stepImage, `Building image for ${stackInfo.stackType}`, "running");
437
459
  try {
460
+ const dockerfilesDir = await resolveRepoDockerfilesDir(projectDir, stackInfo.stackType);
438
461
  autoImage = await ensureImage({
439
462
  stack: stackInfo.stackType,
440
463
  javaVersion: stackInfo.javaVersion,
464
+ ...(dockerfilesDir ? { dockerfilesDir } : {}),
441
465
  });
442
466
  report(onStep, stepImage, "Docker image ready", "done");
443
467
  }
@@ -586,9 +610,11 @@ async function runRunner(runner, ctx) {
586
610
  }
587
611
  else {
588
612
  report(onStep, stepImage, `Building image for ${runner.name} (${runner.stack})`, "running");
613
+ const dockerfilesDir = await resolveRepoDockerfilesDir(projectDir, runner.stack);
589
614
  imageName = await ensureImage({
590
615
  stack: runner.stack,
591
616
  javaVersion: runner.javaVersion,
617
+ ...(dockerfilesDir ? { dockerfilesDir } : {}),
592
618
  });
593
619
  }
594
620
  if (!runner.image) {
@@ -1122,10 +1148,12 @@ docker, onOutcome) {
1122
1148
  // SAME relpaths in the SAME order, newline-joined, only for scope:changed
1123
1149
  // (gateChangedFiles defined). path.join for native normalizes a trailing
1124
1150
  // slash; the container form is a POSIX join under a known-absolute root.
1125
- const nativeAbs = gateChangedFiles &&
1126
- gateChangedFiles.map((rel) => path.join(projectDir, rel)).join("\n");
1127
- const containerAbs = gateChangedFiles &&
1128
- gateChangedFiles.map((rel) => `${CONTAINER_WORKDIR}/${rel}`).join("\n");
1151
+ const nativeAbs = gateChangedFiles
1152
+ ?.map((rel) => path.join(projectDir, rel))
1153
+ .join("\n");
1154
+ const containerAbs = gateChangedFiles
1155
+ ?.map((rel) => `${CONTAINER_WORKDIR}/${rel}`)
1156
+ .join("\n");
1129
1157
  const nativeEnv = {
1130
1158
  ...baseEnv,
1131
1159
  ...injected,
@@ -27,6 +27,10 @@ export function getDockerfileContent(stack) {
27
27
  switch (stack) {
28
28
  case "java-gradle":
29
29
  case "java-maven":
30
+ // Java is intentionally NOT digest-pinned: the JAVA_VERSION build
31
+ // arg lets the user pick a JDK version, so a per-version digest
32
+ // can't be hardcoded. The ci-local.sh/.ps1 heredocs leave it
33
+ // floating too, keeping the dockerfile-hash cache consistent.
30
34
  return [
31
35
  "ARG JAVA_VERSION=21",
32
36
  "FROM eclipse-temurin:${JAVA_VERSION}-jdk-noble",
@@ -38,7 +42,7 @@ export function getDockerfileContent(stack) {
38
42
  ].join("\n");
39
43
  case "node":
40
44
  return [
41
- "FROM node:22-slim",
45
+ "FROM node:22-slim@sha256:689c11043dad91472750cd824c97dd5e2318e9dd6f954e492fe7af0135d33ceb",
42
46
  "RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*",
43
47
  // Pin pnpm to major 10 to match ci.yml (pnpm/action-setup version:
44
48
  // 10) and the lockfileVersion 9.0 lockfile. Unpinned drifts to
@@ -51,7 +55,7 @@ export function getDockerfileContent(stack) {
51
55
  ].join("\n");
52
56
  case "python":
53
57
  return [
54
- "FROM python:3.12-slim",
58
+ "FROM python:3.12-slim@sha256:401f6e1a67dad31a1bd78e9ad22d0ee0a3b52154e6bd30e90be696bb6a3d7461",
55
59
  "RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*",
56
60
  "RUN pip install --no-cache-dir pytest ruff pylint poetry",
57
61
  "RUN useradd -m -s /bin/bash runner",
@@ -61,7 +65,7 @@ export function getDockerfileContent(stack) {
61
65
  ].join("\n");
62
66
  case "go":
63
67
  return [
64
- "FROM golang:1.23-bookworm",
68
+ "FROM golang:1.23-bookworm@sha256:167053a2bb901972bf2c1611f8f52c44d5fe7e762e5cab213708d82c421614db",
65
69
  "RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*",
66
70
  "RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 && mv /root/go/bin/golangci-lint /usr/local/bin/",
67
71
  "RUN useradd -m -s /bin/bash runner",
@@ -71,7 +75,7 @@ export function getDockerfileContent(stack) {
71
75
  ].join("\n");
72
76
  case "rust":
73
77
  return [
74
- "FROM rust:1.83-slim",
78
+ "FROM rust:1.83-slim@sha256:540c902e99c384163b688bbd8b5b8520e94e7731b27f7bd0eaa56ae1960627ab",
75
79
  "RUN apt-get update && apt-get install -y git pkg-config libssl-dev && rm -rf /var/lib/apt/lists/*",
76
80
  "RUN rustup component add clippy rustfmt",
77
81
  "RUN useradd -m -s /bin/bash runner",
@@ -81,7 +85,7 @@ export function getDockerfileContent(stack) {
81
85
  ].join("\n");
82
86
  default:
83
87
  return [
84
- "FROM ubuntu:24.04",
88
+ "FROM ubuntu:24.04@sha256:c4a8d5503dfb2a3eb8ab5f807da5bc69a85730fb49b5cfca2330194ebcc41c7b",
85
89
  "RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*",
86
90
  "RUN useradd -m -s /bin/bash runner",
87
91
  "USER runner",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javi-forge",
3
- "version": "1.21.2",
3
+ "version": "1.22.0",
4
4
  "description": "Project scaffolding and AI-ready CI bootstrap",
5
5
  "type": "module",
6
6
  "bin": {