Merge pull request #136 from github/cschleiden/reusable-needs
Support `needs` for reusable jobs
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import {DescriptionDictionary} from "@github/actions-expressions";
|
||||
import {WorkflowContext} from "../context/workflow-context";
|
||||
import {testGetWorkflowContext} from "../test-utils/test-workflow-context";
|
||||
import {getNeedsContext} from "./needs";
|
||||
|
||||
describe("needs context", () => {
|
||||
describe("invalid workflow context", () => {
|
||||
it("jobs not defined", () => {
|
||||
const workflowContext = {} as WorkflowContext;
|
||||
expect(workflowContext.job).toBeUndefined();
|
||||
expect(workflowContext.reusableWorkflowJob).toBeUndefined();
|
||||
|
||||
const context = getNeedsContext(workflowContext);
|
||||
expect(context).toEqual(new DescriptionDictionary());
|
||||
});
|
||||
});
|
||||
|
||||
it("job without needs", async () => {
|
||||
const workflowContext = await testGetWorkflowContext(`on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: ec|ho`);
|
||||
|
||||
const context = getNeedsContext(workflowContext);
|
||||
expect(context).toEqual(new DescriptionDictionary());
|
||||
});
|
||||
|
||||
it("job with needs", async () => {
|
||||
const workflowContext = await testGetWorkflowContext(`on: push
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test]
|
||||
steps:
|
||||
- run: ec|ho`);
|
||||
|
||||
const context = getNeedsContext(workflowContext);
|
||||
expect(context.pairs().map(x => x.key)).toEqual(["test"]);
|
||||
});
|
||||
|
||||
it("reusable job without needs", async () => {
|
||||
const workflowContext = await testGetWorkflowContext(`on: push
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo
|
||||
build:
|
||||
uses: ./.github/workflows/some-reusable-wor|kflow.yml`);
|
||||
|
||||
const context = getNeedsContext(workflowContext);
|
||||
expect(context).toEqual(new DescriptionDictionary());
|
||||
});
|
||||
|
||||
it("reusable job with needs", async () => {
|
||||
const workflowContext = await testGetWorkflowContext(`on: push
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo
|
||||
build:
|
||||
uses: ./.github/workflows/some-reusable-wor|kflow.yml
|
||||
needs: [test]`);
|
||||
|
||||
const context = getNeedsContext(workflowContext);
|
||||
expect(context.pairs().map(x => x.key)).toEqual(["test"]);
|
||||
});
|
||||
});
|
||||
@@ -6,11 +6,14 @@ import {WorkflowContext} from "../context/workflow-context";
|
||||
|
||||
export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDictionary {
|
||||
const d = new DescriptionDictionary();
|
||||
if (!workflowContext.job || !workflowContext.job.needs) {
|
||||
|
||||
const job = workflowContext.job || workflowContext.reusableWorkflowJob;
|
||||
|
||||
if (!job?.needs) {
|
||||
return d;
|
||||
}
|
||||
|
||||
for (const jobID of workflowContext.job.needs) {
|
||||
for (const jobID of job.needs) {
|
||||
const job = workflowContext.template?.jobs.find(job => job.id.value === jobID.value);
|
||||
d.add(jobID.value, needsJobContext(job));
|
||||
}
|
||||
|
||||
@@ -1,30 +1,5 @@
|
||||
import {convertWorkflowTemplate, parseWorkflow, WorkflowTemplate} from "@github/actions-workflow-parser";
|
||||
import {ActionStep, RunStep} from "@github/actions-workflow-parser/model/workflow-template";
|
||||
import {nullTrace} from "../nulltrace";
|
||||
import {getPositionFromCursor} from "../test-utils/cursor-position";
|
||||
import {findToken} from "../utils/find-token";
|
||||
import {getWorkflowContext, WorkflowContext} from "./workflow-context";
|
||||
|
||||
async function testGetWorkflowContext(input: string): Promise<WorkflowContext> {
|
||||
const [textDocument, pos] = getPositionFromCursor(input);
|
||||
const result = parseWorkflow(
|
||||
{
|
||||
content: textDocument.getText(),
|
||||
name: "wf.yaml"
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
let template: WorkflowTemplate | undefined;
|
||||
|
||||
if (result.value) {
|
||||
template = await convertWorkflowTemplate(result.context, result.value);
|
||||
}
|
||||
|
||||
const {path} = findToken(pos, result.value);
|
||||
|
||||
return getWorkflowContext(textDocument.uri, template, path);
|
||||
}
|
||||
import {testGetWorkflowContext} from "../test-utils/test-workflow-context";
|
||||
|
||||
describe("getWorkflowContext", () => {
|
||||
it("context for workflow", async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {parseWorkflow} from "@github/actions-workflow-parser/.";
|
||||
import {parseWorkflow} from "@github/actions-workflow-parser";
|
||||
import {File} from "@github/actions-workflow-parser/workflows/file";
|
||||
import {nullTrace} from "../nulltrace";
|
||||
import {getPositionFromCursor} from "../test-utils/cursor-position";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {isString} from "@github/actions-workflow-parser/.";
|
||||
import {isString} from "@github/actions-workflow-parser";
|
||||
import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token";
|
||||
import {DescriptionProvider, hover, HoverConfig} from "./hover";
|
||||
import {getPositionFromCursor} from "./test-utils/cursor-position";
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import {convertWorkflowTemplate, parseWorkflow, WorkflowTemplate} from "@github/actions-workflow-parser";
|
||||
import {getWorkflowContext, WorkflowContext} from "../context/workflow-context";
|
||||
import {nullTrace} from "../nulltrace";
|
||||
import {findToken} from "../utils/find-token";
|
||||
import {getPositionFromCursor} from "./cursor-position";
|
||||
|
||||
export async function testGetWorkflowContext(input: string): Promise<WorkflowContext> {
|
||||
const [textDocument, pos] = getPositionFromCursor(input);
|
||||
const result = parseWorkflow(
|
||||
{
|
||||
content: textDocument.getText(),
|
||||
name: "wf.yaml"
|
||||
},
|
||||
nullTrace
|
||||
);
|
||||
|
||||
let template: WorkflowTemplate | undefined;
|
||||
|
||||
if (result.value) {
|
||||
template = await convertWorkflowTemplate(result.context, result.value);
|
||||
}
|
||||
|
||||
const {path} = findToken(pos, result.value);
|
||||
|
||||
return getWorkflowContext(textDocument.uri, template, path);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import {TemplateContext} from "../../templates/template-context";
|
||||
import {StringToken, MappingToken, BasicExpressionToken, TemplateToken, ScalarToken} from "../../templates/tokens";
|
||||
import {BasicExpressionToken, MappingToken, ScalarToken, StringToken, TemplateToken} from "../../templates/tokens";
|
||||
import {isSequence, isString} from "../../templates/tokens/type-guards";
|
||||
import {WorkflowJob, Step} from "../workflow-template";
|
||||
import {Step, WorkflowJob} from "../workflow-template";
|
||||
import {convertConcurrency} from "./concurrency";
|
||||
import {convertToJobContainer, convertToJobServices} from "./container";
|
||||
import {handleTemplateTokenErrors} from "./handle-errors";
|
||||
@@ -103,7 +103,7 @@ export function convertJob(context: TemplateContext, jobKey: StringToken, token:
|
||||
type: "reusableWorkflowJob",
|
||||
id: jobKey,
|
||||
name: jobName(name, jobKey),
|
||||
needs: needs ?? [],
|
||||
needs: needs || [],
|
||||
if: new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, undefined),
|
||||
ref: workflowJobRef,
|
||||
"input-definitions": undefined,
|
||||
|
||||
Reference in New Issue
Block a user