Merge branch 'main' into elbrenn/expression-complete
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
dist
|
||||
*.md
|
||||
*.js
|
||||
*.json
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-workflow-parser",
|
||||
"version": "0.1.113",
|
||||
"version": "0.1.126",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"source": "./src/index.ts",
|
||||
@@ -40,7 +40,7 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "^0.1.113",
|
||||
"@github/actions-expressions": "^0.1.126",
|
||||
"cronstrue": "^2.21.0",
|
||||
"yaml": "^2.0.0-8"
|
||||
},
|
||||
|
||||
@@ -6,19 +6,16 @@ import {parseWorkflow} from "./workflows/workflow-parser";
|
||||
describe("Workflow Expression Parsing", () => {
|
||||
it("preserves original expressions when building format", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
run-name: Test \${{ github.event_name }} \${{ github.ref }}
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo 'hello'`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -44,20 +41,17 @@ jobs:
|
||||
|
||||
it("preserves original expressions when building format for multi-line strings", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo \${{ github.event_name }}
|
||||
echo 'hello' \${{ github.ref }}`
|
||||
}
|
||||
],
|
||||
echo 'hello' \${{github.ref }}`
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -81,19 +75,27 @@ jobs:
|
||||
}
|
||||
|
||||
expect(stepRun.originalExpressions).toHaveLength(2);
|
||||
expect(stepRun.originalExpressions!.map(x => [x.toDisplayString(), x.range])).toEqual([
|
||||
expect(stepRun.originalExpressions!.map(x => [x.toDisplayString(), x.range, x.expressionRange])).toEqual([
|
||||
[
|
||||
"${{ github.event_name }}",
|
||||
{
|
||||
start: {line: 7, column: 16},
|
||||
end: {line: 7, column: 40}
|
||||
},
|
||||
{
|
||||
start: {line: 7, column: 20},
|
||||
end: {line: 7, column: 37}
|
||||
}
|
||||
],
|
||||
[
|
||||
"${{ github.ref }}",
|
||||
{
|
||||
start: {line: 8, column: 24},
|
||||
end: {line: 8, column: 41}
|
||||
end: {line: 8, column: 40}
|
||||
},
|
||||
{
|
||||
start: {line: 8, column: 27},
|
||||
end: {line: 8, column: 37}
|
||||
}
|
||||
]
|
||||
]);
|
||||
@@ -101,11 +103,9 @@ jobs:
|
||||
|
||||
it("return errors and string token with preserved expressions for (multiple) expression errors", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -113,8 +113,7 @@ jobs:
|
||||
- run: |
|
||||
echo \${{ abc }}
|
||||
echo 'hello' \${{ gith }}`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -139,11 +138,9 @@ jobs:
|
||||
|
||||
it("reports all errors for multi-line expressions at the correct locations", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -151,8 +148,7 @@ jobs:
|
||||
- run: |
|
||||
echo \${{ fromJSON2('test') }}
|
||||
echo 'hello' \${{ toJSON2(inputs.test) }}`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -178,19 +174,16 @@ jobs:
|
||||
|
||||
it("parses isExpression strings into expression tokens", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
steps:
|
||||
- run: echo 'hello'`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
|
||||
@@ -5,13 +5,10 @@ import {parseWorkflow} from "./workflows/workflow-parser";
|
||||
describe("parseWorkflow", () => {
|
||||
it("parses valid workflow", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: "on: push\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - run: echo 'hello'"
|
||||
}
|
||||
],
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: "on: push\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - run: echo 'hello'"
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -20,13 +17,10 @@ describe("parseWorkflow", () => {
|
||||
|
||||
it("contains range for error", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: "on: push\njobs:\n build:\n steps:\n - run: echo 'hello'"
|
||||
}
|
||||
],
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: "on: push\njobs:\n build:\n steps:\n - run: echo 'hello'"
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -40,19 +34,16 @@ describe("parseWorkflow", () => {
|
||||
|
||||
it("error range for expression is constrained to scalar node", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: \${{ github.event = 12 }}
|
||||
run: echo 'hello'`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
@@ -71,14 +62,11 @@ jobs:
|
||||
|
||||
it("tokens contain descriptions", () => {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content:
|
||||
"on: push\nname: hello\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - run: echo 'hello'"
|
||||
}
|
||||
],
|
||||
{
|
||||
name: "test.yaml",
|
||||
content:
|
||||
"on: push\nname: hello\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - run: echo 'hello'"
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
|
||||
@@ -7,22 +7,19 @@ function serializeTemplate(template: unknown): unknown {
|
||||
}
|
||||
|
||||
describe("convertWorkflowTemplate", () => {
|
||||
it("converts workflow with one job", () => {
|
||||
it("converts workflow with one job", async () => {
|
||||
const result = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
const template = convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
|
||||
expect(serializeTemplate(template)).toEqual({
|
||||
events: {
|
||||
@@ -46,13 +43,11 @@ jobs:
|
||||
});
|
||||
});
|
||||
|
||||
it("converts workflow if expressions", () => {
|
||||
it("converts workflow if expressions", async () => {
|
||||
const result = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
if: \${{ true }}
|
||||
@@ -60,12 +55,11 @@ jobs:
|
||||
deploy:
|
||||
if: true
|
||||
runs-on: ubuntu-latest`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
const template = convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
|
||||
expect(serializeTemplate(template)).toEqual({
|
||||
events: {
|
||||
@@ -98,23 +92,20 @@ jobs:
|
||||
});
|
||||
});
|
||||
|
||||
it("converts workflow with empty needs", () => {
|
||||
it("converts workflow with empty needs", async () => {
|
||||
const result = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:
|
||||
needs: # comment to preserve whitespace in test
|
||||
runs-on: ubuntu-latest`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
const template = convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
|
||||
expect(serializeTemplate(template)).toEqual({
|
||||
errors: [
|
||||
@@ -143,13 +134,11 @@ jobs:
|
||||
});
|
||||
});
|
||||
|
||||
it("converts workflow with needs errors", () => {
|
||||
it("converts workflow with needs errors", async () => {
|
||||
const result = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
job1:
|
||||
needs: [unknown-job, job3]
|
||||
@@ -159,12 +148,11 @@ jobs:
|
||||
job3:
|
||||
needs: job1
|
||||
runs-on: ubuntu-latest`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
const template = convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
|
||||
expect(serializeTemplate(template)).toEqual({
|
||||
errors: [
|
||||
@@ -223,13 +211,11 @@ jobs:
|
||||
});
|
||||
});
|
||||
|
||||
it("converts workflow with invalid on", () => {
|
||||
it("converts workflow with invalid on", async () => {
|
||||
const result = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on:
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test:
|
||||
@@ -239,12 +225,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo hello`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
const template = convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
|
||||
expect(template.jobs).not.toBeUndefined();
|
||||
expect(template.jobs).toHaveLength(1);
|
||||
@@ -286,21 +271,18 @@ jobs:
|
||||
});
|
||||
});
|
||||
|
||||
it("converts workflow with invalid jobs", () => {
|
||||
it("converts workflow with invalid jobs", async () => {
|
||||
const result = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push
|
||||
jobs:
|
||||
build:`
|
||||
}
|
||||
],
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
const template = convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, ErrorPolicy.TryConversion);
|
||||
|
||||
expect(template.jobs).not.toBeUndefined();
|
||||
expect(template.jobs).toHaveLength(0);
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import {TemplateContext} from "../templates/template-context";
|
||||
import {TemplateToken, TemplateTokenError} from "../templates/tokens/template-token";
|
||||
import {FileProvider} from "../workflows/file-provider";
|
||||
import {parseFileReference} from "../workflows/file-reference";
|
||||
import {parseWorkflow} from "../workflows/workflow-parser";
|
||||
import {convertConcurrency} from "./converter/concurrency";
|
||||
import {convertOn} from "./converter/events";
|
||||
import {handleTemplateTokenErrors} from "./converter/handle-errors";
|
||||
import {convertJobs} from "./converter/jobs";
|
||||
import {convertReferencedWorkflow} from "./converter/referencedWorkflow";
|
||||
import {isReusableWorkflowJob} from "./type-guards";
|
||||
import {WorkflowTemplate} from "./workflow-template";
|
||||
|
||||
export enum ErrorPolicy {
|
||||
@@ -11,11 +16,35 @@ export enum ErrorPolicy {
|
||||
TryConversion
|
||||
}
|
||||
|
||||
export function convertWorkflowTemplate(
|
||||
export type WorkflowTemplateConverterOptions = {
|
||||
/**
|
||||
* The maximum depth of reusable workflows allowed in the workflow.
|
||||
* If this depth is exceeded, an error will be reported.
|
||||
* If {@link fetchReusableWorkflowDepth} is less than this value, the maximum depth
|
||||
* won't be enforced.
|
||||
* Default: 4
|
||||
*/
|
||||
maxReusableWorkflowDepth?: number;
|
||||
/**
|
||||
* The depth to fetch reusable workflows, up to {@link maxReusableWorkflowDepth}.
|
||||
* Currently only a fetch depth of 0 or 1 is supported.
|
||||
* Default: 0
|
||||
*/
|
||||
fetchReusableWorkflowDepth?: number;
|
||||
};
|
||||
|
||||
const defaultOptions: Required<WorkflowTemplateConverterOptions> = {
|
||||
maxReusableWorkflowDepth: 4,
|
||||
fetchReusableWorkflowDepth: 0
|
||||
};
|
||||
|
||||
export async function convertWorkflowTemplate(
|
||||
context: TemplateContext,
|
||||
root: TemplateToken,
|
||||
errorPolicy: ErrorPolicy = ErrorPolicy.ReturnErrorsOnly
|
||||
): WorkflowTemplate {
|
||||
errorPolicy: ErrorPolicy = ErrorPolicy.ReturnErrorsOnly,
|
||||
fileProvider?: FileProvider,
|
||||
options: WorkflowTemplateConverterOptions = defaultOptions
|
||||
): Promise<WorkflowTemplate> {
|
||||
const result = {} as WorkflowTemplate;
|
||||
|
||||
if (context.errors.getErrors().length > 0 && errorPolicy === ErrorPolicy.ReturnErrorsOnly) {
|
||||
@@ -25,6 +54,12 @@ export function convertWorkflowTemplate(
|
||||
return result;
|
||||
}
|
||||
|
||||
const opts = getOptionsWithDefaults(options);
|
||||
|
||||
if (fileProvider === undefined && opts.fetchReusableWorkflowDepth > 0) {
|
||||
context.error(root, new Error("A file provider is required to fetch reusable workflows"));
|
||||
}
|
||||
|
||||
try {
|
||||
const rootMapping = root.assertMapping("root");
|
||||
|
||||
@@ -49,6 +84,31 @@ export function convertWorkflowTemplate(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load referenced workflows
|
||||
for (const job of result.jobs || []) {
|
||||
if (isReusableWorkflowJob(job)) {
|
||||
if (opts.maxReusableWorkflowDepth === 0) {
|
||||
context.error(job.ref, new Error("Reusable workflows are not allowed"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (opts.fetchReusableWorkflowDepth === 0 || fileProvider === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const file = await fileProvider.getFileContent(parseFileReference(job.ref.value));
|
||||
const workflow = parseWorkflow(file, context);
|
||||
if (!workflow.value) {
|
||||
continue;
|
||||
}
|
||||
convertReferencedWorkflow(context, workflow.value, job);
|
||||
} catch {
|
||||
context.error(job.ref, new Error("Unable to find reusable workflow"));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof TemplateTokenError) {
|
||||
context.error(err.token, err);
|
||||
@@ -66,3 +126,16 @@ export function convertWorkflowTemplate(
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getOptionsWithDefaults(options: WorkflowTemplateConverterOptions): Required<WorkflowTemplateConverterOptions> {
|
||||
return {
|
||||
maxReusableWorkflowDepth:
|
||||
options.maxReusableWorkflowDepth !== undefined
|
||||
? options.maxReusableWorkflowDepth
|
||||
: defaultOptions.maxReusableWorkflowDepth,
|
||||
fetchReusableWorkflowDepth:
|
||||
options.fetchReusableWorkflowDepth !== undefined
|
||||
? options.fetchReusableWorkflowDepth
|
||||
: defaultOptions.fetchReusableWorkflowDepth
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import {TemplateContext} from "../../templates/template-context";
|
||||
import {StringToken, MappingToken, BasicExpressionToken, TemplateToken, ScalarToken} from "../../templates/tokens";
|
||||
import {isSequence, isString} from "../../templates/tokens/type-guards";
|
||||
import {WorkflowJob, Step} from "../workflow-template";
|
||||
import {convertConcurrency} from "./concurrency";
|
||||
import {convertToJobContainer, convertToJobServices} from "./container";
|
||||
import {handleTemplateTokenErrors} from "./handle-errors";
|
||||
import {IdBuilder} from "./id-builder";
|
||||
import {convertToActionsEnvironmentRef} from "./job/environment";
|
||||
import {convertRunsOn} from "./job/runs-on";
|
||||
import {convertSteps} from "./steps";
|
||||
|
||||
export function convertJob(context: TemplateContext, jobKey: StringToken, token: MappingToken): WorkflowJob {
|
||||
const error = new IdBuilder().tryAddKnownId(jobKey.value);
|
||||
if (error) {
|
||||
context.error(jobKey, error);
|
||||
}
|
||||
|
||||
let concurrency, container, env, environment, name, outputs, runsOn, services, strategy: TemplateToken | undefined;
|
||||
let needs: StringToken[] | undefined = undefined;
|
||||
let steps: Step[] = [];
|
||||
let workflowJobRef: StringToken | undefined;
|
||||
let workflowJobInputs: MappingToken | undefined;
|
||||
|
||||
for (const item of token) {
|
||||
const propertyName = item.key.assertString("job property name");
|
||||
switch (propertyName.value) {
|
||||
case "concurrency":
|
||||
handleTemplateTokenErrors(item.value, context, undefined, () => convertConcurrency(context, item.value));
|
||||
concurrency = item.value;
|
||||
break;
|
||||
|
||||
case "container":
|
||||
convertToJobContainer(context, item.value);
|
||||
container = item.value;
|
||||
break;
|
||||
|
||||
case "env":
|
||||
env = item.value.assertMapping("job env");
|
||||
break;
|
||||
|
||||
case "environment":
|
||||
handleTemplateTokenErrors(item.value, context, undefined, () =>
|
||||
convertToActionsEnvironmentRef(context, item.value)
|
||||
);
|
||||
environment = item.value;
|
||||
break;
|
||||
|
||||
case "name":
|
||||
name = item.value.assertScalar("job name");
|
||||
break;
|
||||
|
||||
case "needs": {
|
||||
needs = [];
|
||||
if (isString(item.value)) {
|
||||
const jobNeeds = item.value.assertString("job needs id");
|
||||
needs.push(jobNeeds);
|
||||
}
|
||||
|
||||
if (isSequence(item.value)) {
|
||||
for (const seqItem of item.value) {
|
||||
const jobNeeds = seqItem.assertString("job needs id");
|
||||
needs.push(jobNeeds);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "outputs":
|
||||
outputs = item.value.assertMapping("job outputs");
|
||||
break;
|
||||
|
||||
case "runs-on":
|
||||
handleTemplateTokenErrors(item.value, context, undefined, () => convertRunsOn(context, item.value));
|
||||
runsOn = item.value;
|
||||
break;
|
||||
|
||||
case "services":
|
||||
convertToJobServices(context, item.value);
|
||||
services = item.value;
|
||||
break;
|
||||
|
||||
case "steps":
|
||||
steps = convertSteps(context, item.value);
|
||||
break;
|
||||
|
||||
case "strategy":
|
||||
strategy = item.value;
|
||||
break;
|
||||
|
||||
case "uses":
|
||||
workflowJobRef = item.value.assertString("job uses value");
|
||||
break;
|
||||
|
||||
case "with":
|
||||
workflowJobInputs = item.value.assertMapping("uses-with value");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (workflowJobRef !== undefined) {
|
||||
return {
|
||||
type: "reusableWorkflowJob",
|
||||
id: jobKey,
|
||||
name: jobName(name, jobKey),
|
||||
needs: needs ?? [],
|
||||
if: new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, undefined),
|
||||
ref: workflowJobRef,
|
||||
"input-definitions": undefined,
|
||||
"input-values": workflowJobInputs,
|
||||
outputs: undefined,
|
||||
concurrency,
|
||||
strategy
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: "job",
|
||||
id: jobKey,
|
||||
name: jobName(name, jobKey),
|
||||
needs,
|
||||
if: new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, undefined),
|
||||
env,
|
||||
concurrency,
|
||||
environment,
|
||||
strategy,
|
||||
"runs-on": runsOn,
|
||||
container,
|
||||
services,
|
||||
outputs,
|
||||
steps
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function jobName(name: ScalarToken | undefined, jobKey: StringToken): ScalarToken {
|
||||
if (name === undefined) {
|
||||
return jobKey;
|
||||
}
|
||||
|
||||
if (isString(name) && name.value === "") {
|
||||
return jobKey;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import {TemplateContext} from "../../../templates/template-context";
|
||||
import {MappingToken, TemplateToken} from "../../../templates/tokens";
|
||||
import {ReusableWorkflowJob} from "../../workflow-template";
|
||||
|
||||
type TokenMap = Map<string, [key: string, value: TemplateToken]>;
|
||||
|
||||
export function convertWorkflowJobInputs(context: TemplateContext, job: ReusableWorkflowJob) {
|
||||
const inputDefinitions = createTokenMap(
|
||||
job["input-definitions"]?.assertMapping("workflow job input definitions"),
|
||||
"inputs"
|
||||
);
|
||||
|
||||
const inputValues = createTokenMap(job["input-values"]?.assertMapping("workflow job input values"), "with");
|
||||
|
||||
if (inputDefinitions !== undefined) {
|
||||
for (const [_, [name, value]] of inputDefinitions) {
|
||||
const inputSpec = createTokenMap(value.assertMapping(`input ${name}`), `input ${name} key`)!;
|
||||
|
||||
const inputTypeToken = inputSpec.get("type")?.[1];
|
||||
if (!inputTypeToken) {
|
||||
// This should be validated by the template reader per the schema
|
||||
continue;
|
||||
}
|
||||
|
||||
const inputSet = inputValues !== undefined && inputValues.has(name.toLowerCase());
|
||||
const required = inputSpec.get("required")?.[1].assertBoolean(`input ${name} required`).value;
|
||||
if (required && !inputSet) {
|
||||
context.error(job.ref, `Input ${name} is required, but not provided while calling.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inputValues !== undefined) {
|
||||
for (const [_, [name, value]] of inputValues) {
|
||||
if (!inputDefinitions?.has(name.toLowerCase())) {
|
||||
context.error(value, `Invalid input, ${name} is not defined in the referenced workflow.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createTokenMap(mapping: MappingToken | undefined, description: string): TokenMap | undefined {
|
||||
if (!mapping) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = new Map<string, [key: string, value: TemplateToken]>();
|
||||
for (const item of mapping) {
|
||||
const name = item.key.assertString(`${description} key`);
|
||||
result.set(name.value.toLowerCase(), [name.value, item.value]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import {TemplateContext} from "../../../templates/template-context";
|
||||
import {TemplateToken} from "../../../templates/tokens";
|
||||
import {isMapping, isString, isSequence} from "../../../templates/tokens/type-guards";
|
||||
|
||||
type RunsOn = {
|
||||
labels: Set<string>;
|
||||
group: string;
|
||||
};
|
||||
|
||||
export function convertRunsOn(context: TemplateContext, token: TemplateToken): RunsOn {
|
||||
const labels = convertRunsOnLabels(token);
|
||||
|
||||
if (!isMapping(token)) {
|
||||
return {
|
||||
labels,
|
||||
group: ""
|
||||
};
|
||||
}
|
||||
|
||||
let group = "";
|
||||
|
||||
for (const item of token) {
|
||||
const key = item.key.assertString("job runs-on property name");
|
||||
switch (key.value) {
|
||||
case "group": {
|
||||
if (item.value.isExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const groupName = item.value.assertString("job runs-on group name").value;
|
||||
const names = groupName.split("/");
|
||||
switch (names.length) {
|
||||
case 1: {
|
||||
group = groupName;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if (!["org", "organization", "ent", "enterprise"].includes(names[0])) {
|
||||
context.error(
|
||||
item.value,
|
||||
`Invalid runs-on group name '${groupName}. Please use 'organization/' or 'enterprise/' prefix to target a single runner group.'`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!names[1]) {
|
||||
context.error(item.value, `Invalid runs-on group name '${groupName}'.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
group = groupName;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
context.error(
|
||||
item.value,
|
||||
`Invalid runs-on group name '${groupName}. Please use 'organization/' or 'enterprise/' prefix to target a single runner group.'`
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "labels": {
|
||||
const mapLabels = convertRunsOnLabels(item.value);
|
||||
for (const label of mapLabels) {
|
||||
labels.add(label);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
labels,
|
||||
group
|
||||
};
|
||||
}
|
||||
|
||||
function convertRunsOnLabels(token: TemplateToken): Set<string> {
|
||||
const labels = new Set<string>();
|
||||
if (token.isExpression) {
|
||||
return labels;
|
||||
}
|
||||
|
||||
if (isString(token)) {
|
||||
labels.add(token.value);
|
||||
return labels;
|
||||
}
|
||||
|
||||
if (isSequence(token)) {
|
||||
for (const item of token) {
|
||||
if (item.isExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const label = item.assertString("job runs-on label sequence item");
|
||||
labels.add(label.value);
|
||||
}
|
||||
}
|
||||
|
||||
return labels;
|
||||
}
|
||||
@@ -1,23 +1,19 @@
|
||||
import {TemplateContext} from "../../templates/template-context";
|
||||
import {BasicExpressionToken, MappingToken, StringToken} from "../../templates/tokens";
|
||||
import {StringToken} from "../../templates/tokens";
|
||||
import {TemplateToken} from "../../templates/tokens/template-token";
|
||||
import {isMapping, isSequence, isString} from "../../templates/tokens/type-guards";
|
||||
import {Job} from "../workflow-template";
|
||||
import {convertConcurrency} from "./concurrency";
|
||||
import {convertToJobContainer, convertToJobServices} from "./container";
|
||||
import {isMapping} from "../../templates/tokens/type-guards";
|
||||
import {WorkflowJob} from "../workflow-template";
|
||||
import {handleTemplateTokenErrors} from "./handle-errors";
|
||||
import {IdBuilder} from "./id-builder";
|
||||
import {convertToActionsEnvironmentRef} from "./job/environment";
|
||||
import {convertSteps} from "./steps";
|
||||
import {convertJob} from "./job";
|
||||
|
||||
type nodeInfo = {
|
||||
name: string;
|
||||
needs: StringToken[];
|
||||
};
|
||||
|
||||
export function convertJobs(context: TemplateContext, token: TemplateToken): Job[] {
|
||||
export function convertJobs(context: TemplateContext, token: TemplateToken): WorkflowJob[] {
|
||||
if (isMapping(token)) {
|
||||
const result: Job[] = [];
|
||||
const result: WorkflowJob[] = [];
|
||||
const jobsWithSatisfiedNeeds: nodeInfo[] = [];
|
||||
const alljobsWithUnsatisfiedNeeds: nodeInfo[] = [];
|
||||
|
||||
@@ -53,7 +49,7 @@ export function convertJobs(context: TemplateContext, token: TemplateToken): Job
|
||||
function validateNeeds(
|
||||
token: TemplateToken,
|
||||
context: TemplateContext,
|
||||
result: Job[],
|
||||
result: WorkflowJob[],
|
||||
jobsWithSatisfiedNeeds: nodeInfo[],
|
||||
alljobsWithUnsatisfiedNeeds: nodeInfo[]
|
||||
) {
|
||||
@@ -101,199 +97,3 @@ function validateNeeds(
|
||||
}
|
||||
}
|
||||
|
||||
function convertJob(context: TemplateContext, jobKey: StringToken, token: MappingToken): Job {
|
||||
const error = new IdBuilder().tryAddKnownId(jobKey.value);
|
||||
if (error) {
|
||||
context.error(jobKey, error);
|
||||
}
|
||||
const result: Job = {
|
||||
type: "job",
|
||||
id: jobKey,
|
||||
name: undefined,
|
||||
needs: undefined,
|
||||
if: new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, "success()"),
|
||||
env: undefined,
|
||||
concurrency: undefined,
|
||||
environment: undefined,
|
||||
strategy: undefined,
|
||||
"runs-on": undefined,
|
||||
container: undefined,
|
||||
services: undefined,
|
||||
outputs: undefined,
|
||||
steps: []
|
||||
};
|
||||
|
||||
for (const item of token) {
|
||||
const propertyName = item.key.assertString("job property name");
|
||||
switch (propertyName.value) {
|
||||
case "concurrency":
|
||||
handleTemplateTokenErrors(item.value, context, undefined, () => convertConcurrency(context, item.value));
|
||||
result.concurrency = item.value;
|
||||
break;
|
||||
|
||||
case "container":
|
||||
// Do early validation, but don't convert
|
||||
convertToJobContainer(context, item.value);
|
||||
result.container = item.value;
|
||||
break;
|
||||
|
||||
case "env":
|
||||
result.env = item.value.assertMapping("job env");
|
||||
break;
|
||||
|
||||
case "environment":
|
||||
handleTemplateTokenErrors(item.value, context, undefined, () =>
|
||||
convertToActionsEnvironmentRef(context, item.value)
|
||||
);
|
||||
result.environment = item.value;
|
||||
break;
|
||||
|
||||
case "name":
|
||||
result.name = item.value.assertScalar("job name");
|
||||
break;
|
||||
|
||||
case "needs":
|
||||
result.needs = [];
|
||||
if (isString(item.value)) {
|
||||
const jobNeeds = item.value.assertString("job needs id");
|
||||
result.needs.push(jobNeeds);
|
||||
}
|
||||
|
||||
if (isSequence(item.value)) {
|
||||
for (const seqItem of item.value) {
|
||||
const jobNeeds = seqItem.assertString("job needs id");
|
||||
result.needs.push(jobNeeds);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "outputs":
|
||||
result.outputs = item.value.assertMapping("job outputs");
|
||||
break;
|
||||
|
||||
case "runs-on":
|
||||
handleTemplateTokenErrors(item.value, context, undefined, () => convertRunsOn(context, item.value));
|
||||
result["runs-on"] = item.value;
|
||||
break;
|
||||
|
||||
case "services":
|
||||
// Do early validation, but don't convert
|
||||
convertToJobServices(context, item.value);
|
||||
result.services = item.value;
|
||||
break;
|
||||
|
||||
case "steps":
|
||||
result.steps = convertSteps(context, item.value);
|
||||
break;
|
||||
|
||||
case "strategy":
|
||||
result.strategy = item.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.name) {
|
||||
result.name = result.id;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
type RunsOn = {
|
||||
labels: Set<string>;
|
||||
group: string;
|
||||
};
|
||||
|
||||
function convertRunsOn(context: TemplateContext, token: TemplateToken): RunsOn {
|
||||
const labels = convertRunsOnLabels(token);
|
||||
|
||||
if (!isMapping(token)) {
|
||||
return {
|
||||
labels,
|
||||
group: ""
|
||||
};
|
||||
}
|
||||
|
||||
let group = "";
|
||||
|
||||
for (const item of token) {
|
||||
const key = item.key.assertString("job runs-on property name");
|
||||
switch (key.value) {
|
||||
case "group": {
|
||||
if (item.value.isExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const groupName = item.value.assertString("job runs-on group name").value;
|
||||
const names = groupName.split("/");
|
||||
switch (names.length) {
|
||||
case 1: {
|
||||
group = groupName;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if (!["org", "organization", "ent", "enterprise"].includes(names[0])) {
|
||||
context.error(
|
||||
item.value,
|
||||
`Invalid runs-on group name '${groupName}. Please use 'organization/' or 'enterprise/' prefix to target a single runner group.'`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!names[1]) {
|
||||
context.error(item.value, `Invalid runs-on group name '${groupName}'.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
group = groupName;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
context.error(
|
||||
item.value,
|
||||
`Invalid runs-on group name '${groupName}. Please use 'organization/' or 'enterprise/' prefix to target a single runner group.'`
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "labels": {
|
||||
const mapLabels = convertRunsOnLabels(item.value);
|
||||
for (const label of mapLabels) {
|
||||
labels.add(label);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
labels,
|
||||
group
|
||||
};
|
||||
}
|
||||
|
||||
function convertRunsOnLabels(token: TemplateToken): Set<string> {
|
||||
const labels = new Set<string>();
|
||||
if (token.isExpression) {
|
||||
return labels;
|
||||
}
|
||||
|
||||
if (isString(token)) {
|
||||
labels.add(token.value);
|
||||
return labels;
|
||||
}
|
||||
|
||||
if (isSequence(token)) {
|
||||
for (const item of token) {
|
||||
if (item.isExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const label = item.assertString("job runs-on label sequence item");
|
||||
labels.add(label.value);
|
||||
}
|
||||
}
|
||||
|
||||
return labels;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import {TemplateContext} from "../../templates/template-context";
|
||||
import {TemplateToken} from "../../templates/tokens";
|
||||
import {TokenType} from "../../templates/tokens/types";
|
||||
import {ReusableWorkflowJob} from "../workflow-template";
|
||||
import {handleTemplateTokenErrors} from "./handle-errors";
|
||||
import {convertWorkflowJobInputs} from "./job/inputs";
|
||||
import {convertJobs} from "./jobs";
|
||||
|
||||
export function convertReferencedWorkflow(
|
||||
context: TemplateContext,
|
||||
referencedWorkflow: TemplateToken,
|
||||
job: ReusableWorkflowJob
|
||||
) {
|
||||
const mapping = referencedWorkflow.assertMapping("root");
|
||||
|
||||
// The language service doesn't currently handles on other documents,
|
||||
// So use the ref in the original workflow as the error location
|
||||
const tokenForErrors = job.ref;
|
||||
|
||||
for (const pair of mapping) {
|
||||
const key = pair.key.assertString("root key");
|
||||
switch (key.value) {
|
||||
case "on": {
|
||||
handleTemplateTokenErrors(tokenForErrors, context, undefined, () =>
|
||||
convertReferencedWorkflowOn(context, pair.value, job)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "jobs": {
|
||||
job.jobs = handleTemplateTokenErrors(tokenForErrors, context, [], () => convertJobs(context, pair.value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convertReferencedWorkflowOn(context: TemplateContext, on: TemplateToken, job: ReusableWorkflowJob) {
|
||||
const tokenForErrors = job.ref;
|
||||
switch (on.templateTokenType) {
|
||||
case TokenType.String: {
|
||||
const event = on.assertString("Reference workflow on value").value;
|
||||
if (event === "workflow_call") {
|
||||
handleTemplateTokenErrors(tokenForErrors, context, undefined, () => convertWorkflowJobInputs(context, job));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenType.Sequence: {
|
||||
const events = on.assertSequence("Reference workflow on value");
|
||||
for (const eventToken of events) {
|
||||
const event = eventToken.assertString(`Reference workflow on value ${eventToken}`).value;
|
||||
if (event === "workflow_call") {
|
||||
handleTemplateTokenErrors(tokenForErrors, context, undefined, () => convertWorkflowJobInputs(context, job));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenType.Mapping: {
|
||||
const eventMapping = on.assertMapping("Reference workflow on value");
|
||||
|
||||
for (const pair of eventMapping) {
|
||||
const event = pair.key.assertString(`Reference workflow on value ${pair.key}`).value;
|
||||
if (event !== "workflow_call") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pair.value.templateTokenType === TokenType.Null) {
|
||||
handleTemplateTokenErrors(tokenForErrors, context, undefined, () => convertWorkflowJobInputs(context, job));
|
||||
return;
|
||||
}
|
||||
|
||||
const definitions = pair.value.assertMapping(`Reference workflow on value ${pair.key}`);
|
||||
for (const definition of definitions) {
|
||||
const definitionKey = definition.key.assertString(`on-workflow_call-${definition.key}`).value;
|
||||
switch (definitionKey) {
|
||||
case "inputs":
|
||||
job["input-definitions"] = definition.value.assertMapping(`on-workflow_call-${definition.key}`);
|
||||
break;
|
||||
|
||||
case "outputs":
|
||||
job.outputs = definition.value.assertMapping(`on-workflow_call-${definition.key}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleTemplateTokenErrors(tokenForErrors, context, undefined, () => convertWorkflowJobInputs(context, job));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
context.error(tokenForErrors, "workflow_call key is not defined in the referenced workflow.");
|
||||
}
|
||||
@@ -52,7 +52,7 @@ function convertStep(context: TemplateContext, idBuilder: IdBuilder, step: Templ
|
||||
let uses: StringToken | undefined;
|
||||
let continueOnError: boolean | undefined;
|
||||
let env: MappingToken | undefined;
|
||||
const ifCondition = new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, "success()");
|
||||
const ifCondition = new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, undefined);
|
||||
for (const item of mapping) {
|
||||
const key = item.key.assertString("steps item key");
|
||||
switch (key.value) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {ActionStep, RunStep, Step} from "./workflow-template";
|
||||
import {ActionStep, Job, ReusableWorkflowJob, RunStep, Step, WorkflowJob} from "./workflow-template";
|
||||
|
||||
export function isRunStep(step: Step): step is RunStep {
|
||||
return (step as RunStep).run !== undefined;
|
||||
@@ -7,3 +7,11 @@ export function isRunStep(step: Step): step is RunStep {
|
||||
export function isActionStep(step: Step): step is ActionStep {
|
||||
return (step as ActionStep).uses !== undefined;
|
||||
}
|
||||
|
||||
export function isJob(job: WorkflowJob): job is Job {
|
||||
return job.type === "job";
|
||||
}
|
||||
|
||||
export function isReusableWorkflowJob(job: WorkflowJob): job is ReusableWorkflowJob {
|
||||
return job.type === "reusableWorkflowJob";
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
|
||||
export type WorkflowTemplate = {
|
||||
events: EventsConfig;
|
||||
jobs: Job[];
|
||||
jobs: WorkflowJob[];
|
||||
concurrency: TemplateToken;
|
||||
env: TemplateToken;
|
||||
|
||||
@@ -28,23 +28,41 @@ export type ActionsEnvironmentReference = {
|
||||
url?: TemplateToken;
|
||||
};
|
||||
|
||||
export type Job = {
|
||||
type: string;
|
||||
export type WorkflowJob = Job | ReusableWorkflowJob;
|
||||
|
||||
export type JobType = "job" | "reusableWorkflowJob";
|
||||
|
||||
export type BaseJob = {
|
||||
type: JobType;
|
||||
id: StringToken;
|
||||
name?: ScalarToken;
|
||||
needs?: StringToken[];
|
||||
if: BasicExpressionToken;
|
||||
env?: MappingToken;
|
||||
concurrency?: TemplateToken;
|
||||
environment?: TemplateToken;
|
||||
strategy?: TemplateToken;
|
||||
outputs?: MappingToken;
|
||||
};
|
||||
|
||||
// `job-factory` in the schema
|
||||
export type Job = BaseJob & {
|
||||
type: "job";
|
||||
env?: MappingToken;
|
||||
environment?: TemplateToken;
|
||||
"runs-on"?: TemplateToken;
|
||||
container?: TemplateToken;
|
||||
services?: TemplateToken;
|
||||
outputs?: MappingToken;
|
||||
steps: Step[];
|
||||
};
|
||||
|
||||
// `workflow-job` in the schema
|
||||
export type ReusableWorkflowJob = BaseJob & {
|
||||
type: "reusableWorkflowJob";
|
||||
ref: StringToken;
|
||||
"input-definitions"?: MappingToken;
|
||||
"input-values"?: MappingToken;
|
||||
jobs?: WorkflowJob[];
|
||||
};
|
||||
|
||||
export type Container = {
|
||||
image: StringToken;
|
||||
credentials?: Credential;
|
||||
|
||||
@@ -616,10 +616,10 @@ class TemplateReader {
|
||||
tr: TokenRange,
|
||||
rawExpression: string,
|
||||
allowedContext: string[],
|
||||
token: TemplateToken,
|
||||
token: StringToken,
|
||||
definitionInfo: DefinitionInfo | undefined
|
||||
): ExpressionToken | undefined {
|
||||
const parseExpressionResult = this.parseExpression(tr, rawExpression, allowedContext, definitionInfo);
|
||||
const parseExpressionResult = this.parseExpression(tr, token, rawExpression, allowedContext, definitionInfo);
|
||||
|
||||
// Check for error
|
||||
if (parseExpressionResult.error) {
|
||||
@@ -631,7 +631,8 @@ class TemplateReader {
|
||||
}
|
||||
|
||||
private parseExpression(
|
||||
range: TokenRange | undefined,
|
||||
range: TokenRange,
|
||||
token: StringToken,
|
||||
value: string,
|
||||
allowedContext: string[],
|
||||
definitionInfo: DefinitionInfo | undefined
|
||||
@@ -666,9 +667,31 @@ class TemplateReader {
|
||||
};
|
||||
}
|
||||
|
||||
const startTrim = value.length - value.trimStart().length;
|
||||
const endTrim = value.length - value.trimEnd().length;
|
||||
|
||||
const expressionRange: TokenRange = {
|
||||
start: {
|
||||
...range.start,
|
||||
column: range.start.column + OPEN_EXPRESSION.length + startTrim
|
||||
},
|
||||
end: {
|
||||
...range.end,
|
||||
column: range.end.column - CLOSE_EXPRESSION.length - endTrim
|
||||
}
|
||||
};
|
||||
|
||||
// Return the expression
|
||||
return <ParseExpressionResult>{
|
||||
expression: new BasicExpressionToken(this._fileId, range, trimmed, definitionInfo, undefined, value),
|
||||
expression: new BasicExpressionToken(
|
||||
this._fileId,
|
||||
range,
|
||||
trimmed,
|
||||
definitionInfo,
|
||||
undefined,
|
||||
token.source,
|
||||
expressionRange
|
||||
),
|
||||
error: undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,10 +11,20 @@ import {TokenType} from "./types";
|
||||
export class BasicExpressionToken extends ExpressionToken {
|
||||
private readonly expr: string;
|
||||
|
||||
public readonly source: string | undefined;
|
||||
|
||||
public readonly originalExpressions: BasicExpressionToken[] | undefined;
|
||||
|
||||
public readonly source: string;
|
||||
|
||||
/**
|
||||
* The range of the expression within the source string.
|
||||
*
|
||||
* `range` is the range of the entire expression, including the `${{` and `}}`. `expression` is only the expression
|
||||
* without any ${{ }} markers. `expressionRange` is the range of just the expression within the document.
|
||||
*/
|
||||
public readonly expressionRange: TokenRange | undefined;
|
||||
|
||||
/**
|
||||
* @param originalExpressions If the basic expression was transformed from individual expressions, these will be the original ones
|
||||
*/
|
||||
@@ -24,12 +34,14 @@ export class BasicExpressionToken extends ExpressionToken {
|
||||
expression: string,
|
||||
definitionInfo: DefinitionInfo | undefined,
|
||||
originalExpressions: BasicExpressionToken[] | undefined,
|
||||
source: string
|
||||
source: string | undefined,
|
||||
expressionRange?: TokenRange | undefined
|
||||
) {
|
||||
super(TokenType.BasicExpression, file, range, undefined, definitionInfo);
|
||||
this.expr = expression;
|
||||
this.originalExpressions = originalExpressions;
|
||||
this.source = source;
|
||||
this.originalExpressions = originalExpressions;
|
||||
this.expressionRange = expressionRange;
|
||||
}
|
||||
|
||||
public get expression(): string {
|
||||
@@ -44,7 +56,8 @@ export class BasicExpressionToken extends ExpressionToken {
|
||||
this.expr,
|
||||
this.definitionInfo,
|
||||
this.originalExpressions,
|
||||
this.source
|
||||
this.source,
|
||||
this.expressionRange
|
||||
)
|
||||
: new BasicExpressionToken(
|
||||
this.file,
|
||||
@@ -52,7 +65,8 @@ export class BasicExpressionToken extends ExpressionToken {
|
||||
this.expr,
|
||||
this.definitionInfo,
|
||||
this.originalExpressions,
|
||||
this.source
|
||||
this.source,
|
||||
this.expressionRange
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,10 @@ import {TemplateToken} from "./template-token";
|
||||
describe("traverse", () => {
|
||||
it("returns parent token and key", () => {
|
||||
const workflow = parseWorkflow(
|
||||
"wf.yaml",
|
||||
[
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push`
|
||||
}
|
||||
],
|
||||
{
|
||||
name: "wf.yaml",
|
||||
content: `on: push`
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
export type Position = {
|
||||
/** The one-based line value */
|
||||
line: number;
|
||||
|
||||
/** The one-based column value */
|
||||
column: number;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import {File} from "./file";
|
||||
import {FileReference} from "./file-reference";
|
||||
|
||||
export interface FileProvider {
|
||||
getFileContent(ref: FileReference): Promise<File>;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {parseFileReference} from "./file-reference";
|
||||
|
||||
describe("parseFileReference", () => {
|
||||
it("parses local file reference", () => {
|
||||
const ref = parseFileReference("./workflow/path");
|
||||
expect(ref).toEqual({
|
||||
path: "workflow/path"
|
||||
});
|
||||
});
|
||||
|
||||
it("parses local file references with an empty path", () => {
|
||||
const ref = parseFileReference("./");
|
||||
expect(ref).toEqual({
|
||||
path: ""
|
||||
});
|
||||
});
|
||||
|
||||
it("parses remote file reference", () => {
|
||||
const ref = parseFileReference("owner/repo/path@version");
|
||||
expect(ref).toEqual({
|
||||
owner: "owner",
|
||||
repository: "repo",
|
||||
path: "path",
|
||||
version: "version"
|
||||
});
|
||||
});
|
||||
|
||||
it("parses remote file reference with an empty path", () => {
|
||||
const ref = parseFileReference("owner/repo@version");
|
||||
expect(ref).toEqual({
|
||||
owner: "owner",
|
||||
repository: "repo",
|
||||
path: "",
|
||||
version: "version"
|
||||
});
|
||||
});
|
||||
|
||||
it("parses remote file reference with slashes in the version", () => {
|
||||
const ref = parseFileReference("owner/repo@feature-branch/dev");
|
||||
expect(ref).toEqual({
|
||||
owner: "owner",
|
||||
repository: "repo",
|
||||
path: "",
|
||||
version: "feature-branch/dev"
|
||||
});
|
||||
});
|
||||
|
||||
it("throws for malformed remote file references", () => {
|
||||
expect(() => parseFileReference("owner/repo/path")).toThrowError("Invalid file reference: owner/repo/path");
|
||||
|
||||
expect(() => parseFileReference("owner/repo/path@")).toThrowError("Invalid file reference: owner/repo/path@");
|
||||
|
||||
expect(() => parseFileReference("owner@")).toThrowError("Invalid file reference: owner@");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
export type FileReference = LocalFileReference | RemoteFileReference;
|
||||
|
||||
export type LocalFileReference = {
|
||||
path: string;
|
||||
};
|
||||
|
||||
export type RemoteFileReference = {
|
||||
repository: string;
|
||||
owner: string;
|
||||
path: string;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export function parseFileReference(ref: string): FileReference {
|
||||
if (ref.startsWith("./")) {
|
||||
return {
|
||||
path: ref.substring(2)
|
||||
};
|
||||
}
|
||||
|
||||
const [remotePath, version] = ref.split("@");
|
||||
const [owner, repository, ...pathSegments] = remotePath.split("/").filter(s => s.length > 0);
|
||||
|
||||
if (!owner || !repository || !version) {
|
||||
throw new Error(`Invalid file reference: ${ref}`);
|
||||
}
|
||||
|
||||
return {
|
||||
repository,
|
||||
owner,
|
||||
path: pathSegments.join("/"),
|
||||
version
|
||||
};
|
||||
}
|
||||
|
||||
export function fileIdentifier(ref: FileReference): string {
|
||||
if (!("repository" in ref)) {
|
||||
return "./" + ref.path;
|
||||
}
|
||||
|
||||
return `${ref.owner}/${ref.repository}/${ref.path}@${ref.version}`;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: 'Hello \${{ fromJSON('test') == inputs.name }}'
|
||||
run: echo Hello, world!`;
|
||||
|
||||
const result = parseWorkflow("main.yaml", [{name: "main.yaml", content: content}], nullTrace);
|
||||
const result = parseWorkflow({name: "main.yaml", content: content}, nullTrace);
|
||||
|
||||
expect(result.context.errors.count).toBe(1);
|
||||
expect(result.value).toBeUndefined();
|
||||
|
||||
@@ -11,15 +11,16 @@ export interface ParseWorkflowResult {
|
||||
value: TemplateToken | undefined;
|
||||
}
|
||||
|
||||
export function parseWorkflow(entryFileName: string, files: File[], trace: TraceWriter): ParseWorkflowResult {
|
||||
const context = new TemplateContext(new TemplateValidationErrors(), getWorkflowSchema(), trace);
|
||||
export function parseWorkflow(entryFile: File, trace: TraceWriter): ParseWorkflowResult;
|
||||
export function parseWorkflow(entryFile: File, context: TemplateContext): ParseWorkflowResult;
|
||||
export function parseWorkflow(entryFile: File, contextOrTrace: TraceWriter | TemplateContext): ParseWorkflowResult {
|
||||
const context =
|
||||
contextOrTrace instanceof TemplateContext
|
||||
? contextOrTrace
|
||||
: new TemplateContext(new TemplateValidationErrors(), getWorkflowSchema(), contextOrTrace);
|
||||
|
||||
// Add file ids
|
||||
files.forEach(x => context.getFileId(x.name));
|
||||
|
||||
const fileId = context.getFileId(entryFileName);
|
||||
const fileContent = files[fileId - 1].content;
|
||||
const reader = new YamlObjectReader(context, fileId, fileContent);
|
||||
const fileId = context.getFileId(entryFile.name);
|
||||
const reader = new YamlObjectReader(context, fileId, entryFile.content);
|
||||
if (context.errors.count > 0) {
|
||||
// The file is not valid YAML, template errors could be misleading
|
||||
return {
|
||||
|
||||
@@ -81,13 +81,10 @@ it("YAML errors include range information", () => {
|
||||
|
||||
function parseAsWorkflow(content: string): TemplateToken | undefined {
|
||||
const result = parseWorkflow(
|
||||
"test.yaml",
|
||||
[
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: content
|
||||
}
|
||||
],
|
||||
{
|
||||
name: "test.yaml",
|
||||
content: content
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ import * as path from "path";
|
||||
import * as YAML from "yaml";
|
||||
import {convertWorkflowTemplate} from "./model/convert";
|
||||
import {TraceWriter} from "./templates/trace-writer";
|
||||
import {File} from "./workflows/file";
|
||||
import {FileProvider} from "./workflows/file-provider";
|
||||
import {fileIdentifier, FileReference} from "./workflows/file-reference";
|
||||
import {parseWorkflow} from "./workflows/workflow-parser";
|
||||
|
||||
interface TestOptions {
|
||||
@@ -41,31 +44,53 @@ describe("x-lang tests", () => {
|
||||
const testOptions: TestOptions = YAML.parse(testDocs[0]);
|
||||
const unsupportedTest = contains(testOptions.skip, "TypeScript");
|
||||
|
||||
const test = () => {
|
||||
let testFileName = ".github/workflows" + fileName.substring(fileName.lastIndexOf("/"));
|
||||
let testInput = testDocs[1];
|
||||
let expectedTemplate = testDocs[2].trim();
|
||||
// TODO: when reusable workflows are implemented, implement correctly
|
||||
const test = async () => {
|
||||
const testFileName = ".github/workflows" + fileName.substring(fileName.lastIndexOf("/"));
|
||||
const testInput = testDocs[1];
|
||||
const expectedTemplate = testDocs[testDocs.length - 1].trim();
|
||||
|
||||
// For reusable workflow tests, additional workflows are passed in as pairs of
|
||||
// file names and file contents
|
||||
const reusableWorkflows: Record<string, File> = {};
|
||||
if (fileName.indexOf("reusable") !== -1) {
|
||||
testFileName = testDocs[1];
|
||||
testInput = testDocs[2];
|
||||
expectedTemplate = testDocs[3].trim();
|
||||
for (let i = 2; i < testDocs.length - 1; i = i + 2) {
|
||||
reusableWorkflows[testDocs[i]] = {
|
||||
name: testDocs[i],
|
||||
content: testDocs[i + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const parseResult = parseWorkflow(
|
||||
testFileName,
|
||||
[
|
||||
{
|
||||
name: testFileName,
|
||||
content: testInput
|
||||
const testFileProvider: FileProvider = {
|
||||
getFileContent: async (ref: FileReference) => {
|
||||
const file = reusableWorkflows[fileIdentifier(ref)];
|
||||
if (file) {
|
||||
return file;
|
||||
}
|
||||
],
|
||||
|
||||
throw new Error("File not found: " + fileName);
|
||||
}
|
||||
};
|
||||
|
||||
const parseResult = parseWorkflow(
|
||||
{
|
||||
name: testFileName,
|
||||
content: testInput
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
expect(parseResult.value).not.toBeUndefined();
|
||||
|
||||
const workflowTemplate = convertWorkflowTemplate(parseResult.context, parseResult.value!);
|
||||
const workflowTemplate = await convertWorkflowTemplate(
|
||||
parseResult.context,
|
||||
parseResult.value!,
|
||||
undefined,
|
||||
testFileProvider,
|
||||
{
|
||||
fetchReusableWorkflowDepth: 1
|
||||
}
|
||||
);
|
||||
|
||||
// Unless this tests is only used by TypeScript, remove the events for now.
|
||||
// TODO: Remove this once we parse events everywhere
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@ skip:
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- run: echo hi
|
||||
continue-on-error: true
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
build2:
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
concurrency: staging
|
||||
build4:
|
||||
runs-on: macos-latest
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ref
|
||||
cancel-in-progress: ${{ github.ref }}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
bad_insert1: "This is a bad ${{ insert }}"
|
||||
bad_insert2: "${{ insert }} are bad at the beginning"
|
||||
${{ insert }}: ${{ github.ref }}
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"Message": ".github/workflows/errors-insert.yml (Line: 6, Col: 20): The directive 'insert' is not allowed in this context. Directives are not supported for expressions that are embedded within a string. Directives are only supported when the entire value is an expression."
|
||||
},
|
||||
{
|
||||
"Message": ".github/workflows/errors-insert.yml (Line: 7, Col: 20): The directive 'insert' is not allowed in this context. Directives are not supported for expressions that are embedded within a string. Directives are only supported when the entire value is an expression."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- null : ' '
|
||||
run: echo {{ 😀 }}
|
||||
---
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"Message": ".github/workflows/errors-invalid-mapping-key.yml (Line: 6, Col: 9): Unexpected value ''"
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
- run: echo hi
|
||||
build3:
|
||||
runs-on:
|
||||
runs-on:
|
||||
group: ent/
|
||||
steps:
|
||||
- run: echo hi
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
bad-strategy-key:
|
||||
strategy:
|
||||
bad-key:
|
||||
os: [10]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"Message": ".github/workflows/errors-matrix-bad-key.yml (Line: 5, Col: 7): Unexpected value 'bad-key'"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
empty-vector:
|
||||
strategy:
|
||||
matrix:
|
||||
os: []
|
||||
version: [10,12]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"Message": ".github/workflows/errors-matrix-empty-vector.yml (Line: 6, Col: 13): Matrix vector 'os' does not contain any values"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
max-depth: 5
|
||||
skip:
|
||||
- TypeScript
|
||||
max-depth: 5
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
max-file-size: 124
|
||||
skip:
|
||||
- TypeScript
|
||||
max-file-size: 124
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
max-result-size: 768
|
||||
skip:
|
||||
- TypeScript
|
||||
max-result-size: 768
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
max-result-size: 2048
|
||||
skip:
|
||||
- TypeScript
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- run: echo Hello && World #string token
|
||||
build2:
|
||||
if: false
|
||||
if: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo 1
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Switch to using Python 3.10 by default
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: >-
|
||||
3.10
|
||||
---
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__actions_setup-python",
|
||||
"name": "Switch to using Python 3.10 by default",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"uses": "actions/setup-python@v4",
|
||||
"with": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "python-version",
|
||||
"Value": "3.10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix_map: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- run: echo hi
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
needs: generate
|
||||
env:
|
||||
${{ insert }}: ${{ fromJson(needs.generate.outputs.matrix_map) }}
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "generate",
|
||||
"name": "generate",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"outputs": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "matrix_map",
|
||||
"Value": {
|
||||
"type": 3,
|
||||
"expr": "steps.set-matrix.outputs.matrix"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "job",
|
||||
"id": "run",
|
||||
"name": "run",
|
||||
"needs": [
|
||||
"generate"
|
||||
],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"env": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": {
|
||||
"type": 4,
|
||||
"directive": "insert"
|
||||
},
|
||||
"Value": {
|
||||
"type": 3,
|
||||
"expr": "fromJson(needs.generate.outputs.matrix_map)"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo hi
|
||||
build4:
|
||||
build4:
|
||||
needs:
|
||||
- build
|
||||
- build2
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
matrix-basic:
|
||||
strategy:
|
||||
matrix:
|
||||
version: [10, 12, 14]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: echo hi
|
||||
matrix-nested-sequences:
|
||||
strategy:
|
||||
matrix:
|
||||
version: [[[[10]],2],12,14]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: echo hi
|
||||
matrix-with-infinity:
|
||||
strategy:
|
||||
matrix:
|
||||
version: [1, 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: echo hi
|
||||
nested-matrix:
|
||||
strategy:
|
||||
matrix: { vector1: [ {foo: {bar: baz} } ] }
|
||||
runs-on: linux
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "matrix-basic",
|
||||
"name": "matrix-basic",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"strategy": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "matrix",
|
||||
"Value": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "version",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
10,
|
||||
12,
|
||||
14
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "os",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
"ubuntu-latest",
|
||||
"windows-latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"runs-on": {
|
||||
"type": 3,
|
||||
"expr": "matrix.os"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "job",
|
||||
"id": "matrix-nested-sequences",
|
||||
"name": "matrix-nested-sequences",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"strategy": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "matrix",
|
||||
"Value": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "version",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
{
|
||||
"type": 1,
|
||||
"seq": [
|
||||
{
|
||||
"type": 1,
|
||||
"seq": [
|
||||
{
|
||||
"type": 1,
|
||||
"seq": [
|
||||
10
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
2
|
||||
]
|
||||
},
|
||||
12,
|
||||
14
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "os",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
"ubuntu-latest",
|
||||
"windows-latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"runs-on": {
|
||||
"type": 3,
|
||||
"expr": "matrix.os"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "job",
|
||||
"id": "matrix-with-infinity",
|
||||
"name": "matrix-with-infinity",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"strategy": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "matrix",
|
||||
"Value": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "version",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
1,
|
||||
"Infinity"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "os",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
"ubuntu-latest",
|
||||
"windows-latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"runs-on": {
|
||||
"type": 3,
|
||||
"expr": "matrix.os"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "job",
|
||||
"id": "nested-matrix",
|
||||
"name": "nested-matrix",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"strategy": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "matrix",
|
||||
"Value": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "vector1",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
{
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "foo",
|
||||
"Value": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "bar",
|
||||
"Value": "baz"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"runs-on": "linux",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+3
-3
@@ -10,7 +10,7 @@ jobs:
|
||||
name: ${{ github.actor }}
|
||||
timeout-minutes: ${{ github.ref }}
|
||||
cancel-timeout-minutes: 300
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
@@ -28,10 +28,10 @@ jobs:
|
||||
build2:
|
||||
runs-on: [self-hosted, linux]
|
||||
continue-on-error: true
|
||||
name: Jobs Repro Hardcode
|
||||
name: Jobs Repro Hardcode
|
||||
timeout-minutes: 360
|
||||
cancel-timeout-minutes: 300
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: groupA
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Typescript
|
||||
- TypeScript
|
||||
---
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- Typescript
|
||||
- TypeScript
|
||||
---
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -22,6 +21,10 @@ on:
|
||||
- debug
|
||||
# Defaults to string
|
||||
input4:
|
||||
input5-Env:
|
||||
description: 'Test environment'
|
||||
type: environment
|
||||
required: true
|
||||
jobs:
|
||||
my-job:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -33,7 +36,8 @@ jobs:
|
||||
"input1": "string",
|
||||
"input2": "boolean",
|
||||
"input3": "choice",
|
||||
"input4": "string"
|
||||
"input4": "string",
|
||||
"input5-Env": "environment"
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Typescript
|
||||
- TypeScript
|
||||
---
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- run: echo hi
|
||||
continue-on-error: true
|
||||
deploy:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: write
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
include-source: true # Preserve file/line/col in serialized output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
|
||||
+14
-38
@@ -33,46 +33,34 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": {
|
||||
"type": 0,
|
||||
"file": 1,
|
||||
"line": 3,
|
||||
"col": 3,
|
||||
"lit": "build"
|
||||
},
|
||||
"Name": {
|
||||
"name": {
|
||||
"type": 0,
|
||||
"file": 1,
|
||||
"line": 3,
|
||||
"col": 3,
|
||||
"lit": "build"
|
||||
},
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": {
|
||||
"ref": {
|
||||
"type": 0,
|
||||
"file": 1,
|
||||
"line": 4,
|
||||
"col": 11,
|
||||
"lit": "some-org-1/some-repo-1/.github/workflows/build.yml@v1"
|
||||
},
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": {
|
||||
@@ -120,46 +108,34 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": {
|
||||
"type": 0,
|
||||
"file": 1,
|
||||
"line": 5,
|
||||
"col": 3,
|
||||
"lit": "deploy"
|
||||
},
|
||||
"Name": {
|
||||
"name": {
|
||||
"type": 0,
|
||||
"file": 1,
|
||||
"line": 5,
|
||||
"col": 3,
|
||||
"lit": "deploy"
|
||||
},
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": {
|
||||
"ref": {
|
||||
"type": 0,
|
||||
"file": 1,
|
||||
"line": 6,
|
||||
"col": 11,
|
||||
"lit": "some-org-2/some-repo-2/.github/workflows/deploy.yml@v2"
|
||||
},
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": {
|
||||
|
||||
@@ -3,7 +3,7 @@ skip:
|
||||
- TypeScript
|
||||
---
|
||||
# This is meant to cover all the different types of TemplateToken that are output
|
||||
# with include-source: true. Currently it is missing type 4 (insert expression)
|
||||
# with include-source: true. Currently it is missing type 4 (insert expression)
|
||||
# and type 7 (null), once we have matrix strategy we should be able to get null or combine
|
||||
# this test with preserves-source-info-basic.yml.
|
||||
on: push
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -53,17 +52,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"input-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -200,7 +198,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InputValues": {
|
||||
"input-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -229,16 +227,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
@@ -66,19 +66,18 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-1",
|
||||
"Name": "deploy-1",
|
||||
"Needs": [
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-1",
|
||||
"name": "deploy-1",
|
||||
"needs": [
|
||||
"build"
|
||||
],
|
||||
"If": {
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/deploy.yml@v1",
|
||||
"input-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -99,7 +98,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InputValues": {
|
||||
"input-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -108,7 +107,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretDefinitions": {
|
||||
"secret-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -129,7 +128,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretValues": {
|
||||
"secret-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -141,14 +140,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "job1",
|
||||
@@ -184,19 +176,18 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-2",
|
||||
"Name": "deploy-2",
|
||||
"Needs": [
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-2",
|
||||
"name": "deploy-2",
|
||||
"needs": [
|
||||
"build"
|
||||
],
|
||||
"If": {
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/deploy.yml@v1",
|
||||
"input-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -217,7 +208,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InputValues": {
|
||||
"input-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -226,7 +217,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretDefinitions": {
|
||||
"secret-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -247,15 +238,8 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": true,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"inherit-secrets": true,
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "job1",
|
||||
|
||||
+9
-20
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -35,17 +34,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy",
|
||||
"Name": "deploy",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy",
|
||||
"name": "deploy",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/deploy.yml@v1",
|
||||
"input-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -98,7 +96,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InputValues": {
|
||||
"input-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -119,16 +117,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "job1",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -26,28 +25,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "build-it",
|
||||
@@ -71,28 +58,16 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build1",
|
||||
"Name": "custom name",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build1",
|
||||
"name": "custom name",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "build-it",
|
||||
@@ -116,31 +91,19 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build2",
|
||||
"Name": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build2",
|
||||
"name": {
|
||||
"type": 3,
|
||||
"expr": "github.ref"
|
||||
},
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "build-it",
|
||||
|
||||
+14
-38
@@ -28,51 +28,27 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-level-0",
|
||||
"Name": "deploy-level-0",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-0",
|
||||
"name": "deploy-level-0",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy-level-1.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-1.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-level-1",
|
||||
"Name": "deploy-level-1",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-1",
|
||||
"name": "deploy-level-1",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy-level-2.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-2.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy-level-1",
|
||||
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
max-nested-reusable-workflows-depth: 2
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
a:
|
||||
uses: contoso/templates/.github/workflows/deploy-level-1a.yml@v1
|
||||
b:
|
||||
uses: contoso/templates/.github/workflows/deploy-level-1b.yml@v1
|
||||
c:
|
||||
uses: contoso/templates/.github/workflows/deploy-level-1c.yml@v1
|
||||
---
|
||||
contoso/templates/.github/workflows/deploy-level-1a.yml@v1
|
||||
---
|
||||
on: workflow_call
|
||||
jobs:
|
||||
deploy-level-1a:
|
||||
uses: contoso/templates/.github/workflows/deploy-level-2a.yml@v1
|
||||
---
|
||||
contoso/templates/.github/workflows/deploy-level-2a.yml@v1
|
||||
---
|
||||
on: workflow_call
|
||||
jobs:
|
||||
deploy-level-2a:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
contoso/templates/.github/workflows/deploy-level-1b.yml@v1
|
||||
---
|
||||
on: workflow_call
|
||||
jobs:
|
||||
deploy-level-1b:
|
||||
uses: contoso/templates/.github/workflows/deploy-level-2b.yml@v1
|
||||
---
|
||||
contoso/templates/.github/workflows/deploy-level-2b.yml@v1
|
||||
---
|
||||
on: workflow_call
|
||||
jobs:
|
||||
deploy-level-2b:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
contoso/templates/.github/workflows/deploy-level-1c.yml@v1
|
||||
---
|
||||
on: workflow_call
|
||||
jobs:
|
||||
deploy-level-1c:
|
||||
uses: contoso/templates/.github/workflows/deploy-level-2c.yml@v1
|
||||
---
|
||||
contoso/templates/.github/workflows/deploy-level-2c.yml@v1
|
||||
---
|
||||
on: workflow_call
|
||||
jobs:
|
||||
deploy-level-2c:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "a",
|
||||
"name": "a",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-1a.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-1a",
|
||||
"name": "deploy-level-1a",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-2a.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy-level-2a",
|
||||
"name": "deploy-level-2a",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "b",
|
||||
"name": "b",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-1b.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-1b",
|
||||
"name": "deploy-level-1b",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-2b.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy-level-2b",
|
||||
"name": "deploy-level-2b",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "c",
|
||||
"name": "c",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-1c.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-1c",
|
||||
"name": "deploy-level-1c",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-2c.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy-level-2c",
|
||||
"name": "deploy-level-2c",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+24
-57
@@ -42,80 +42,47 @@ jobs:
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-level-0",
|
||||
"Name": "deploy-level-0",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-0",
|
||||
"name": "deploy-level-0",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy-level-1.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-1.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "write"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-level-1",
|
||||
"Name": "deploy-level-1",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-1",
|
||||
"name": "deploy-level-1",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy-level-2.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-2.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "read"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "deploy-level-3",
|
||||
"Name": "deploy-level-3",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "deploy-level-3",
|
||||
"name": "deploy-level-3",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/deploy-level-3.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/deploy-level-3.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "read"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy-level-3",
|
||||
|
||||
+8
-19
@@ -47,30 +47,19 @@ permissions:
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "write"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
Vendored
+8
-19
@@ -47,30 +47,19 @@ jobs:
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "read"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
+15
-38
@@ -27,28 +27,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
@@ -72,30 +60,19 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build2",
|
||||
"Name": "build2",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build2",
|
||||
"name": "build2",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "write"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
+15
-38
@@ -27,28 +27,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
@@ -72,30 +60,19 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build2",
|
||||
"Name": "build2",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build2",
|
||||
"name": "build2",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "write"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
+16
-38
@@ -32,30 +32,19 @@ jobs:
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "read"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
@@ -82,30 +71,19 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build2",
|
||||
"Name": "build2",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build2",
|
||||
"name": "build2",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"permissions": {
|
||||
"actions": "write"
|
||||
},
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
+10
-20
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -31,17 +30,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"input-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -58,7 +56,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InputValues": {
|
||||
"input-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -70,15 +68,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": {
|
||||
"strategy": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -101,7 +91,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "build-it",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -33,28 +32,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
@@ -78,28 +65,16 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build2",
|
||||
"Name": "build2",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build2",
|
||||
"name": "build2",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso2/templates2/.github/workflows/build2.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso2/templates2/.github/workflows/build2.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy2",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -21,28 +20,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -27,22 +26,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": null,
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": false,
|
||||
"Outputs": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"outputs": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -66,12 +59,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "job1",
|
||||
|
||||
Vendored
+9
-19
@@ -25,19 +25,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"secret-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -46,7 +43,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretValues": {
|
||||
"secret-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -58,14 +55,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
@@ -32,19 +32,16 @@ jobs:
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build",
|
||||
"Name": "build",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"secret-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -61,7 +58,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretValues": {
|
||||
"secret-values": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -73,14 +70,7 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"InheritSecrets": false,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
@@ -104,19 +94,16 @@ jobs:
|
||||
]
|
||||
},
|
||||
{
|
||||
"Type": "reusableWorkflowJob",
|
||||
"Id": "build2",
|
||||
"Name": "build2",
|
||||
"Needs": [],
|
||||
"If": {
|
||||
"type": "reusableWorkflowJob",
|
||||
"id": "build2",
|
||||
"name": "build2",
|
||||
"needs": [],
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"Ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"Permissions": null,
|
||||
"InputDefinitions": null,
|
||||
"InputValues": null,
|
||||
"SecretDefinitions": {
|
||||
"ref": "contoso/templates/.github/workflows/build.yml@v1",
|
||||
"secret-definitions": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
@@ -133,15 +120,8 @@ jobs:
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecretValues": null,
|
||||
"InheritSecrets": true,
|
||||
"Outputs": null,
|
||||
"Defaults": null,
|
||||
"Env": null,
|
||||
"Concurrency": null,
|
||||
"EmbeddedConcurrency": null,
|
||||
"Strategy": null,
|
||||
"Jobs": [
|
||||
"inherit-secrets": true,
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "deploy",
|
||||
|
||||
+18
@@ -6,10 +6,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Actions/Capitalized@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: docker://alpine:latest
|
||||
- run: echo hello
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Actions/Capitalized@v2
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: docker://alpine:latest
|
||||
- run: echo hello
|
||||
@@ -34,6 +36,14 @@ jobs:
|
||||
},
|
||||
"uses": "actions/checkout@v2"
|
||||
},
|
||||
{
|
||||
"id": "__Actions_Capitalized",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"uses": "Actions/Capitalized@v2"
|
||||
},
|
||||
{
|
||||
"id": "__actions_setup-node",
|
||||
"if": {
|
||||
@@ -66,6 +76,14 @@ jobs:
|
||||
},
|
||||
"uses": "actions/checkout@v2"
|
||||
},
|
||||
{
|
||||
"id": "__Actions_Capitalized_2",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"uses": "Actions/Capitalized@v2"
|
||||
},
|
||||
{
|
||||
"id": "__actions_setup-node_2",
|
||||
"if": {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
---
|
||||
on: push
|
||||
env:
|
||||
UNDERSCORED_INT_AS_STRING: 12_345
|
||||
UNDERSCORED_FLOAT_AS_STRING: 23_456.789_321
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
vector-1:
|
||||
- 12_345
|
||||
- 23_456.789_321
|
||||
steps:
|
||||
- run: echo hi
|
||||
---
|
||||
{
|
||||
"env": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "UNDERSCORED_INT_AS_STRING",
|
||||
"Value": "12_345"
|
||||
},
|
||||
{
|
||||
"Key": "UNDERSCORED_FLOAT_AS_STRING",
|
||||
"Value": "23_456.789_321"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"type": "job",
|
||||
"id": "build",
|
||||
"name": "build",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"strategy": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "matrix",
|
||||
"Value": {
|
||||
"type": 2,
|
||||
"map": [
|
||||
{
|
||||
"Key": "vector-1",
|
||||
"Value": {
|
||||
"type": 1,
|
||||
"seq": [
|
||||
"12_345",
|
||||
"23_456.789_321"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": [
|
||||
{
|
||||
"id": "__run",
|
||||
"if": {
|
||||
"type": 3,
|
||||
"expr": "success()"
|
||||
},
|
||||
"run": "echo hi"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- Go
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
@@ -35,7 +34,7 @@ jobs:
|
||||
|
||||
# Customer-breaking change we discovered when upgrading from YamlDotNet.Signed 6.0.0 to YamlDotNet 12.0.2.
|
||||
# YamlDotNet 12.0.2 produces the error "While scanning a multi-line double-quoted scalar, found wrong indentation."
|
||||
- "hello
|
||||
- "hello
|
||||
world"
|
||||
|
||||
steps:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
@@ -12,6 +12,14 @@ jobs:
|
||||
dot: .
|
||||
single-quoted-number: '8'
|
||||
double-quoted-number: "9"
|
||||
hex-number: 0xCB2431
|
||||
hex-string: "0xCB2431"
|
||||
# binary-number: 0b10100111001 // Binary numbers are not supported by C# at the moment
|
||||
# binary-string: "0b1111"
|
||||
octal-number: 0o1234567
|
||||
octal-string: "0o1234567"
|
||||
python-version: >-
|
||||
3.10
|
||||
---
|
||||
{
|
||||
"jobs": [
|
||||
@@ -46,6 +54,26 @@ jobs:
|
||||
{
|
||||
"Key": "double-quoted-number",
|
||||
"Value": "9"
|
||||
},
|
||||
{
|
||||
"Key": "hex-number",
|
||||
"Value": "13313073"
|
||||
},
|
||||
{
|
||||
"Key": "hex-string",
|
||||
"Value": "0xCB2431"
|
||||
},
|
||||
{
|
||||
"Key": "octal-number",
|
||||
"Value": "342391"
|
||||
},
|
||||
{
|
||||
"Key": "octal-string",
|
||||
"Value": "0o1234567"
|
||||
},
|
||||
{
|
||||
"Key": "python-version",
|
||||
"Value": "3.10"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
include-source: false # Drop file/line/col from output
|
||||
skip:
|
||||
- TypeScript
|
||||
- TypeScript
|
||||
---
|
||||
on: push
|
||||
jobs:
|
||||
|
||||
Reference in New Issue
Block a user