@intentius/chant-lexicon-docker 0.124.20 → 0.124.22

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.
Files changed (106) hide show
  1. package/dist/codegen/docs.d.ts.map +1 -1
  2. package/dist/codegen/generate.d.ts.map +1 -1
  3. package/dist/dockerfile-order.d.ts +13 -0
  4. package/dist/dockerfile-order.d.ts.map +1 -0
  5. package/dist/generated/index.d.ts +121 -0
  6. package/dist/generated/index.d.ts.map +1 -1
  7. package/dist/import/adapter.d.ts.map +1 -1
  8. package/dist/import/parser.d.ts +23 -0
  9. package/dist/import/parser.d.ts.map +1 -1
  10. package/dist/integrity.json +17 -8
  11. package/dist/lint/audit-catalog.d.ts.map +1 -1
  12. package/dist/lint/audit-lineage.d.ts.map +1 -1
  13. package/dist/lint/post-synth/add-url-checksum.d.ts +9 -0
  14. package/dist/lint/post-synth/add-url-checksum.d.ts.map +1 -0
  15. package/dist/lint/post-synth/apt-update-alone.d.ts +10 -0
  16. package/dist/lint/post-synth/apt-update-alone.d.ts.map +1 -0
  17. package/dist/lint/post-synth/cache-busting-copy.d.ts +11 -0
  18. package/dist/lint/post-synth/cache-busting-copy.d.ts.map +1 -0
  19. package/dist/lint/post-synth/copy-from-stage.d.ts +10 -0
  20. package/dist/lint/post-synth/copy-from-stage.d.ts.map +1 -0
  21. package/dist/lint/post-synth/docker-helpers.d.ts +35 -0
  22. package/dist/lint/post-synth/docker-helpers.d.ts.map +1 -1
  23. package/dist/lint/post-synth/index.d.ts.map +1 -1
  24. package/dist/lint/post-synth/no-root-user.d.ts +3 -2
  25. package/dist/lint/post-synth/no-root-user.d.ts.map +1 -1
  26. package/dist/lint/post-synth/relative-workdir.d.ts +10 -0
  27. package/dist/lint/post-synth/relative-workdir.d.ts.map +1 -0
  28. package/dist/lint/post-synth/repeated-cmd.d.ts +9 -0
  29. package/dist/lint/post-synth/repeated-cmd.d.ts.map +1 -0
  30. package/dist/lint/post-synth/root-after-user.d.ts +10 -0
  31. package/dist/lint/post-synth/root-after-user.d.ts.map +1 -0
  32. package/dist/lint/post-synth/unused-global-arg.d.ts +10 -0
  33. package/dist/lint/post-synth/unused-global-arg.d.ts.map +1 -0
  34. package/dist/lint/rules/index.d.ts +1 -0
  35. package/dist/lint/rules/index.d.ts.map +1 -1
  36. package/dist/lint/rules/per-kind-order.d.ts +15 -0
  37. package/dist/lint/rules/per-kind-order.d.ts.map +1 -0
  38. package/dist/manifest.json +1 -1
  39. package/dist/meta.json +6 -0
  40. package/dist/okf/index.md +10 -1
  41. package/dist/okf/rules/DKRD012.md +2 -2
  42. package/dist/okf/rules/DKRD013.md +11 -0
  43. package/dist/okf/rules/DKRD014.md +11 -0
  44. package/dist/okf/rules/DKRD015.md +11 -0
  45. package/dist/okf/rules/DKRD016.md +11 -0
  46. package/dist/okf/rules/DKRD017.md +11 -0
  47. package/dist/okf/rules/DKRD018.md +11 -0
  48. package/dist/okf/rules/DKRD019.md +11 -0
  49. package/dist/okf/rules/DKRD020.md +11 -0
  50. package/dist/okf/rules/DKRS002.md +15 -0
  51. package/dist/okf/types/Dockerfile.md +4 -1
  52. package/dist/plugin.d.ts.map +1 -1
  53. package/dist/rules/add-url-checksum.ts +38 -0
  54. package/dist/rules/apt-update-alone.ts +39 -0
  55. package/dist/rules/cache-busting-copy.ts +64 -0
  56. package/dist/rules/copy-from-stage.ts +54 -0
  57. package/dist/rules/docker-helpers.ts +80 -0
  58. package/dist/rules/no-root-user.ts +19 -17
  59. package/dist/rules/per-kind-order.ts +130 -0
  60. package/dist/rules/relative-workdir.ts +38 -0
  61. package/dist/rules/repeated-cmd.ts +35 -0
  62. package/dist/rules/root-after-user.ts +44 -0
  63. package/dist/rules/unused-global-arg.ts +38 -0
  64. package/dist/serializer.d.ts.map +1 -1
  65. package/dist/skills/chant-docker-patterns.md +91 -22
  66. package/dist/skills/chant-docker.md +42 -16
  67. package/dist/spec/parse-engine.d.ts +9 -0
  68. package/dist/spec/parse-engine.d.ts.map +1 -1
  69. package/dist/types/index.d.ts +81 -0
  70. package/package.json +3 -3
  71. package/src/codegen/__snapshots__/okf.test.ts.snap +155 -4
  72. package/src/codegen/docs.ts +14 -0
  73. package/src/codegen/generate.ts +77 -19
  74. package/src/dockerfile-order.ts +20 -0
  75. package/src/docs-examples.test.ts +141 -0
  76. package/src/generated/index.d.ts +81 -0
  77. package/src/generated/index.ts +117 -0
  78. package/src/generated/lexicon-docker.json +6 -0
  79. package/src/import/adapter.ts +8 -2
  80. package/src/import/generator.ts +49 -33
  81. package/src/import/parser.ts +82 -13
  82. package/src/import/roundtrip.test.ts +105 -0
  83. package/src/lint/audit-catalog.ts +9 -1
  84. package/src/lint/audit-lineage.ts +14 -0
  85. package/src/lint/post-synth/add-url-checksum.ts +38 -0
  86. package/src/lint/post-synth/apt-update-alone.ts +39 -0
  87. package/src/lint/post-synth/cache-busting-copy.ts +64 -0
  88. package/src/lint/post-synth/copy-from-stage.ts +54 -0
  89. package/src/lint/post-synth/docker-helpers.ts +80 -0
  90. package/src/lint/post-synth/index.ts +16 -0
  91. package/src/lint/post-synth/no-root-user.ts +19 -17
  92. package/src/lint/post-synth/post-synth.test.ts +149 -0
  93. package/src/lint/post-synth/relative-workdir.ts +38 -0
  94. package/src/lint/post-synth/repeated-cmd.ts +35 -0
  95. package/src/lint/post-synth/root-after-user.ts +44 -0
  96. package/src/lint/post-synth/unused-global-arg.ts +38 -0
  97. package/src/lint/rules/index.ts +1 -0
  98. package/src/lint/rules/per-kind-order.ts +130 -0
  99. package/src/lint/rules/rules.test.ts +88 -0
  100. package/src/plugin.test.ts +4 -0
  101. package/src/plugin.ts +2 -1
  102. package/src/serializer.test.ts +112 -0
  103. package/src/serializer.ts +58 -11
  104. package/src/skills/chant-docker-patterns.md +91 -22
  105. package/src/skills/chant-docker.md +42 -16
  106. package/src/spec/parse-engine.ts +17 -5
