build(gen): pin the reference packages, regenerate their answers from a clean npm ci
- commit
- a52e9b5cddd6dfccb870cf440148f6dddd27cd61
- author
- brice · · 2026-10-12 16:15 UTC
- committer
- brice · · 2026-10-12 16:17 UTC
- parent
- fa5b491
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
10 files · +172 -9
A gen/.gitignore +1 -0
| @@ -0,0 +1,1 @@ | |||
| 1 | + | node_modules/ | |
| @@ -0,0 +1,1 @@ | |||||
| 1 | + | node_modules/ | |||
A gen/json-hook.mjs +8 -0
| @@ -0,0 +1,8 @@ | |||
| 1 | + | // SPDX-License-Identifier: MIT | |
| 2 | + | ||
| 3 | + | export async function load(url, context, nextLoad) { | |
| 4 | + | if (url.endsWith(".json") && !context.importAttributes?.type) { | |
| 5 | + | return nextLoad(url, { ...context, importAttributes: { ...context.importAttributes, type: "json" } }); | |
| 6 | + | } | |
| 7 | + | return nextLoad(url, context); | |
| 8 | + | } | |
| @@ -0,0 +1,8 @@ | |||||
| 1 | + | // SPDX-License-Identifier: MIT | |||
| 2 | + | ||||
| 3 | + | export async function load(url, context, nextLoad) { | |||
| 4 | + | if (url.endsWith(".json") && !context.importAttributes?.type) { | |||
| 5 | + | return nextLoad(url, { ...context, importAttributes: { ...context.importAttributes, type: "json" } }); | |||
| 6 | + | } | |||
| 7 | + | return nextLoad(url, context); | |||
| 8 | + | } | |||
A gen/package-lock.json +65 -0 generated file: collapsed
A gen/package.json +13 -0
| @@ -0,0 +1,13 @@ | |||
| 1 | + | { | |
| 2 | + | "name": "ermite-actions-gen", | |
| 3 | + | "private": true, | |
| 4 | + | "description": "Pinned reference implementations that the generators in expr/gen, template/gen and workflow/gen run. Not shipped.", | |
| 5 | + | "license": "MIT", | |
| 6 | + | "type": "module", | |
| 7 | + | "dependencies": { | |
| 8 | + | "@actions/expressions": "0.3.61", | |
| 9 | + | "@actions/workflow-parser": "0.3.61", | |
| 10 | + | "cronstrue": "2.61.0", | |
| 11 | + | "yaml": "2.8.3" | |
| 12 | + | } | |
| 13 | + | } | |
| @@ -0,0 +1,13 @@ | |||||
| 1 | + | { | |||
| 2 | + | "name": "ermite-actions-gen", | |||
| 3 | + | "private": true, | |||
| 4 | + | "description": "Pinned reference implementations that the generators in expr/gen, template/gen and workflow/gen run. Not shipped.", | |||
| 5 | + | "license": "MIT", | |||
| 6 | + | "type": "module", | |||
| 7 | + | "dependencies": { | |||
| 8 | + | "@actions/expressions": "0.3.61", | |||
| 9 | + | "@actions/workflow-parser": "0.3.61", | |||
| 10 | + | "cronstrue": "2.61.0", | |||
| 11 | + | "yaml": "2.8.3" | |||
| 12 | + | } | |||
| 13 | + | } | |||
A gen/regen.sh +18 -0
| @@ -0,0 +1,18 @@ | |||
| 1 | + | #!/bin/sh | |
| 2 | + | # SPDX-License-Identifier: MIT | |
| 3 | + | # | |
| 4 | + | # Regenerates every file that is the answer of a reference implementation: | |
| 5 | + | # workflow/testdata/convert.json (@actions/workflow-parser) | |
| 6 | + | # template/testdata/scalars.json (yaml) | |
| 7 | + | # from the exact versions pinned in gen/package-lock.json, installed with | |
| 8 | + | # `npm ci`. Run from anywhere; `git diff` afterwards must be empty unless the | |
| 9 | + | # pins or the corpus changed. (expr/gen has its own generators, run the same | |
| 10 | + | # way with `--import ./gen/register.mjs` and the dist path of | |
| 11 | + | # gen/node_modules/@actions/expressions.) | |
| 12 | + | set -eu | |
| 13 | + | root=$(cd "$(dirname "$0")/.." && pwd) | |
| 14 | + | cd "$root/gen" | |
| 15 | + | npm ci --ignore-scripts --no-audit --no-fund | |
| 16 | + | cd "$root" | |
| 17 | + | node --import ./gen/register.mjs workflow/gen/convert.mjs > workflow/testdata/convert.json | |
| 18 | + | node --import ./gen/register.mjs template/gen/scalars.mjs > template/testdata/scalars.json | |
| @@ -0,0 +1,18 @@ | |||||
| 1 | + | #!/bin/sh | |||
| 2 | + | # SPDX-License-Identifier: MIT | |||
| 3 | + | # | |||
| 4 | + | # Regenerates every file that is the answer of a reference implementation: | |||
| 5 | + | # workflow/testdata/convert.json (@actions/workflow-parser) | |||
| 6 | + | # template/testdata/scalars.json (yaml) | |||
| 7 | + | # from the exact versions pinned in gen/package-lock.json, installed with | |||
| 8 | + | # `npm ci`. Run from anywhere; `git diff` afterwards must be empty unless the | |||
| 9 | + | # pins or the corpus changed. (expr/gen has its own generators, run the same | |||
| 10 | + | # way with `--import ./gen/register.mjs` and the dist path of | |||
| 11 | + | # gen/node_modules/@actions/expressions.) | |||
| 12 | + | set -eu | |||
| 13 | + | root=$(cd "$(dirname "$0")/.." && pwd) | |||
| 14 | + | cd "$root/gen" | |||
| 15 | + | npm ci --ignore-scripts --no-audit --no-fund | |||
| 16 | + | cd "$root" | |||
| 17 | + | node --import ./gen/register.mjs workflow/gen/convert.mjs > workflow/testdata/convert.json | |||
| 18 | + | node --import ./gen/register.mjs template/gen/scalars.mjs > template/testdata/scalars.json | |||
A gen/register.mjs +10 -0
| @@ -0,0 +1,10 @@ | |||
| 1 | + | // SPDX-License-Identifier: MIT | |
| 2 | + | // | |
| 3 | + | // Node 22+ refuses to import a .json file without `with { type: "json" }`, | |
| 4 | + | // which @actions/workflow-parser 0.3.61 does for workflow-v1.0.min.json. This | |
| 5 | + | // loader hook adds the attribute so that the package can run unmodified: | |
| 6 | + | // | |
| 7 | + | // node --import ./gen/register.mjs workflow/gen/convert.mjs | |
| 8 | + | import { register } from "node:module"; | |
| 9 | + | ||
| 10 | + | register("./json-hook.mjs", import.meta.url); | |
| @@ -0,0 +1,10 @@ | |||||
| 1 | + | // SPDX-License-Identifier: MIT | |||
| 2 | + | // | |||
| 3 | + | // Node 22+ refuses to import a .json file without `with { type: "json" }`, | |||
| 4 | + | // which @actions/workflow-parser 0.3.61 does for workflow-v1.0.min.json. This | |||
| 5 | + | // loader hook adds the attribute so that the package can run unmodified: | |||
| 6 | + | // | |||
| 7 | + | // node --import ./gen/register.mjs workflow/gen/convert.mjs | |||
| 8 | + | import { register } from "node:module"; | |||
| 9 | + | ||||
| 10 | + | register("./json-hook.mjs", import.meta.url); | |||
M template/PORTING.md +17 -0
| @@ -11,6 +11,19 @@ replays them (messages, line and column included). | |||
| 11 | 11 | The C# runner (`ObjectTemplating`) is what runs on github.com. It was not | |
| 12 | 12 | available. Nothing here has been checked against it. | |
| 13 | 13 | ||
| 14 | + | ## Reference versions and regeneration | |
| 15 | + | ||
| 16 | + | The answers in `../workflow/testdata/convert.json` and `testdata/scalars.json` | |
| 17 | + | come from the versions pinned in `../gen/package.json` and | |
| 18 | + | `../gen/package-lock.json`: `@actions/workflow-parser` 0.3.61, | |
| 19 | + | `@actions/expressions` 0.3.61, `yaml` 2.8.3, `cronstrue` 2.61.0 (only imported | |
| 20 | + | by the parser's cron description helper, which is not used here). Run | |
| 21 | + | `../gen/regen.sh`: it does an `npm ci` and rewrites both files; `git diff` | |
| 22 | + | must show nothing. The loader hook `../gen/register.mjs` adds the | |
| 23 | + | `with { type: "json" }` import attribute that Node 22+ requires and the | |
| 24 | + | parser omits, so the packages run unmodified. The last check, on a clean | |
| 25 | + | `npm ci`, gave identical files. | |
| 26 | + | ||
| 14 | 27 | ## Differences from the reference | |
| 15 | 28 | ||
| 16 | 29 | - **YAML parser.** The reference uses the JavaScript `yaml` library (YAML 1.2, | |
| @@ -38,6 +51,10 @@ available. Nothing here has been checked against it. | |||
| 38 | 51 | messages use too (checked on `multiline_*`, `expr_multi`). | |
| 39 | 52 | `BasicExpression.Source` is the value of the scalar, not the raw source text | |
| 40 | 53 | (so a block scalar's indentation is not in it). | |
| 54 | + | - **File size.** A document over `MaxFileBytes` (1 MiB) is refused before any | |
| 55 | + | parsing, with `file.yml: The file is too large: N bytes, the limit is M | |
| 56 | + | bytes` (our wording; the reference has no limit, GitHub has its own). | |
| 57 | + | TODO(verify with recording). | |
| 41 | 58 | - **Error limit.** `Context` keeps at most `MaxErrors` (1 000) errors. | |
| 42 | 59 | - **Limits on evaluation.** `MaxEvalDepth` (100) nested tokens; the result | |
| 43 | 60 | budget of package expr applies per expression. | |
| @@ -11,6 +11,19 @@ replays them (messages, line and column included). | |||||
| 11 | The C# runner (`ObjectTemplating`) is what runs on github.com. It was not | 11 | The C# runner (`ObjectTemplating`) is what runs on github.com. It was not | ||
| 12 | available. Nothing here has been checked against it. | 12 | available. Nothing here has been checked against it. | ||
| 13 | 13 | ||||
| 14 | + | ## Reference versions and regeneration | |||
| 15 | + | ||||
| 16 | + | The answers in `../workflow/testdata/convert.json` and `testdata/scalars.json` | |||
| 17 | + | come from the versions pinned in `../gen/package.json` and | |||
| 18 | + | `../gen/package-lock.json`: `@actions/workflow-parser` 0.3.61, | |||
| 19 | + | `@actions/expressions` 0.3.61, `yaml` 2.8.3, `cronstrue` 2.61.0 (only imported | |||
| 20 | + | by the parser's cron description helper, which is not used here). Run | |||
| 21 | + | `../gen/regen.sh`: it does an `npm ci` and rewrites both files; `git diff` | |||
| 22 | + | must show nothing. The loader hook `../gen/register.mjs` adds the | |||
| 23 | + | `with { type: "json" }` import attribute that Node 22+ requires and the | |||
| 24 | + | parser omits, so the packages run unmodified. The last check, on a clean | |||
| 25 | + | `npm ci`, gave identical files. | |||
| 26 | + | ||||
| 14 | ## Differences from the reference | 27 | ## Differences from the reference | ||
| 15 | 28 | ||||
| 16 | - **YAML parser.** The reference uses the JavaScript `yaml` library (YAML 1.2, | 29 | - **YAML parser.** The reference uses the JavaScript `yaml` library (YAML 1.2, | ||
| @@ -38,6 +51,10 @@ available. Nothing here has been checked against it. | |||||
| 38 | messages use too (checked on `multiline_*`, `expr_multi`). | 51 | messages use too (checked on `multiline_*`, `expr_multi`). | ||
| 39 | `BasicExpression.Source` is the value of the scalar, not the raw source text | 52 | `BasicExpression.Source` is the value of the scalar, not the raw source text | ||
| 40 | (so a block scalar's indentation is not in it). | 53 | (so a block scalar's indentation is not in it). | ||
| 54 | + | - **File size.** A document over `MaxFileBytes` (1 MiB) is refused before any | |||
| 55 | + | parsing, with `file.yml: The file is too large: N bytes, the limit is M | |||
| 56 | + | bytes` (our wording; the reference has no limit, GitHub has its own). | |||
| 57 | + | TODO(verify with recording). | |||
| 41 | - **Error limit.** `Context` keeps at most `MaxErrors` (1 000) errors. | 58 | - **Error limit.** `Context` keeps at most `MaxErrors` (1 000) errors. | ||
| 42 | - **Limits on evaluation.** `MaxEvalDepth` (100) nested tokens; the result | 59 | - **Limits on evaluation.** `MaxEvalDepth` (100) nested tokens; the result | ||
| 43 | budget of package expr applies per expression. | 60 | budget of package expr applies per expression. | ||
M template/gen/scalars.mjs +5 -2
| @@ -3,9 +3,12 @@ | |||
| 3 | 3 | // Generates testdata/scalars.json: how the JavaScript `yaml` library (2.x, the | |
| 4 | 4 | // one @actions/workflow-parser uses) types plain scalars. | |
| 5 | 5 | // | |
| 6 | - | // node gen/scalars.mjs > testdata/scalars.json | |
| 6 | + | // gen/regen.sh | |
| 7 | 7 | ||
| 8 | - | import {parseDocument} from "yaml"; | |
| 8 | + | import { createRequire } from "node:module"; | |
| 9 | + | ||
| 10 | + | // The yaml package pinned in gen/package.json. | |
| 11 | + | const { parseDocument } = createRequire(new URL("../../gen/package.json", import.meta.url))("yaml"); | |
| 9 | 12 | const vals = ["yes","no","on","off","y","n","~","null","Null","NULL","","true","True","TRUE","tRUE","false","0","-0","+1","017","0o17","0O17","0x1F","0X1f","0b11","1_000","1:30","1e3","1E3","1.","1.5","-.5",".5","+.5",".inf","-.inf",".Inf",".INF","+.inf",".nan",".NaN",".NAN","-.nan","1e","e1","0x","0xg","12abc","2001-01-01","1.5e+3","0.","00","08","-017","+0x1F","-0x1F","1,000","Infinity","NaN","inf","=","<<","!!str 1","!!int 5"]; | |
| 10 | 13 | const out = {}; | |
| 11 | 14 | for (const v of vals) { | |
| @@ -3,9 +3,12 @@ | |||||
| 3 | // Generates testdata/scalars.json: how the JavaScript `yaml` library (2.x, the | 3 | // Generates testdata/scalars.json: how the JavaScript `yaml` library (2.x, the | ||
| 4 | // one @actions/workflow-parser uses) types plain scalars. | 4 | // one @actions/workflow-parser uses) types plain scalars. | ||
| 5 | // | 5 | // | ||
| 6 | - | // node gen/scalars.mjs > testdata/scalars.json | 6 | + | // gen/regen.sh |
| 7 | 7 | ||||
| 8 | - | import {parseDocument} from "yaml"; | 8 | + | import { createRequire } from "node:module"; |
| 9 | + | ||||
| 10 | + | // The yaml package pinned in gen/package.json. | |||
| 11 | + | const { parseDocument } = createRequire(new URL("../../gen/package.json", import.meta.url))("yaml"); | |||
| 9 | const vals = ["yes","no","on","off","y","n","~","null","Null","NULL","","true","True","TRUE","tRUE","false","0","-0","+1","017","0o17","0O17","0x1F","0X1f","0b11","1_000","1:30","1e3","1E3","1.","1.5","-.5",".5","+.5",".inf","-.inf",".Inf",".INF","+.inf",".nan",".NaN",".NAN","-.nan","1e","e1","0x","0xg","12abc","2001-01-01","1.5e+3","0.","00","08","-017","+0x1F","-0x1F","1,000","Infinity","NaN","inf","=","<<","!!str 1","!!int 5"]; | 12 | const vals = ["yes","no","on","off","y","n","~","null","Null","NULL","","true","True","TRUE","tRUE","false","0","-0","+1","017","0o17","0O17","0x1F","0X1f","0b11","1_000","1:30","1e3","1E3","1.","1.5","-.5",".5","+.5",".inf","-.inf",".Inf",".INF","+.inf",".nan",".NaN",".NAN","-.nan","1e","e1","0x","0xg","12abc","2001-01-01","1.5e+3","0.","00","08","-017","+0x1F","-0x1F","1,000","Infinity","NaN","inf","=","<<","!!str 1","!!int 5"]; | ||
| 10 | const out = {}; | 13 | const out = {}; | ||
| 11 | for (const v of vals) { | 14 | for (const v of vals) { | ||
M workflow/PORTING.md +29 -2
| @@ -18,6 +18,20 @@ code. | |||
| 18 | 18 | accepts them; GitHub refuses the file. `Parse` reports | |
| 19 | 19 | `Event 'push' cannot use both 'branches' and 'branches-ignore'. Use only one | |
| 20 | 20 | of them.` (our wording, to replace with GitHub's). Applied to every event. | |
| 21 | + | - **A filter list made only of `!` patterns** (`branches: ['!main']`) is an | |
| 22 | + | error (`Event 'push' filter 'branches' has only patterns that start with | |
| 23 | + | '!'...`), and so is a pattern that does not compile. Both are ours; GitHub's | |
| 24 | + | texts are unknown. Applied to every event and every filter. | |
| 25 | + | - **Matrix exclude** with a key that is not a vector of the matrix is | |
| 26 | + | `Matrix exclude key '<k>' does not match any key within the matrix` | |
| 27 | + | (GitHub's text as remembered, not recorded). | |
| 28 | + | - **Limits that GitHub does not state**: the cross product of the vectors may | |
| 29 | + | not exceed `MaxMatrixProduct` (65 536) before exclusions, include and exclude | |
| 30 | + | have at most `MaxMatrixEntries` (256) entries each, and the context is | |
| 31 | + | checked every 1 024 combinations. They keep a hostile matrix from running | |
| 32 | + | for long; a legitimate one (at most 256 jobs) is far below them. The | |
| 33 | + | product limit also refuses a matrix GitHub would accept by excluding most | |
| 34 | + | of a huge product. | |
| 21 | 35 | - **Reusable workflows** are parsed (`uses`, `with`, `secrets`, `inherit`) but | |
| 22 | 36 | not followed, and the called workflow's inputs and secrets are not checked. | |
| 23 | 37 | - Unknown event types are reported by the schema (`Unexpected value 'x'`). | |
| @@ -50,12 +64,25 @@ code. | |||
| 50 | 64 | combinations after include, key case-insensitivity, value comparison | |
| 51 | 65 | (same kind; objects by containment), the error when all combinations are | |
| 52 | 66 | excluded (GitHub may fail the run differently), empty vector error. | |
| 67 | + | - [ ] A **null matrix value** is shown as an empty segment (`job (, 1)`); | |
| 68 | + | GitHub may skip it. | |
| 53 | 69 | - [ ] **Job display names** (`MatrixCombo.DisplayName`, `Job.DisplayName`): | |
| 54 | 70 | `name (v1, v2)` listing every scalar value of the combination in key | |
| 55 | - | order, then keys added by include; a name that refers to `matrix.` is | |
| 56 | - | used as is. Booleans/numbers/null are shown with `CoerceString`. | |
| 71 | + | order, then keys added by include; a name that reads the `matrix` | |
| 72 | + | context (found in the expression's syntax tree, not by searching the | |
| 73 | + | text) is used as is. Booleans/numbers/null are shown with `CoerceString`. | |
| 57 | 74 | - [ ] **`strategy` context** (`Strategy.Context`): `fail-fast`, `job-index`, | |
| 58 | 75 | `job-total`, `max-parallel` (the job count when unlimited). | |
| 59 | 76 | - [ ] `fail-fast` and `max-parallel` accept strings (`"false"`, `"2"`) after | |
| 60 | 77 | evaluation; `max-parallel` must be a whole number ≥ 1. | |
| 61 | 78 | - [ ] The 1 000-commit and 300-file limits themselves are the caller's. | |
| 79 | + | ||
| 80 | + | ## New in the second pass | |
| 81 | + | ||
| 82 | + | - `Job.EvaluateRunsOn`, `Job.EvaluateIf`, `Step.EvaluateIf` and | |
| 83 | + | `Workflow.JobLevels` are conveniences for the planner and are not in the | |
| 84 | + | reference. `EvaluateRunsOn` applies the reference's runs-on checks to the | |
| 85 | + | evaluated value (labels must be strings; group names as in the converter). | |
| 86 | + | `JobLevels` is a layering of `needs` by depth, file order inside a level. | |
| 87 | + | - The reference versions and the regeneration of its answers are in | |
| 88 | + | `../template/PORTING.md`. | |
| @@ -18,6 +18,20 @@ code. | |||||
| 18 | accepts them; GitHub refuses the file. `Parse` reports | 18 | accepts them; GitHub refuses the file. `Parse` reports | ||
| 19 | `Event 'push' cannot use both 'branches' and 'branches-ignore'. Use only one | 19 | `Event 'push' cannot use both 'branches' and 'branches-ignore'. Use only one | ||
| 20 | of them.` (our wording, to replace with GitHub's). Applied to every event. | 20 | of them.` (our wording, to replace with GitHub's). Applied to every event. | ||
| 21 | + | - **A filter list made only of `!` patterns** (`branches: ['!main']`) is an | |||
| 22 | + | error (`Event 'push' filter 'branches' has only patterns that start with | |||
| 23 | + | '!'...`), and so is a pattern that does not compile. Both are ours; GitHub's | |||
| 24 | + | texts are unknown. Applied to every event and every filter. | |||
| 25 | + | - **Matrix exclude** with a key that is not a vector of the matrix is | |||
| 26 | + | `Matrix exclude key '<k>' does not match any key within the matrix` | |||
| 27 | + | (GitHub's text as remembered, not recorded). | |||
| 28 | + | - **Limits that GitHub does not state**: the cross product of the vectors may | |||
| 29 | + | not exceed `MaxMatrixProduct` (65 536) before exclusions, include and exclude | |||
| 30 | + | have at most `MaxMatrixEntries` (256) entries each, and the context is | |||
| 31 | + | checked every 1 024 combinations. They keep a hostile matrix from running | |||
| 32 | + | for long; a legitimate one (at most 256 jobs) is far below them. The | |||
| 33 | + | product limit also refuses a matrix GitHub would accept by excluding most | |||
| 34 | + | of a huge product. | |||
| 21 | - **Reusable workflows** are parsed (`uses`, `with`, `secrets`, `inherit`) but | 35 | - **Reusable workflows** are parsed (`uses`, `with`, `secrets`, `inherit`) but | ||
| 22 | not followed, and the called workflow's inputs and secrets are not checked. | 36 | not followed, and the called workflow's inputs and secrets are not checked. | ||
| 23 | - Unknown event types are reported by the schema (`Unexpected value 'x'`). | 37 | - Unknown event types are reported by the schema (`Unexpected value 'x'`). | ||
| @@ -50,12 +64,25 @@ code. | |||||
| 50 | combinations after include, key case-insensitivity, value comparison | 64 | combinations after include, key case-insensitivity, value comparison | ||
| 51 | (same kind; objects by containment), the error when all combinations are | 65 | (same kind; objects by containment), the error when all combinations are | ||
| 52 | excluded (GitHub may fail the run differently), empty vector error. | 66 | excluded (GitHub may fail the run differently), empty vector error. | ||
| 67 | + | - [ ] A **null matrix value** is shown as an empty segment (`job (, 1)`); | |||
| 68 | + | GitHub may skip it. | |||
| 53 | - [ ] **Job display names** (`MatrixCombo.DisplayName`, `Job.DisplayName`): | 69 | - [ ] **Job display names** (`MatrixCombo.DisplayName`, `Job.DisplayName`): | ||
| 54 | `name (v1, v2)` listing every scalar value of the combination in key | 70 | `name (v1, v2)` listing every scalar value of the combination in key | ||
| 55 | - | order, then keys added by include; a name that refers to `matrix.` is | 71 | + | order, then keys added by include; a name that reads the `matrix` |
| 56 | - | used as is. Booleans/numbers/null are shown with `CoerceString`. | 72 | + | context (found in the expression's syntax tree, not by searching the |
| 73 | + | text) is used as is. Booleans/numbers/null are shown with `CoerceString`. | |||
| 57 | - [ ] **`strategy` context** (`Strategy.Context`): `fail-fast`, `job-index`, | 74 | - [ ] **`strategy` context** (`Strategy.Context`): `fail-fast`, `job-index`, | ||
| 58 | `job-total`, `max-parallel` (the job count when unlimited). | 75 | `job-total`, `max-parallel` (the job count when unlimited). | ||
| 59 | - [ ] `fail-fast` and `max-parallel` accept strings (`"false"`, `"2"`) after | 76 | - [ ] `fail-fast` and `max-parallel` accept strings (`"false"`, `"2"`) after | ||
| 60 | evaluation; `max-parallel` must be a whole number ≥ 1. | 77 | evaluation; `max-parallel` must be a whole number ≥ 1. | ||
| 61 | - [ ] The 1 000-commit and 300-file limits themselves are the caller's. | 78 | - [ ] The 1 000-commit and 300-file limits themselves are the caller's. | ||
| 79 | + | ||||
| 80 | + | ## New in the second pass | |||
| 81 | + | ||||
| 82 | + | - `Job.EvaluateRunsOn`, `Job.EvaluateIf`, `Step.EvaluateIf` and | |||
| 83 | + | `Workflow.JobLevels` are conveniences for the planner and are not in the | |||
| 84 | + | reference. `EvaluateRunsOn` applies the reference's runs-on checks to the | |||
| 85 | + | evaluated value (labels must be strings; group names as in the converter). | |||
| 86 | + | `JobLevels` is a layering of `needs` by depth, file order inside a level. | |||
| 87 | + | - The reference versions and the regeneration of its answers are in | |||
| 88 | + | `../template/PORTING.md`. | |||
M workflow/gen/convert.mjs +6 -5
| @@ -4,17 +4,18 @@ | |||
| 4 | 4 | // the errors and the model summary that @actions/workflow-parser 0.3.61 (MIT, | |
| 5 | 5 | // GitHub) produces. convert_test.go replays the files and compares. | |
| 6 | 6 | // | |
| 7 | - | // node gen/convert.mjs /path/to/@actions/workflow-parser/dist > testdata/convert.json | |
| 7 | + | // gen/regen.sh | |
| 8 | 8 | // | |
| 9 | - | // The package imports "yaml" and "@actions/expressions"; the JSON import of the | |
| 10 | - | // schema needs `with { type: "json" }` in dist/workflows/workflow-schema.js on | |
| 11 | - | // recent Node versions. | |
| 9 | + | // which installs the versions pinned in gen/package-lock.json and runs this | |
| 10 | + | // script with the loader of gen/register.mjs (the package imports its JSON | |
| 11 | + | // schema without the import attribute recent Node versions require). A dist | |
| 12 | + | // path may be given as the first argument. | |
| 12 | 13 | ||
| 13 | 14 | import { pathToFileURL } from "node:url"; | |
| 14 | 15 | import path from "node:path"; | |
| 15 | 16 | import fs from "node:fs"; | |
| 16 | 17 | ||
| 17 | - | const dist = path.resolve(process.argv[2]); | |
| 18 | + | const dist = path.resolve(process.argv[2] ?? new URL("../../gen/node_modules/@actions/workflow-parser/dist", import.meta.url).pathname); | |
| 18 | 19 | const imp = p => import(pathToFileURL(path.join(dist, p)).href); | |
| 19 | 20 | const { parseWorkflow } = await imp("workflows/workflow-parser.js"); | |
| 20 | 21 | const { NoOperationTraceWriter } = await imp("templates/trace-writer.js"); | |
| @@ -4,17 +4,18 @@ | |||||
| 4 | // the errors and the model summary that @actions/workflow-parser 0.3.61 (MIT, | 4 | // the errors and the model summary that @actions/workflow-parser 0.3.61 (MIT, | ||
| 5 | // GitHub) produces. convert_test.go replays the files and compares. | 5 | // GitHub) produces. convert_test.go replays the files and compares. | ||
| 6 | // | 6 | // | ||
| 7 | - | // node gen/convert.mjs /path/to/@actions/workflow-parser/dist > testdata/convert.json | 7 | + | // gen/regen.sh |
| 8 | // | 8 | // | ||
| 9 | - | // The package imports "yaml" and "@actions/expressions"; the JSON import of the | 9 | + | // which installs the versions pinned in gen/package-lock.json and runs this |
| 10 | - | // schema needs `with { type: "json" }` in dist/workflows/workflow-schema.js on | 10 | + | // script with the loader of gen/register.mjs (the package imports its JSON |
| 11 | - | // recent Node versions. | 11 | + | // schema without the import attribute recent Node versions require). A dist |
| 12 | + | // path may be given as the first argument. | |||
| 12 | 13 | ||||
| 13 | import { pathToFileURL } from "node:url"; | 14 | import { pathToFileURL } from "node:url"; | ||
| 14 | import path from "node:path"; | 15 | import path from "node:path"; | ||
| 15 | import fs from "node:fs"; | 16 | import fs from "node:fs"; | ||
| 16 | 17 | ||||
| 17 | - | const dist = path.resolve(process.argv[2]); | 18 | + | const dist = path.resolve(process.argv[2] ?? new URL("../../gen/node_modules/@actions/workflow-parser/dist", import.meta.url).pathname); |
| 18 | const imp = p => import(pathToFileURL(path.join(dist, p)).href); | 19 | const imp = p => import(pathToFileURL(path.join(dist, p)).href); | ||
| 19 | const { parseWorkflow } = await imp("workflows/workflow-parser.js"); | 20 | const { parseWorkflow } = await imp("workflows/workflow-parser.js"); | ||
| 20 | const { NoOperationTraceWriter } = await imp("templates/trace-writer.js"); | 21 | const { NoOperationTraceWriter } = await imp("templates/trace-writer.js"); | ||