From 9d402a3cb7ba9c24e60e32e1464c59fff6e26659 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Tue, 14 Feb 2023 15:48:12 -0500 Subject: [PATCH] Add descriptions to reusable workflow outputs --- .../src/context-providers/needs.test.ts | 17 +++++++++-- .../src/context-providers/needs.ts | 29 ++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/actions-languageservice/src/context-providers/needs.test.ts b/actions-languageservice/src/context-providers/needs.test.ts index 729646c..a50fc30 100644 --- a/actions-languageservice/src/context-providers/needs.test.ts +++ b/actions-languageservice/src/context-providers/needs.test.ts @@ -1,4 +1,5 @@ import {DescriptionDictionary} from "@github/actions-expressions"; +import {StringData} from "@github/actions-expressions/data/string"; import {WorkflowContext} from "../context/workflow-context"; import {testGetWorkflowContext} from "../test-utils/test-workflow-context"; import {getNeedsContext} from "./needs"; @@ -96,8 +97,13 @@ jobs: const outputs = needs.get("outputs") as DescriptionDictionary; expect(outputs).toBeDefined(); - - expect(outputs.pairs().map(x => x.key)).toEqual(["build_id"]); + expect(outputs.pairs()).toEqual([ + { + key: "build_id", + value: new StringData("my-build-id"), + description: undefined + } + ]); }); it("reusable job with outputs", async () => { @@ -123,6 +129,13 @@ jobs: expect(outputs).toBeDefined(); expect(outputs.pairs().map(x => x.key)).toEqual(["build_id"]); + expect(outputs.pairs()).toEqual([ + { + key: "build_id", + value: new StringData("123"), + description: "The resulting build ID" + } + ]); }); }); }); diff --git a/actions-languageservice/src/context-providers/needs.ts b/actions-languageservice/src/context-providers/needs.ts index 3196e9f..d1baa25 100644 --- a/actions-languageservice/src/context-providers/needs.ts +++ b/actions-languageservice/src/context-providers/needs.ts @@ -1,6 +1,8 @@ import {data, DescriptionDictionary} from "@github/actions-expressions"; -import {isScalar, isString} from "@github/actions-workflow-parser"; +import {isMapping, 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 {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token"; import {WorkflowContext} from "../context/workflow-context"; export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDictionary { @@ -44,9 +46,28 @@ function jobOutputs(job?: WorkflowJob): DescriptionDictionary { continue; } - // Include the value for hover purposes - const value = isScalar(output.value) ? new data.StringData(output.value.toDisplayString()) : new data.Null(); - d.add(output.key.value, value); + d.add(output.key.value, ...jobOutput(job, output.value)); } return d; } + +function jobOutput(job: WorkflowJob, outputValue: TemplateToken): [data.ExpressionData, string | undefined] { + if (isJob(job)) { + // A regular workflow job won't have a description + return isScalar(outputValue) + ? [new data.StringData(outputValue.toDisplayString()), undefined] + : [new data.Null(), undefined]; + } + + if (!isMapping(outputValue)) { + return [new data.Null(), undefined]; + } + + const description = outputValue.find("description"); + const value = outputValue.find("value"); + + return [ + value && isScalar(value) ? new data.StringData(value.toDisplayString()) : new data.Null(), + description && isString(description) ? description.value : undefined + ]; +}