@@ -39,15 +39,21 @@ export const nfsdata = new Volume({ driver: "local", driver_opts: { type: "nfs",
39
39
 
40
40
  ## Dockerfile — generates Dockerfile.{name}:
41
41
 
42
+ Each stage is `from` plus `steps`. A step is an object with one key naming one instruction. Steps are written exactly in the order listed.
43
+
42
44
  ```typescript
43
- // Single-stage:
44
- export const builder = new Dockerfile({
45
+ // Single stage. Manifests before source, so the install layer is cached; root setup before USER.
46
+ export const server = new Dockerfile({
45
47
  from: "node:20-alpine",
46
- workdir: "/app",
47
- copy: ["package*.json ./"],
48
- run: ["npm ci --only=production"],
49
- user: "node",
50
- cmd: `["node", "dist/index.js"]`,
48
+ steps: [
49
+ { workdir: "/app" },
50
+ { copy: "package.json package-lock.json ./" },
51
+ { run: "npm ci --omit=dev" },
52
+ { copy: "src/ ./src/" },
53
+ { user: "node" },
54
+ { expose: 3000 },
55
+ { cmd: ["node", "src/index.js"] }, // a list is written in JSON exec form
56
+ ],
51
57
  });
52
58
 
53
59
  // Multi-stage build:
@@ -56,21 +62,36 @@ export const app = new Dockerfile({
56
62
  {
57
63
  from: "node:20-alpine",
58
64
  as: "build",
59
- workdir: "/app",
60
- copy: ["package*.json ./"],
61
- run: ["npm ci", "npm run build"],
65
+ steps: [
66
+ { workdir: "/app" },
67
+ { copy: "package.json package-lock.json ./" },
68
+ { run: "npm ci" },
69
+ { copy: ". ." },
70
+ { run: "npm run build" },
71
+ { run: "npm prune --omit=dev" },
72
+ ],
62
73
  },
63
74
  {
64
75
  from: "node:20-alpine",
65
- workdir: "/app",
66
- copy: ["--from=build /app/dist ./dist", "--from=build /app/node_modules ./node_modules"],
67
- user: "node",
68
- cmd: `["node", "dist/index.js"]`,
76
+ steps: [
77
+ { workdir: "/app" },
78
+ { copy: "--from=build /app/node_modules ./node_modules" },
79
+ { copy: "--from=build /app/dist ./dist" },
80
+ { user: "node" },
81
+ { cmd: ["node", "dist/index.js"] },
82
+ ],
69
83
  },
70
84
  ],
71
85
  });
72
86
  ```
73
87
 
88
+ Step keys: `arg`, `env`, `workdir`, `user`, `run`, `copy`, `add`, `expose`, `volume`, `label`, `entrypoint`, `cmd`, `healthcheck`, `shell`, `stopsignal`, `onbuild`. `from` and `as` are stage fields, and `globalArgs: ["NAME=value"]` writes `ARG` lines before the first `FROM`. `run`, `cmd`, `entrypoint` and `shell` take a string or a list (exec form); `expose` takes a number too.
89
+
90
+ Rules:
91
+ - Use `steps`. The older per-kind fields (`run: [...]`, `copy: [...]`, `user`) are written in a fixed order (ARG, ENV, WORKDIR, USER, RUN, COPY, ADD, EXPOSE, VOLUME, LABEL, ENTRYPOINT, CMD, HEALTHCHECK), not the order written, so every RUN lands before every COPY. Lint rule DKRS002 flags this, and `chant lint --fix` rewrites them as steps.
92
+ - A stage can't have both `steps` and per-kind fields, and a step can't name two instructions. Both are build errors.
93
+ - To share stages or steps between Dockerfiles in different modules, export a `const` stage (`DockerfileStage`) or step list (`DockerfileStep[]`) and import it. List the stage in `stages`, or spread the steps: `steps: [...nodeRuntime, { cmd: ["node", "dist/server.js"] }]`. This is chant's equivalent of an INCLUDE. Spreading a function call's result is a lint error (EVL004); put parameterized Dockerfiles in a `Composite`.
94
+
74
95
  ## Variable interpolation with env():
75
96
 
76
97
  ```typescript
@@ -112,7 +133,10 @@ export const api = new Service({
112
133
  },
113
134
  ports: ["8080:8080"],
114
135
  });
115
- export const builder = new Dockerfile({ from: "node:20-alpine", ... });
136
+ export const builder = new Dockerfile({
137
+ from: "node:20-alpine",
138
+ steps: [{ workdir: "/app" }, { copy: ". ." }, { run: "npm ci" }, { user: "node" }, { cmd: ["node", "index.js"] }],
139
+ });
116
140
  ```
117
141
 
118
142
  ## Output structure
@@ -126,4 +150,6 @@ export const builder = new Dockerfile({ from: "node:20-alpine", ... });
126
150
  - `DKRD001`: Post-synth: no `:latest` images in generated YAML
127
151
  - `DKRD002`: Post-synth: no unused named volumes
128
152
  - `DKRD003`: Post-synth: SSH port 22 not exposed externally
129
- - `DKRD010–012`: Dockerfile best practices (apt recommends, COPY vs ADD, USER)
153
+ - `DKRS002`: Dockerfile per-kind fields declared in an order the fixed order changes; use `steps`
154
+ - `DKRD010–012`: Dockerfile best practices (apt recommends, COPY vs ADD, final stage USER)
155
+ - `DKRD013–020`: order-aware Dockerfile checks: COPY . before a dependency install, root-only RUN after USER, repeated CMD/ENTRYPOINT, COPY --from an undefined stage, unused ARG before FROM, relative WORKDIR, ADD of a URL without --checksum, apt-get update in its own RUN
@@ -15,7 +15,16 @@ export interface DockerfileParseResult {
15
15
  export interface DockerfileInstruction {
16
16
  name: string;
17
17
  description?: string;
18
- multi?: boolean; // can appear multiple times
18
+ multi?: boolean; // can appear multiple times (as a per-kind field, an array)
19
+ /**
20
+ * Only available as a step (`{ shell: ... }` in `steps`), not as a per-kind
21
+ * field. The per-kind fields keep the set and fixed order they always had.
22
+ */
23
+ stepOnly?: boolean;
24
+ /** As a step, the value may be a JSON exec-form array as well as a string. */
25
+ execForm?: boolean;
26
+ /** As a step, the value may be a number as well as a string. */
27
+ numeric?: boolean;
19
28
  }
20
29
 
21
30
  /**
@@ -31,17 +40,20 @@ export function parseEngineApi(_data: Buffer): DockerfileParseResult {
31
40
  { name: "from", description: "Base image (required first instruction)" },
32
41
  { name: "arg", description: "Build-time argument", multi: true },
33
42
  { name: "env", description: "Environment variable", multi: true },
34
- { name: "run", description: "Run a command during build", multi: true },
43
+ { name: "run", description: "Run a command during build", multi: true, execForm: true },
35
44
  { name: "copy", description: "Copy files from build context", multi: true },
36
45
  { name: "add", description: "Add files (supports URLs and archives)", multi: true },
37
46
  { name: "workdir", description: "Set working directory" },
38
47
  { name: "user", description: "Set user for subsequent instructions" },
39
- { name: "expose", description: "Document exposed ports", multi: true },
48
+ { name: "expose", description: "Document exposed ports", multi: true, numeric: true },
40
49
  { name: "volume", description: "Create mount points", multi: true },
41
50
  { name: "label", description: "Add metadata labels", multi: true },
42
- { name: "entrypoint", description: "Set the entrypoint executable" },
43
- { name: "cmd", description: "Default command arguments" },
51
+ { name: "entrypoint", description: "Set the entrypoint executable", execForm: true },
52
+ { name: "cmd", description: "Default command arguments", execForm: true },
44
53
  { name: "healthcheck", description: "Health check instruction" },
54
+ { name: "shell", description: "Set the shell for shell-form commands (JSON array form)", stepOnly: true, execForm: true },
55
+ { name: "stopsignal", description: "Signal sent to stop the container", stepOnly: true },
56
+ { name: "onbuild", description: "Instruction to run when the image is used as a base", stepOnly: true },
45
57
  ],
46
58
  };
47
59
  }