Support reusable workflow outputs in expressions
This commit is contained in:
@@ -72,4 +72,57 @@ jobs:
|
|||||||
const context = getNeedsContext(workflowContext);
|
const context = getNeedsContext(workflowContext);
|
||||||
expect(context.pairs().map(x => x.key)).toEqual(["test"]);
|
expect(context.pairs().map(x => x.key)).toEqual(["test"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("outputs", () => {
|
||||||
|
it("regular job with outputs", async () => {
|
||||||
|
const workflowContext = await testGetWorkflowContext(`
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
a:
|
||||||
|
outputs:
|
||||||
|
build_id: my-build-id
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo
|
||||||
|
b:
|
||||||
|
uses: ./.github/workflows/some-reusable-wor|kflow.yml
|
||||||
|
needs: [a]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const context = getNeedsContext(workflowContext);
|
||||||
|
|
||||||
|
const needs = context.get("a") as DescriptionDictionary;
|
||||||
|
expect(needs).toBeDefined();
|
||||||
|
|
||||||
|
const outputs = needs.get("outputs") as DescriptionDictionary;
|
||||||
|
expect(outputs).toBeDefined();
|
||||||
|
|
||||||
|
expect(outputs.pairs().map(x => x.key)).toEqual(["build_id"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reusable job with outputs", async () => {
|
||||||
|
const workflowContext = await testGetWorkflowContext(`
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
a:
|
||||||
|
uses: ./reusable-workflow-with-outputs.yaml
|
||||||
|
|
||||||
|
b:
|
||||||
|
needs: [a]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: ec|ho
|
||||||
|
`);
|
||||||
|
|
||||||
|
const context = getNeedsContext(workflowContext);
|
||||||
|
|
||||||
|
const needs = context.get("a") as DescriptionDictionary;
|
||||||
|
expect(needs).toBeDefined();
|
||||||
|
|
||||||
|
const outputs = needs.get("outputs") as DescriptionDictionary;
|
||||||
|
expect(outputs).toBeDefined();
|
||||||
|
|
||||||
|
expect(outputs.pairs().map(x => x.key)).toEqual(["build_id"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import {data, DescriptionDictionary} from "@github/actions-expressions";
|
import {data, DescriptionDictionary} from "@github/actions-expressions";
|
||||||
import {isScalar, isString} from "@github/actions-workflow-parser";
|
import {isScalar, isString} from "@github/actions-workflow-parser";
|
||||||
import {isJob} from "@github/actions-workflow-parser/model/type-guards";
|
import {WorkflowJob} from "@github/actions-workflow-parser/model/workflow-template";
|
||||||
import {Job, WorkflowJob} from "@github/actions-workflow-parser/model/workflow-template";
|
|
||||||
import {WorkflowContext} from "../context/workflow-context";
|
import {WorkflowContext} from "../context/workflow-context";
|
||||||
|
|
||||||
export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDictionary {
|
export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDictionary {
|
||||||
@@ -25,7 +24,7 @@ function needsJobContext(job?: WorkflowJob): DescriptionDictionary {
|
|||||||
// https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context
|
// https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context
|
||||||
const d = new DescriptionDictionary();
|
const d = new DescriptionDictionary();
|
||||||
|
|
||||||
if (job && isJob(job)) {
|
if (job) {
|
||||||
d.add("outputs", jobOutputs(job));
|
d.add("outputs", jobOutputs(job));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ function needsJobContext(job?: WorkflowJob): DescriptionDictionary {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jobOutputs(job?: Job): DescriptionDictionary {
|
function jobOutputs(job?: WorkflowJob): DescriptionDictionary {
|
||||||
const d = new DescriptionDictionary();
|
const d = new DescriptionDictionary();
|
||||||
if (!job?.outputs) {
|
if (!job?.outputs) {
|
||||||
return d;
|
return d;
|
||||||
|
|||||||
@@ -68,6 +68,25 @@ jobs:
|
|||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case "./reusable-workflow-with-outputs.yaml":
|
||||||
|
return {
|
||||||
|
name: "reusable-workflow-with-outputs.yaml",
|
||||||
|
content: `
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
outputs:
|
||||||
|
build_id:
|
||||||
|
description: 'The resulting build ID'
|
||||||
|
value: 123
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error("File not found");
|
throw new Error("File not found");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {getWorkflowContext, WorkflowContext} from "../context/workflow-context";
|
|||||||
import {nullTrace} from "../nulltrace";
|
import {nullTrace} from "../nulltrace";
|
||||||
import {findToken} from "../utils/find-token";
|
import {findToken} from "../utils/find-token";
|
||||||
import {getPositionFromCursor} from "./cursor-position";
|
import {getPositionFromCursor} from "./cursor-position";
|
||||||
|
import {testFileProvider} from "./test-file-provider";
|
||||||
|
|
||||||
export async function testGetWorkflowContext(input: string): Promise<WorkflowContext> {
|
export async function testGetWorkflowContext(input: string): Promise<WorkflowContext> {
|
||||||
const [textDocument, pos] = getPositionFromCursor(input);
|
const [textDocument, pos] = getPositionFromCursor(input);
|
||||||
@@ -17,7 +18,9 @@ export async function testGetWorkflowContext(input: string): Promise<WorkflowCon
|
|||||||
let template: WorkflowTemplate | undefined;
|
let template: WorkflowTemplate | undefined;
|
||||||
|
|
||||||
if (result.value) {
|
if (result.value) {
|
||||||
template = await convertWorkflowTemplate(result.context, result.value);
|
template = await convertWorkflowTemplate(result.context, result.value, undefined, testFileProvider, {
|
||||||
|
fetchReusableWorkflowDepth: 1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const {path} = findToken(pos, result.value);
|
const {path} = findToken(pos, result.value);
|
||||||
|
|||||||
Reference in New Issue
Block a user