From 4faa096820317526d1c960265b8c7e2908a3f7b6 Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 4 Sep 2025 15:25:36 +0000 Subject: [PATCH] Add support for new `snapshot` keyword and object into workflow parser --- workflow-parser/src/model/converter/job.ts | 9 ++- .../src/model/workflow-template.ts | 1 + workflow-parser/src/workflow-v1.0.json | 56 +++++++++++++++++- .../testdata/reader/job-snapshot-mapping.yml | 57 +++++++++++++++++++ .../testdata/reader/job-snapshot-simple.yml | 42 ++++++++++++++ 5 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 workflow-parser/testdata/reader/job-snapshot-mapping.yml create mode 100644 workflow-parser/testdata/reader/job-snapshot-simple.yml diff --git a/workflow-parser/src/model/converter/job.ts b/workflow-parser/src/model/converter/job.ts index 1886207..4a2100b 100644 --- a/workflow-parser/src/model/converter/job.ts +++ b/workflow-parser/src/model/converter/job.ts @@ -16,7 +16,7 @@ export function convertJob(context: TemplateContext, jobKey: StringToken, token: context.error(jobKey, error); } - let concurrency, container, env, environment, name, outputs, runsOn, services, strategy: TemplateToken | undefined; + let concurrency, container, env, environment, name, outputs, runsOn, services, strategy, snapshot: TemplateToken | undefined; let needs: StringToken[] | undefined = undefined; let steps: Step[] = []; let workflowJobRef: StringToken | undefined; @@ -86,6 +86,10 @@ export function convertJob(context: TemplateContext, jobKey: StringToken, token: services = item.value; break; + case "snapshot": + snapshot = item.value; + break; + case "steps": steps = convertSteps(context, item.value); break; @@ -147,7 +151,8 @@ export function convertJob(context: TemplateContext, jobKey: StringToken, token: container, services, outputs, - steps + steps, + snapshot }; } } diff --git a/workflow-parser/src/model/workflow-template.ts b/workflow-parser/src/model/workflow-template.ts index 679da4f..ebe10ac 100644 --- a/workflow-parser/src/model/workflow-template.ts +++ b/workflow-parser/src/model/workflow-template.ts @@ -41,6 +41,7 @@ export type BaseJob = { concurrency?: TemplateToken; strategy?: TemplateToken; outputs?: MappingToken; + snapshot?: TemplateToken; }; // `job-factory` in the schema diff --git a/workflow-parser/src/workflow-v1.0.json b/workflow-parser/src/workflow-v1.0.json index 5e24de2..09febda 100644 --- a/workflow-parser/src/workflow-v1.0.json +++ b/workflow-parser/src/workflow-v1.0.json @@ -1710,7 +1710,8 @@ "concurrency": "job-concurrency", "outputs": "job-outputs", "defaults": "job-defaults", - "steps": "steps" + "steps": "steps", + "snapshot": "snapshot" } } }, @@ -1732,7 +1733,8 @@ "if": "job-if", "permissions": "permissions", "concurrency": "job-concurrency", - "strategy": "strategy" + "strategy": "strategy", + "snapshot": "snapshot" } } }, @@ -1826,6 +1828,56 @@ } } }, + "snapshot": { + "description": "Use `snapshot` to generate a custom image from this job", + "one-of": [ + "string", + "snapshot-mapping" + ] + }, + "snapshot-mapping": { + "mapping": { + "properties": { + "if": "snapshot-if", + "image-name": { + "type": "non-empty-string", + "required": true, + "description": "The image name." + }, + "version": { + "type": "string", + "description": "The major version to publish the snapshot as, use * to auto-increment minor version" + }, + "tags": { + "type": "sequence-of-non-empty-string", + "description": "An array of tags to apply to the snapshot." + } + } + } + }, + "snapshot-if": { + "description": "You can use the `if` conditional to prevent a snapshot from being created unless a condition is met. You can use any supported context and expression to create a conditional.", + "context": [ + "github", + "inputs", + "vars", + "needs", + "strategy", + "matrix", + "steps", + "job", + "runner", + "env", + "always(0,0)", + "failure(0,0)", + "cancelled(0,0)", + "success(0,0)", + "hashFiles(1,255)" + ], + "string": { + "is-expression": true + } + }, "matrix": { "description": "Use `matrix` to define a matrix of different job configurations. Within your matrix, define one or more variables followed by an array of values.", "mapping": { diff --git a/workflow-parser/testdata/reader/job-snapshot-mapping.yml b/workflow-parser/testdata/reader/job-snapshot-mapping.yml new file mode 100644 index 0000000..9947e60 --- /dev/null +++ b/workflow-parser/testdata/reader/job-snapshot-mapping.yml @@ -0,0 +1,57 @@ +include-source: false # Drop file/line/col from output +--- +on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + - run: echo hi + snapshot: + image-name: custom-image + version: 1.* + if: ${{ always() }} +--- +{ + "jobs": [ + { + "type": "job", + "id": "build", + "name": "build", + "if": { + "type": 3, + "expr": "success()" + }, + "runs-on": "ubuntu-latest", + "steps": [ + { + "id": "__run", + "if": { + "type": 3, + "expr": "success()" + }, + "run": "echo hi" + } + ], + "snapshot": { + "type": 2, + "map": [ + { + "Key": "image-name", + "Value": "custom-image" + }, + { + "Key": "version", + "Value": "1.*" + }, + { + "Key": "if", + "Value": { + "type": 3, + "expr": "always()" + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/workflow-parser/testdata/reader/job-snapshot-simple.yml b/workflow-parser/testdata/reader/job-snapshot-simple.yml new file mode 100644 index 0000000..b009a09 --- /dev/null +++ b/workflow-parser/testdata/reader/job-snapshot-simple.yml @@ -0,0 +1,42 @@ +include-source: false # Drop file/line/col from output +--- +# on: push +# jobs: +# job1: +# runs-on: windows-2019 +# snapshot: custom-image +# steps: +# - run: echo 1 +on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + - run: echo hi + snapshot: custom-image +--- +{ + "jobs": [ + { + "type": "job", + "id": "build", + "name": "build", + "if": { + "type": 3, + "expr": "success()" + }, + "runs-on": "ubuntu-latest", + "steps": [ + { + "id": "__run", + "if": { + "type": 3, + "expr": "success()" + }, + "run": "echo hi" + } + ], + "snapshot": "custom-image" + } + ] +} \ No newline at end of file