Add initial support for converting reusable wf jobs

This commit is contained in:
Josh Gross
2023-02-03 16:57:28 -05:00
parent 36f879de6c
commit fe16d1a1ed
14 changed files with 335 additions and 224 deletions
@@ -1,5 +1,6 @@
import {data, DescriptionDictionary} from "@github/actions-expressions";
import {isScalar, isString} from "@github/actions-workflow-parser";
import {isJob} from "@github/actions-workflow-parser/model/type-guards";
import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/mapping-token";
import {WorkflowContext} from "../context/workflow-context";
@@ -12,8 +13,9 @@ export function getEnvContext(workflowContext: WorkflowContext): DescriptionDict
}
//job env
if (workflowContext.job && workflowContext.job.env) {
envContext(workflowContext.job.env, d);
const job = workflowContext.job;
if (job && isJob(job) && job.env) {
envContext(job.env, d);
}
//workflow env
@@ -1,5 +1,6 @@
import {data, DescriptionDictionary} from "@github/actions-expressions";
import {isMapping, isSequence} from "@github/actions-workflow-parser";
import {isReusableWorkflowJob} from "@github/actions-workflow-parser/model/type-guards";
import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/mapping-token";
import {WorkflowContext} from "../context/workflow-context";
@@ -7,7 +8,7 @@ export function getJobContext(workflowContext: WorkflowContext): DescriptionDict
// https://docs.github.com/en/actions/learn-github-actions/contexts#job-context
const jobContext = new DescriptionDictionary();
const job = workflowContext.job;
if (!job) {
if (!job || isReusableWorkflowJob(job)) {
return jobContext;
}
@@ -1,6 +1,7 @@
import {data, DescriptionDictionary} from "@github/actions-expressions";
import {isScalar, isString} from "@github/actions-workflow-parser";
import {Job} from "@github/actions-workflow-parser/model/workflow-template";
import {isJob} from "@github/actions-workflow-parser/model/type-guards";
import {Job, WorkflowJob} from "@github/actions-workflow-parser/model/workflow-template";
import {WorkflowContext} from "../context/workflow-context";
export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDictionary {
@@ -17,20 +18,21 @@ export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDi
return d;
}
function needsJobContext(job?: Job): DescriptionDictionary {
function needsJobContext(job?: WorkflowJob): DescriptionDictionary {
// https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context
const d = new DescriptionDictionary();
d.add("outputs", jobOutputs(job));
if (job && isJob(job)) {
d.add("outputs", jobOutputs(job));
}
// Can be "success", "failure", "cancelled", or "skipped"
d.add("result", new data.Null());
return d;
}
function jobOutputs(job?: Job): DescriptionDictionary {
function jobOutputs(job: Job): DescriptionDictionary {
const d = new DescriptionDictionary();
if (!job?.outputs) {
if (!job.outputs) {
return d;
}
@@ -1,11 +1,12 @@
import {data, DescriptionDictionary} from "@github/actions-expressions";
import {isReusableWorkflowJob} from "@github/actions-workflow-parser/model/type-guards";
import {Step} from "@github/actions-workflow-parser/model/workflow-template";
import {WorkflowContext} from "../context/workflow-context";
import {getDescription} from "./descriptions";
export function getStepsContext(workflowContext: WorkflowContext): DescriptionDictionary {
const d = new DescriptionDictionary();
if (!workflowContext.job?.steps) {
if (!workflowContext.job || isReusableWorkflowJob(workflowContext.job)) {
return d;
}
@@ -1,5 +1,6 @@
import {isMapping, isSequence, WorkflowTemplate} from "@github/actions-workflow-parser";
import {Job, Step} from "@github/actions-workflow-parser/model/workflow-template";
import {isJob, isReusableWorkflowJob} from "@github/actions-workflow-parser/model/type-guards";
import {Step, WorkflowJob} from "@github/actions-workflow-parser/model/workflow-template";
import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/mapping-token";
import {SequenceToken} from "@github/actions-workflow-parser/templates/tokens/sequence-token";
import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token";
@@ -11,7 +12,7 @@ export interface WorkflowContext {
template: WorkflowTemplate | undefined;
/** If the context is for a position within a job, this will be the job */
job?: Job;
job?: WorkflowJob;
/** If the context is for a position within a step, this will be the step */
step?: Step;
@@ -54,7 +55,10 @@ export function getWorkflowContext(
}
}
context.step = findStep(context.job?.steps, stepsSequence, stepToken);
if (context.job && isJob(context.job)) {
context.step = findStep(context.job.steps, stepsSequence, stepToken);
}
return context;
}
@@ -1,5 +1,6 @@
import {convertWorkflowTemplate, parseWorkflow} from "@github/actions-workflow-parser";
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
import {isJob} from "@github/actions-workflow-parser/model/type-guards";
import {File} from "@github/actions-workflow-parser/workflows/file";
import {TextDocument} from "vscode-languageserver-textdocument";
import {DocumentLink} from "vscode-languageserver-types";
@@ -27,7 +28,10 @@ export async function documentLinks(document: TextDocument): Promise<DocumentLin
const gitHubBaseUri = "https://www.github.com/";
for (const job of template?.jobs || []) {
for (const step of job?.steps || []) {
if (!job || !isJob(job)) {
continue;
}
for (const step of job.steps || []) {
if ("uses" in step) {
const actionRef = parseActionReference(step.uses.value);
if (!actionRef) {
@@ -0,0 +1,5 @@
import {File} from "@github/actions-workflow-parser/workflows/file";
export type WorkflowProvider = {
getWorkflow: (name: string) => Promise<File | undefined>;
};