From 97d50f74af7d0305f5f3161798648e6ccf25d1a2 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Tue, 10 Jan 2023 16:05:50 -0800 Subject: [PATCH 01/50] Clean up transform function --- actions-expressions/src/completion.test.ts | 6 +++ .../src/utils/transform.test.ts | 20 +++++++- .../src/utils/transform.ts | 46 ++++++++++--------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/actions-expressions/src/completion.test.ts b/actions-expressions/src/completion.test.ts index 810cd44..64e9283 100644 --- a/actions-expressions/src/completion.test.ts +++ b/actions-expressions/src/completion.test.ts @@ -70,6 +70,12 @@ describe("auto-complete", () => { }); }); + describe("in multi-line expressions", () => { + it("includes built-in functions", () => { + expect(testComplete("1 == (\nto").map(x => x.label)).toContainEqual("toJson"); + }); + }); + describe("for contexts", () => { it("provides suggestions for env", () => { const expected = completionItems("BAR_TEST", "FOO"); diff --git a/actions-languageservice/src/utils/transform.test.ts b/actions-languageservice/src/utils/transform.test.ts index ba4d85d..db91c60 100644 --- a/actions-languageservice/src/utils/transform.test.ts +++ b/actions-languageservice/src/utils/transform.test.ts @@ -37,7 +37,7 @@ jobs: jobs: build: runs-on: - - dummy`); + - key`); expect(newPos.character).toEqual(9); }); @@ -53,7 +53,23 @@ jobs: jobs: build: runs-on: - dummy:`); + key:`); expect(newPos.character).toEqual(7); }); + + it("does not transform expression lines", () => { + const [doc, pos] = getPositionFromCursor(`on: push +jobs: + build: + runs-on: + \${{ github| }}`); + const [newDoc, newPos] = transform(doc, pos); + + expect(newDoc.getText()).toEqual(`on: push +jobs: + build: + runs-on: + \${{ github }}`); + expect(newPos.character).toEqual(16); + }); }); diff --git a/actions-languageservice/src/utils/transform.ts b/actions-languageservice/src/utils/transform.ts index 015f709..a71ef9e 100644 --- a/actions-languageservice/src/utils/transform.ts +++ b/actions-languageservice/src/utils/transform.ts @@ -1,7 +1,7 @@ import {Position, TextDocument} from "vscode-languageserver-textdocument"; import {Range} from "vscode-languageserver-types"; -const DUMMY_KEY = "dummy"; +const PLACEHOLDER_KEY = "key"; // Transform a document to work around YAML parsing issues // Based on `_transform` in https://github.com/cschleiden/github-actions-parser/blob/main/src/lib/parser/complete.ts#L311 @@ -27,29 +27,33 @@ export function transform(doc: TextDocument, pos: Position): [TextDocument, Posi // Special case for Actions, if this line contains an expression marker, do _not_ transform. This is // an ugly fix for auto-completion in multi-line YAML strings. At this point in the process, we cannot // determine if a line is in such a multi-line string. - if (line.indexOf("${{") === -1) { - const colon = line.indexOf(":"); - if (colon === -1) { - const trimmedLine = line.trim(); - if (trimmedLine === "" || trimmedLine === "-") { - // Node in sequence or empty line - let spacer = ""; - if (trimmedLine === "-" && !line.endsWith(" ")) { - spacer = " "; - offset++; - } + if (line.indexOf("${{") !== -1) { + return [doc, pos]; + } - line = - line.substring(0, linePos) + spacer + DUMMY_KEY + (trimmedLine === "-" ? "" : ":") + line.substring(linePos); - - // Adjust pos by one to prevent a sequence node being marked as active + const containsColon = line.indexOf(":") !== -1; + if (!containsColon) { + const trimmedLine = line.trim(); + if (trimmedLine === "" || trimmedLine === "-") { + // Pos in sequence or empty line + let spacer = ""; + if (trimmedLine === "-" && !line.endsWith(" ")) { + spacer = " "; offset++; - } else if (!trimmedLine.startsWith("-")) { - // Add `:` to end of line - line = line + ":"; } - } else { - offset = offset - 1; + + line = + line.substring(0, linePos) + + spacer + + PLACEHOLDER_KEY + + (trimmedLine === "-" ? "" : ":") + + line.substring(linePos); + + // Adjust pos by one to prevent a sequence node being marked as active + offset++; + } else if (!trimmedLine.startsWith("-")) { + // Add `:` to end of line + line = line + ":"; } } From eb25801e47315cde8a51aecc8ac36492961bf9c5 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Tue, 10 Jan 2023 16:11:15 -0800 Subject: [PATCH 02/50] Adjust exports --- actions-expressions/src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/actions-expressions/src/index.ts b/actions-expressions/src/index.ts index c49489c..ad211b7 100644 --- a/actions-expressions/src/index.ts +++ b/actions-expressions/src/index.ts @@ -1,6 +1,7 @@ -export {complete} from "./completion"; +export {Expr} from "./ast"; +export {complete, CompletionItem} from "./completion"; export * as data from "./data"; export {ExpressionError} from "./errors"; export {Evaluator} from "./evaluator"; -export {Lexer} from "./lexer"; +export {Lexer, Result} from "./lexer"; export {Parser} from "./parser"; From 2bfc7d5293c7df2d22514efa7a48faf46e18c71c Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 11 Jan 2023 00:37:23 +0000 Subject: [PATCH 03/50] v0.1.80 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index e03fbae..326ae41 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.79", + "version": "0.1.80", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 82e9d45..a9ec1b8 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.79", + "version": "0.1.80", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.79", - "@github/actions-workflow-parser": "^0.1.79", + "@github/actions-languageservice": "^0.1.80", + "@github/actions-workflow-parser": "^0.1.80", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index b731a20..d3d35a8 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.79", + "version": "0.1.80", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.79", - "@github/actions-workflow-parser": "^0.1.79", + "@github/actions-expressions": "^0.1.80", + "@github/actions-workflow-parser": "^0.1.80", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 51ba515..1fea2a8 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.79", + "version": "0.1.80", "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.79", + "@github/actions-expressions": "^0.1.80", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 6b20b9f..0b0ebe6 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.79", + "version": "0.1.80", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.79", + "@github/actions-languageserver": "^0.1.80", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 6a6140d..10449ca 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.79" + "version": "0.1.80" } diff --git a/package-lock.json b/package-lock.json index 2d3a8b5..ba17b07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.79", + "version": "0.1.80", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.79", + "version": "0.1.80", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.79", - "@github/actions-workflow-parser": "^0.1.79", + "@github/actions-languageservice": "^0.1.80", + "@github/actions-workflow-parser": "^0.1.80", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.79", + "version": "0.1.80", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.79", - "@github/actions-workflow-parser": "^0.1.79", + "@github/actions-expressions": "^0.1.80", + "@github/actions-workflow-parser": "^0.1.80", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.79", + "version": "0.1.80", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.79", + "@github/actions-expressions": "^0.1.80", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.79", + "version": "0.1.80", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.79", + "@github/actions-languageserver": "^0.1.80", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.79", - "@github/actions-workflow-parser": "^0.1.79", + "@github/actions-languageservice": "^0.1.80", + "@github/actions-workflow-parser": "^0.1.80", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.79", - "@github/actions-workflow-parser": "^0.1.79", + "@github/actions-expressions": "^0.1.80", + "@github/actions-workflow-parser": "^0.1.80", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.79", + "@github/actions-expressions": "^0.1.80", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.79", + "@github/actions-languageserver": "^0.1.80", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From 43fecc8648638fa375d476073f2db2234d7e5a80 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Tue, 10 Jan 2023 17:44:48 -0800 Subject: [PATCH 04/50] Support descriptions for contexts --- actions-expressions/src/completion.test.ts | 18 ++- actions-expressions/src/completion.ts | 38 ++++- actions-expressions/src/index.ts | 2 +- .../src/context-providers.ts | 13 +- .../src/context-providers/secrets.ts | 37 ++--- .../src/context-providers/steps.test.ts | 25 ++- .../src/context-providers/steps.ts | 23 ++- .../src/complete.expressions.test.ts | 33 ++-- .../src/context-providers/config.ts | 27 +--- .../src/context-providers/default.ts | 22 ++- .../src/context-providers/descriptions.json | 148 ++++++++++++++++++ .../src/context-providers/descriptions.ts | 12 ++ .../context-providers/descriptionsSchema.json | 30 ++++ .../src/context-providers/env.ts | 8 +- .../src/context-providers/github.ts | 23 ++- .../src/context-providers/inputs.ts | 18 +-- .../src/context-providers/job.ts | 8 +- .../src/context-providers/matrix.test.ts | 27 ++-- .../src/context-providers/matrix.ts | 6 +- .../src/context-providers/needs.ts | 14 +- .../src/context-providers/steps.ts | 17 +- .../src/context-providers/strategy.ts | 8 +- 22 files changed, 407 insertions(+), 150 deletions(-) create mode 100644 actions-languageservice/src/context-providers/descriptions.json create mode 100644 actions-languageservice/src/context-providers/descriptions.ts create mode 100644 actions-languageservice/src/context-providers/descriptionsSchema.json diff --git a/actions-expressions/src/completion.test.ts b/actions-expressions/src/completion.test.ts index 810cd44..9a4257d 100644 --- a/actions-expressions/src/completion.test.ts +++ b/actions-expressions/src/completion.test.ts @@ -1,4 +1,4 @@ -import {complete, CompletionItem, trimTokenVector} from "./completion"; +import {complete, CompletionItem, DescriptionDictionary, trimTokenVector} from "./completion"; import {BooleanData} from "./data/boolean"; import {Dictionary} from "./data/dictionary"; import {StringData} from "./data/string"; @@ -19,6 +19,14 @@ const testContext = new Dictionary( } ) }, + { + key: "github", + value: new DescriptionDictionary({ + key: "actor", + value: new StringData(""), + description: "The name of the person or app that initiated the workflow. For example, octocat." + }) + }, { key: "secrets", value: new Dictionary({ @@ -79,6 +87,14 @@ describe("auto-complete", () => { expect(testComplete("env.FOO")).toEqual(expected); }); + it("includes descriptions", () => { + expect(testComplete("github.")).toContainEqual({ + label: "actor", + function: false, + description: "The name of the person or app that initiated the workflow. For example, octocat." + }); + }); + it("provides suggestions for secrets", () => { const expected = completionItems("AWS_TOKEN"); diff --git a/actions-expressions/src/completion.ts b/actions-expressions/src/completion.ts index 067f983..f647dfa 100644 --- a/actions-expressions/src/completion.ts +++ b/actions-expressions/src/completion.ts @@ -1,5 +1,5 @@ import {Dictionary, isDictionary} from "./data/dictionary"; -import {ExpressionData} from "./data/expressiondata"; +import {ExpressionData, Kind, Pair} from "./data/expressiondata"; import {Evaluator} from "./evaluator"; import {wellKnownFunctions} from "./funcs"; import {FunctionInfo} from "./funcs/info"; @@ -12,6 +12,36 @@ export type CompletionItem = { function: boolean; }; +export type DescriptionPair = Pair & {description?: string}; + +export class DescriptionDictionary extends Dictionary { + private readonly descriptions = new Map(); + + constructor(...pairs: DescriptionPair[]) { + super(); + + for (const p of pairs) { + this.add(p.key, p.value, p.description); + } + } + + override add(key: string, value: ExpressionData, description?: string): void { + super.add(key, value); + if (description) { + this.descriptions.set(key, description); + } + } + + override pairs(): DescriptionPair[] { + const pairs = super.pairs(); + return pairs.map(p => ({...p, description: this.descriptions.get(p.key)})); + } +} + +export function isDescriptionDictionary(x: ExpressionData): x is DescriptionDictionary { + return x.kind === Kind.Dictionary && x instanceof DescriptionDictionary; +} + // Complete returns a list of completion items for the given expression. // // The main functionality is auto-completing functions and context access: @@ -97,7 +127,7 @@ function contextKeys(context: ExpressionData): CompletionItem[] { return ( context .pairs() - .map(x => completionItemFromContext(x.key)) + .map(x => completionItemFromContext(x)) // Sort contexts .sort((a, b) => a.label.localeCompare(b.label)) ); @@ -106,12 +136,14 @@ function contextKeys(context: ExpressionData): CompletionItem[] { return []; } -function completionItemFromContext(context: string): CompletionItem { +function completionItemFromContext(pair: DescriptionPair): CompletionItem { + const context = pair.key.toString(); const parenIndex = context.indexOf("("); const isFunc = parenIndex >= 0 && context.indexOf(")") >= 0; return { label: isFunc ? context.substring(0, parenIndex) : context, + description: pair.description, function: isFunc }; } diff --git a/actions-expressions/src/index.ts b/actions-expressions/src/index.ts index ad211b7..53fc82a 100644 --- a/actions-expressions/src/index.ts +++ b/actions-expressions/src/index.ts @@ -1,5 +1,5 @@ export {Expr} from "./ast"; -export {complete, CompletionItem} from "./completion"; +export {complete, CompletionItem, DescriptionDictionary, DescriptionPair, isDescriptionDictionary} from "./completion"; export * as data from "./data"; export {ExpressionError} from "./errors"; export {Evaluator} from "./evaluator"; diff --git a/actions-languageserver/src/context-providers.ts b/actions-languageserver/src/context-providers.ts index 2263ff3..96a4f44 100644 --- a/actions-languageserver/src/context-providers.ts +++ b/actions-languageserver/src/context-providers.ts @@ -1,4 +1,4 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {ContextProviderConfig} from "@github/actions-languageservice"; import {WorkflowContext} from "@github/actions-languageservice/context/workflow-context"; import {isMapping, isString} from "@github/actions-workflow-parser"; @@ -23,7 +23,7 @@ export function contextProviders( const getContext = async ( name: string, - defaultContext: data.Dictionary | undefined, + defaultContext: DescriptionDictionary | undefined, workflowContext: WorkflowContext ) => { switch (name) { @@ -46,8 +46,13 @@ export function contextProviders( const secrets = await getSecrets(octokit, cache, repo, environmentName); - defaultContext = defaultContext || new data.Dictionary(); - secrets.forEach(secret => defaultContext!.add(secret.value, new data.StringData("***"))); + defaultContext = defaultContext || new DescriptionDictionary(); + secrets.repoSecrets.forEach(secret => + defaultContext!.add(secret.value, new data.StringData("***"), "Repository secret") + ); + secrets.environmentSecrets.forEach(secret => + defaultContext!.add(secret.value, new data.StringData("***"), `Secret for environment \`${environmentName}\``) + ); return defaultContext; } case "steps": { diff --git a/actions-languageserver/src/context-providers/secrets.ts b/actions-languageserver/src/context-providers/secrets.ts index c9ca049..d979375 100644 --- a/actions-languageserver/src/context-providers/secrets.ts +++ b/actions-languageserver/src/context-providers/secrets.ts @@ -8,28 +8,21 @@ export async function getSecrets( cache: TTLCache, repo: RepositoryContext, environmentName?: string -): Promise { - const secrets: StringData[] = []; - - // Repo secrets - const repoSecrets = await cache.get(`${repo.owner}/${repo.name}/secrets`, undefined, () => - fetchSecrets(octokit, repo.owner, repo.name) - ); - - secrets.push(...repoSecrets); - - // Environment secrets - if (environmentName) { - const envSecrets = await cache.get( - `${repo.owner}/${repo.name}/secrets/environment/${environmentName}`, - undefined, - () => fetchEnvironmentSecrets(octokit, repo.id, environmentName) - ); - - secrets.push(...envSecrets); - } - - return secrets.sort(); +): Promise<{ + repoSecrets: StringData[]; + environmentSecrets: StringData[]; +}> { + return { + repoSecrets: await await cache.get(`${repo.owner}/${repo.name}/secrets`, undefined, () => + fetchSecrets(octokit, repo.owner, repo.name) + ), + environmentSecrets: + (environmentName && + (await cache.get(`${repo.owner}/${repo.name}/secrets/environment/${environmentName}`, undefined, () => + fetchEnvironmentSecrets(octokit, repo.id, environmentName) + ))) || + [] + }; } async function fetchSecrets(octokit: Octokit, owner: string, name: string): Promise { diff --git a/actions-languageserver/src/context-providers/steps.test.ts b/actions-languageserver/src/context-providers/steps.test.ts index 9c883d9..c7d3922 100644 --- a/actions-languageserver/src/context-providers/steps.test.ts +++ b/actions-languageserver/src/context-providers/steps.test.ts @@ -1,4 +1,4 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {getStepsContext as getDefaultStepsContext} from "@github/actions-languageservice/context-providers/steps"; import {Octokit} from "@octokit/rest"; import nock from "nock"; @@ -80,18 +80,29 @@ it("adds action outputs", async () => { expect(stepsContext).toBeDefined(); expect(stepsContext).toEqual( - new data.Dictionary({ + new DescriptionDictionary({ key: "cache-primes", - value: new data.Dictionary( + value: new DescriptionDictionary( { key: "outputs", - value: new data.Dictionary({ + value: new DescriptionDictionary({ key: "cache-hit", - value: new data.StringData("A boolean value to indicate an exact match was found for the primary key") + value: new data.StringData("A boolean value to indicate an exact match was found for the primary key"), + description: "A boolean value to indicate an exact match was found for the primary key" }) }, - {key: "conclusion", value: new data.Null()}, - {key: "outcome", value: new data.Null()} + { + key: "conclusion", + value: new data.Null(), + description: + "The result of a completed step after `continue-on-error` is applied. Possible values are `success`, `failure`, `cancelled`, or `skipped`. When a `continue-on-error` step fails, the `outcome` is `failure`, but the final conclusion is `success`." + }, + { + key: "outcome", + value: new data.Null(), + description: + "The result of a completed step before `continue-on-error` is applied. Possible values are `success`, `failure`, `cancelled`, or `skipped`. When a `continue-on-error` step fails, the `outcome` is `failure`, but the final conclusion is `success`." + } ) }) ); diff --git a/actions-languageserver/src/context-providers/steps.ts b/actions-languageserver/src/context-providers/steps.ts index 85cba47..eea315b 100644 --- a/actions-languageserver/src/context-providers/steps.ts +++ b/actions-languageserver/src/context-providers/steps.ts @@ -1,5 +1,4 @@ -import {data} from "@github/actions-expressions"; -import {isDictionary} from "@github/actions-expressions/data/dictionary"; +import {data, DescriptionDictionary, isDescriptionDictionary} from "@github/actions-expressions"; import {parseActionReference} from "@github/actions-languageservice/action"; import {WorkflowContext} from "@github/actions-languageservice/context/workflow-context"; import {isActionStep} from "@github/actions-workflow-parser/model/type-guards"; @@ -10,9 +9,9 @@ import {getActionOutputs} from "./action-outputs"; export async function getStepsContext( octokit: Octokit, cache: TTLCache, - defaultContext: data.Dictionary | undefined, + defaultContext: DescriptionDictionary | undefined, workflowContext: WorkflowContext -): Promise { +): Promise { if (!defaultContext || !workflowContext.job) { return defaultContext; } @@ -26,7 +25,7 @@ export async function getStepsContext( // Copy the default context for each step // If the step is an action, add the action outputs to the context - const stepsContext = new data.Dictionary(); + const stepsContext = new DescriptionDictionary(); for (const step of workflowContext.job.steps) { if (!contextSteps.has(step.id)) { continue; @@ -38,7 +37,7 @@ export async function getStepsContext( continue; } - if (!isActionStep(step) || !isDictionary(defaultStepContext)) { + if (!isActionStep(step) || !isDescriptionDictionary(defaultStepContext)) { stepsContext.add(step.id, defaultStepContext); continue; } @@ -49,23 +48,23 @@ export async function getStepsContext( continue; } - const stepContext = new data.Dictionary(); - for (const {key, value} of defaultStepContext.pairs()) { + const stepContext = new DescriptionDictionary(); + for (const {key, value, description} of defaultStepContext.pairs()) { switch (key) { case "outputs": const outputs = await getActionOutputs(octokit, cache, action); if (!outputs) { - stepContext.add(key, value); + stepContext.add(key, value, description); continue; } - const outputsDict = new data.Dictionary(); + const outputsDict = new DescriptionDictionary(); for (const [key, value] of Object.entries(outputs)) { - outputsDict.add(key, new data.StringData(value.description)); + outputsDict.add(key, new data.StringData(value.description), value.description); } stepContext.add("outputs", outputsDict); break; default: - stepContext.add(key, value); + stepContext.add(key, value, description); } } stepsContext.add(step.id, stepContext); diff --git a/actions-languageservice/src/complete.expressions.test.ts b/actions-languageservice/src/complete.expressions.test.ts index b57b520..90a5b09 100644 --- a/actions-languageservice/src/complete.expressions.test.ts +++ b/actions-languageservice/src/complete.expressions.test.ts @@ -1,5 +1,5 @@ -import {data} from "@github/actions-expressions"; -import {CompletionItemKind} from "vscode-languageserver-types"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; +import {CompletionItem, CompletionItemKind} from "vscode-languageserver-types"; import {complete, getExpressionInput} from "./complete"; import {ContextProviderConfig} from "./context-providers/config"; import {registerLogger} from "./log"; @@ -10,9 +10,10 @@ const contextProviderConfig: ContextProviderConfig = { getContext: async (context: string) => { switch (context) { case "github": - return new data.Dictionary({ + return new DescriptionDictionary({ key: "event", - value: new data.StringData("push") + value: new data.StringData("push"), + description: "The event that triggered the workflow" }); } @@ -57,6 +58,20 @@ describe("expressions", () => { ]); }); + it("contains description", async () => { + const input = "run-name: ${{ github.| }}"; + const result = await complete(...getPositionFromCursor(input), undefined, undefined); + + expect(result).toContainEqual({ + label: "api_url", + documentation: { + kind: "markdown", + value: "The URL of the GitHub Actions REST API." + }, + kind: CompletionItemKind.Variable + }); + }); + it("single region with existing input", async () => { const input = "run-name: ${{ g| }}"; const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); @@ -319,11 +334,11 @@ env: jobs: a: runs-on: ubuntu-latest - env: + env: envjoba: job_a_env b: runs-on: ubuntu-latest - env: + env: envjobb: job_b_env steps: - name: step a @@ -387,7 +402,7 @@ jobs: it("includes expected keys", async () => { const input = ` on: push - + jobs: test: runs-on: ubuntu-latest @@ -452,7 +467,7 @@ jobs: on: schedule: - cron: '0 0 * * *' - + jobs: test: runs-on: ubuntu-latest @@ -469,7 +484,7 @@ jobs: it("includes event payload", async () => { const input = ` on: [push, pull_request] - + jobs: test: runs-on: ubuntu-latest diff --git a/actions-languageservice/src/context-providers/config.ts b/actions-languageservice/src/context-providers/config.ts index 497b94b..2c2f30b 100644 --- a/actions-languageservice/src/context-providers/config.ts +++ b/actions-languageservice/src/context-providers/config.ts @@ -1,31 +1,10 @@ -import {data} from "@github/actions-expressions"; -import {Dictionary} from "@github/actions-expressions/data/dictionary"; -import {ExpressionData, Pair} from "@github/actions-expressions/data/expressiondata"; +import {DescriptionDictionary} from "@github/actions-expressions"; import {WorkflowContext} from "../context/workflow-context"; export type ContextProviderConfig = { getContext: ( name: string, - defaultContext: data.Dictionary | undefined, + defaultContext: DescriptionDictionary | undefined, workflowContext: WorkflowContext - ) => Promise; + ) => Promise; }; - -/** - * DynamicDictionary is a dictionary that returns an empty DynamicDictionary (or other given type) - * for any key that is not present. - */ -export class DynamicDictionary extends data.Dictionary { - constructor(pairs: Pair[], private creator: () => T = () => new data.Dictionary() as T) { - super(...pairs); - } - - get(key: string): ExpressionData | undefined { - const value = super.get(key); - if (value) { - return value; - } - - return this.creator(); - } -} diff --git a/actions-languageservice/src/context-providers/default.ts b/actions-languageservice/src/context-providers/default.ts index 6f62792..eb8c5b8 100644 --- a/actions-languageservice/src/context-providers/default.ts +++ b/actions-languageservice/src/context-providers/default.ts @@ -1,7 +1,8 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {Kind} from "@github/actions-expressions/data/expressiondata"; import {WorkflowContext} from "../context/workflow-context"; import {ContextProviderConfig} from "./config"; +import {getDescription} from "./descriptions"; import {getEnvContext} from "./env"; import {getGithubContext} from "./github"; import {getInputsContext} from "./inputs"; @@ -13,7 +14,7 @@ import {getStrategyContext} from "./strategy"; // ContextValue is the type of the value returned by a context provider // Null indicates that the context provider doesn't have any value to provide -export type ContextValue = data.Dictionary | data.Null; +export type ContextValue = DescriptionDictionary | data.Null; export enum Mode { Completion, @@ -26,12 +27,12 @@ export async function getContext( config: ContextProviderConfig | undefined, workflowContext: WorkflowContext, mode: Mode -): Promise { - const context = new data.Dictionary(); +): Promise { + const context = new DescriptionDictionary(); const filteredNames = filterContextNames(names, workflowContext); for (const contextName of filteredNames) { - let value = getDefaultContext(contextName, workflowContext, mode) || new data.Dictionary(); + let value = getDefaultContext(contextName, workflowContext, mode) || new DescriptionDictionary(); if (value.kind === Kind.Null) { context.add(contextName, value); continue; @@ -75,7 +76,11 @@ function getDefaultContext(name: string, workflowContext: WorkflowContext, mode: }); case "secrets": - return objectToDictionary({GITHUB_TOKEN: "***"}); + return new DescriptionDictionary({ + key: "GITHUB_TOKEN", + value: new data.StringData("***"), + description: getDescription("secrets", "GITHUB_TOKEN") + }); case "steps": return getStepsContext(workflowContext); @@ -87,8 +92,9 @@ function getDefaultContext(name: string, workflowContext: WorkflowContext, mode: return undefined; } -function objectToDictionary(object: {[key: string]: string}): data.Dictionary { - const dictionary = new data.Dictionary(); +function objectToDictionary(object: {[key: string]: string}): DescriptionDictionary { + const dictionary = new DescriptionDictionary(); + for (const key in object) { dictionary.add(key, new data.StringData(object[key])); } diff --git a/actions-languageservice/src/context-providers/descriptions.json b/actions-languageservice/src/context-providers/descriptions.json new file mode 100644 index 0000000..1439451 --- /dev/null +++ b/actions-languageservice/src/context-providers/descriptions.json @@ -0,0 +1,148 @@ + +{ + "$schema": "./descriptionsSchema.json", + "github": { + "action": { + "description": "The name of the action currently running, or the [`id`](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsid) of a step. GitHub Actions removes special characters, and uses the name `__run` when the current step runs a script without an `id`. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name `__run`, and the second script will be named `__run_2`. Similarly, the second invocation of `actions/checkout` will be `actionscheckout2`." + }, + "action_path": { + "description": "The path where an action is located. This property is only supported in composite actions. You can use this path to access files located in the same repository as the action." + }, + "action_ref": { + "description": "For a step executing an action, this is the ref of the action being executed. For example, `v2`." + }, + "action_repository": { + "description": "For a step executing an action, this is the owner and repository name of the action. For example, `actions/checkout`." + }, + "action_status": { + "description": "For a composite action, the current result of the composite action." + }, + "actor": { + "description": "The username of the user that triggered the initial workflow run. If the workflow run is a re-run, this value may differ from `github.triggering_actor`. Any workflow re-runs will use the privileges of `github.actor`, even if the actor initiating the re-run (`github.triggering_actor`) has different privileges." + }, + "api_url": { + "description": "The URL of the GitHub Actions REST API." + }, + "base_ref": { + "description": "The `base_ref` or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either `pull_request` or `pull_request_target`." + }, + "env": { + "description": "Path on the runner to the file that sets environment variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see [Workflow commands](https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#setting-an-environment-variable)." + }, + "event": { + "description": "The full event webhook payload. You can access individual properties of the event using this context. This object is identical to the webhook payload of the event that triggered the workflow run, and is different for each event. The webhooks for each GitHub Actions event is linked in [Event that trigger workflows](/articles/events-that-trigger-workflows/). For example, for a workflow run triggered by the [`push` event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push), this object contains the contents of the [push webhook payload](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push)." + }, + "event_name": { + "description": "The name of the event that triggered the workflow run." + }, + "event_path": { + "description": "The path to the file on the runner that contains the full event webhook payload." + }, + "graphql_url": { + "description": "The URL of the GitHub Actions GraphQL API." + }, + "head_ref": { + "description": "The `head_ref` or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either `pull_request` or `pull_request_target`." + }, + "job": { + "description": "The [`job_id`](/actions/reference/workflow-syntax-for-github-actions#jobsjob_id) of the current job.
Note: This context property is set by the Actions runner, and is only available within the execution `steps` of a job. Otherwise, the value of this property will be `null`." + }, + "ref": { + "description": "The fully-formed ref of the branch or tag that triggered the workflow run. For workflows triggered by `push`, this is the branch or tag ref that was pushed. For workflows triggered by `pull_request`, this is the pull request merge branch. For workflows triggered by `release`, this is the release tag created. For other triggers, this is the branch or tag ref that triggered the workflow run. This is only set if a branch or tag is available for the event type. The ref given is fully-formed, meaning that for branches the format is `refs/heads/`, for pull requests it is `refs/pull//merge`, and for tags it is `refs/tags/`. For example, `refs/heads/feature-branch-1`.", + "versions": { + "ghes": "3.3", + "ghae": "3.3" + } + }, + "ref_name": { + "description": "The short ref name of the branch or tag that triggered the workflow run. This value matches the branch or tag name shown on GitHub. For example, `feature-branch-1`.", + "versions": { + "ghes": "3.3", + "ghae": "3.3" + } + }, + "ref_protected": { + "description": "`true` if branch protections are configured for the ref that triggered the workflow run.", + "versions": { + "ghes": "3.3", + "ghae": "3.3" + } + }, + "ref_type": { + "description": "The type of ref that triggered the workflow run. Valid values are `branch` or `tag`.", + "versions": { + "ghes": "3.3", + "ghae": "3.3" + } + }, + "path": { + "description": "Path on the runner to the file that sets system `PATH` variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see [Workflow commands](https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#adding-a-system-path)." + }, + "repository": { + "description": "The owner and repository name. For example, `Codertocat/Hello-World`." + }, + "repository_owner": { + "description": "The repository owner's name. For example, `Codertocat`." + }, + "repositoryUrl": { + "description": "The Git URL to the repository. For example, `git://github.com/codertocat/hello-world.git`." + }, + "retention_days": { + "description": "The number of days that workflow run logs and artifacts are kept." + }, + "run_id": { + "description": "A unique number for each workflow run within a repository. This number does not change if you re-run the workflow run." + }, + "run_number": { + "description": "A unique number for each run of a particular workflow in a repository. This number begins at 1 for the workflow's first run, and increments with each new run. This number does not change if you re-run the workflow run." + }, + "run_attempt": { + "description": "A unique number for each attempt of a particular workflow run in a repository. This number begins at 1 for the workflow run's first attempt, and increments with each re-run.", + "versions": { + "ghes": "3.5", + "ghae": "3.4" + } + }, + "secret_source": { + "description": "The source of a secret used in a workflow. Possible values are `None`, `Actions`, `Dependabot`, or `Codespaces`.", + "versions": { + "ghes": "3.3", + "ghae": "3.3" + } + }, + "server_url": { + "description": "The URL of the GitHub server. For example: `https://github.com`." + }, + "sha": { + "description": "The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see [Events that trigger workflows.](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) For example, `ffac537e6cbbf934b08745a378932722df287a53`." + }, + "token": { + "description": "A token to authenticate on behalf of the GitHub App installed on your repository. This is functionally equivalent to the `GITHUB_TOKEN` secret. For more information, see [Automatic token authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication).\nNote: This context property is set by the Actions runner, and is only available within the execution `steps` of a job. Otherwise, the value of this property will be `null`." + }, + "triggering_actor": { + "description": "The username of the user that initiated the workflow run. If the workflow run is a re-run, this value may differ from `github.actor`. Any workflow re-runs will use the privileges of `github.actor`, even if the actor initiating the re-run (`github.triggering_actor`) has different privileges." + }, + "workflow": { + "description": "The name of the workflow. If the workflow file doesn't specify a `name`, the value of this property is the full path of the workflow file in the repository." + }, + "workspace": { + "description": "The default working directory on the runner for steps, and the default location of your repository when using the [`checkout`](https://github.com/actions/checkout) action." + } + }, + "secrets": { + "GITHUB_TOKEN": { + "description": "`GITHUB_TOKEN` is a secret that is automatically created for every workflow run, and is always included in the secrets context. For more information, see [Automatic token authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication)." + } + }, + "steps": { + "outputs": { + "description": "The set of outputs defined for the step." + }, + "conclusion": { + "description": "The result of a completed step after `continue-on-error` is applied. Possible values are `success`, `failure`, `cancelled`, or `skipped`. When a `continue-on-error` step fails, the `outcome` is `failure`, but the final conclusion is `success`." + }, + "outcome": { + "description": "The result of a completed step before `continue-on-error` is applied. Possible values are `success`, `failure`, `cancelled`, or `skipped`. When a `continue-on-error` step fails, the `outcome` is `failure`, but the final conclusion is `success`." + } + } +} \ No newline at end of file diff --git a/actions-languageservice/src/context-providers/descriptions.ts b/actions-languageservice/src/context-providers/descriptions.ts new file mode 100644 index 0000000..73b5281 --- /dev/null +++ b/actions-languageservice/src/context-providers/descriptions.ts @@ -0,0 +1,12 @@ +import descriptions from "./descriptions.json"; + +/** + * Get a description for a built-in context + * @param context Name of the context, for example `github` + * @param key Key of the context, for example `actor` + * @returns Description if one is found, otherwise undefined + */ +export function getDescription(context: string, key: string): string | undefined { + // The inferred type doesn't quite match the actual type, use any to work around that + return (descriptions as any)[context]?.[key]?.description; +} diff --git a/actions-languageservice/src/context-providers/descriptionsSchema.json b/actions-languageservice/src/context-providers/descriptionsSchema.json new file mode 100644 index 0000000..3c27594 --- /dev/null +++ b/actions-languageservice/src/context-providers/descriptionsSchema.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "$schema": { + "type": "string", + "$comment": "Ignore this, just to make VS Code happy" + } + }, + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "versions": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "description" + ] + } + } +} \ No newline at end of file diff --git a/actions-languageservice/src/context-providers/env.ts b/actions-languageservice/src/context-providers/env.ts index 41eda1f..5aa22cb 100644 --- a/actions-languageservice/src/context-providers/env.ts +++ b/actions-languageservice/src/context-providers/env.ts @@ -1,10 +1,10 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {isScalar, isString} from "@github/actions-workflow-parser"; -import {WorkflowContext} from "../context/workflow-context"; import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/mapping-token"; +import {WorkflowContext} from "../context/workflow-context"; -export function getEnvContext(workflowContext: WorkflowContext): data.Dictionary { - const d = new data.Dictionary(); +export function getEnvContext(workflowContext: WorkflowContext): DescriptionDictionary { + const d = new DescriptionDictionary(); //step env if (workflowContext.step?.env) { diff --git a/actions-languageservice/src/context-providers/github.ts b/actions-languageservice/src/context-providers/github.ts index 9695a50..14a9e69 100644 --- a/actions-languageservice/src/context-providers/github.ts +++ b/actions-languageservice/src/context-providers/github.ts @@ -1,11 +1,12 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {ExpressionData} from "@github/actions-expressions/data/expressiondata"; import {WorkflowContext} from "../context/workflow-context"; +import {getDescription} from "./descriptions"; import {eventPayloads} from "./events/eventPayloads"; import {getInputsContext} from "./inputs"; -export function getGithubContext(workflowContext: WorkflowContext): data.Dictionary { - // https://docs.github.com/en/actions/learn-github-actions/contexts#github-context +export function getGithubContext(workflowContext: WorkflowContext): DescriptionDictionary { + // https://docs.github.com/en/actions/learn-github-actions/contexts#github-cwontext const keys = [ "action", "action_path", @@ -43,13 +44,23 @@ export function getGithubContext(workflowContext: WorkflowContext): data.Diction "workspace" ]; - return new data.Dictionary( + return new DescriptionDictionary( ...keys.map(key => { + const description = getDescription("github", key); + if (key == "event") { - return {key, value: getEventContext(workflowContext)}; + return { + key, + value: getEventContext(workflowContext), + description + }; } - return {key, value: new data.Null()}; + return { + key, + value: new data.Null(), + description + }; }) ); } diff --git a/actions-languageservice/src/context-providers/inputs.ts b/actions-languageservice/src/context-providers/inputs.ts index 22d08f7..696ca3a 100644 --- a/actions-languageservice/src/context-providers/inputs.ts +++ b/actions-languageservice/src/context-providers/inputs.ts @@ -1,9 +1,9 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {InputConfig} from "@github/actions-workflow-parser/model/workflow-template"; import {WorkflowContext} from "../context/workflow-context"; -export function getInputsContext(workflowContext: WorkflowContext): data.Dictionary { - const d = new data.Dictionary(); +export function getInputsContext(workflowContext: WorkflowContext): DescriptionDictionary { + const d = new DescriptionDictionary(); const events = workflowContext?.template?.events; if (!events) { @@ -23,22 +23,22 @@ export function getInputsContext(workflowContext: WorkflowContext): data.Diction return d; } -function addInputs(d: data.Dictionary, inputs: {[inputName: string]: InputConfig}) { +function addInputs(d: DescriptionDictionary, inputs: {[inputName: string]: InputConfig}) { for (const inputName of Object.keys(inputs)) { const input = inputs[inputName]; switch (input.type) { case "choice": if (input.default) { - d.add(inputName, new data.StringData(input.default as string)); + d.add(inputName, new data.StringData(input.default as string), input.description); } else { // Default to the first input or an empty string - d.add(inputName, new data.StringData((input.options || [""])[0])); + d.add(inputName, new data.StringData((input.options || [""])[0]), input.description); } break; case "environment": if (input.default) { - d.add(inputName, new data.StringData(input.default as string)); + d.add(inputName, new data.StringData(input.default as string), input.description); } else { // For now default to an empty value if there is no default value. This will always be an environment, so // we could also dynamically look up environments and default to the first one, but leaving this as a @@ -48,12 +48,12 @@ function addInputs(d: data.Dictionary, inputs: {[inputName: string]: InputConfig break; case "boolean": - d.add(inputName, new data.BooleanData((input.default as boolean) || false)); + d.add(inputName, new data.BooleanData((input.default as boolean) || false), input.description); break; case "string": default: - d.add(inputName, new data.StringData((input.default as string) || inputName)); + d.add(inputName, new data.StringData((input.default as string) || inputName), input.description); break; } } diff --git a/actions-languageservice/src/context-providers/job.ts b/actions-languageservice/src/context-providers/job.ts index 89d31c2..6c37ab6 100644 --- a/actions-languageservice/src/context-providers/job.ts +++ b/actions-languageservice/src/context-providers/job.ts @@ -1,11 +1,11 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {isMapping, isSequence} from "@github/actions-workflow-parser"; import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/mapping-token"; import {WorkflowContext} from "../context/workflow-context"; -export function getJobContext(workflowContext: WorkflowContext): data.Dictionary { +export function getJobContext(workflowContext: WorkflowContext): DescriptionDictionary { // https://docs.github.com/en/actions/learn-github-actions/contexts#job-context - const jobContext = new data.Dictionary(); + const jobContext = new DescriptionDictionary(); const job = workflowContext.job; if (!job) { return jobContext; @@ -21,7 +21,7 @@ export function getJobContext(workflowContext: WorkflowContext): data.Dictionary // Services const jobServices = job.services; if (jobServices && isMapping(jobServices)) { - const servicesContext = new data.Dictionary(); + const servicesContext = new DescriptionDictionary(); for (const service of jobServices) { if (!isMapping(service.value)) { continue; diff --git a/actions-languageservice/src/context-providers/matrix.test.ts b/actions-languageservice/src/context-providers/matrix.test.ts index 0aa68cb..6b8bd99 100644 --- a/actions-languageservice/src/context-providers/matrix.test.ts +++ b/actions-languageservice/src/context-providers/matrix.test.ts @@ -1,7 +1,6 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {Job} from "@github/actions-workflow-parser/model/workflow-template"; import {BasicExpressionToken} from "@github/actions-workflow-parser/templates/tokens/basic-expression-token"; -import {ExpressionToken} from "@github/actions-workflow-parser/templates/tokens/expression-token"; 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"; @@ -64,7 +63,7 @@ describe("matrix context", () => { expect(workflowContext.job).toBeUndefined(); const context = getMatrixContext(workflowContext, Mode.Validation); - expect(context).toEqual(new data.Dictionary()); + expect(context).toEqual(new DescriptionDictionary()); }); it("strategy not defined", () => { @@ -73,7 +72,7 @@ describe("matrix context", () => { expect(workflowContext.job!.strategy).toBeUndefined(); const context = getMatrixContext(workflowContext, Mode.Validation); - expect(context).toEqual(new data.Dictionary()); + expect(context).toEqual(new DescriptionDictionary()); }); it("strategy is not a mapping token", () => { @@ -81,7 +80,7 @@ describe("matrix context", () => { expect(workflowContext.job!.strategy).toBeDefined(); const context = getMatrixContext(workflowContext, Mode.Validation); - expect(context).toEqual(new data.Dictionary()); + expect(context).toEqual(new DescriptionDictionary()); }); it("matrix is not defined", () => { @@ -107,7 +106,7 @@ describe("matrix context", () => { const workflowContext = contextFromStrategy(strategy); const context = getMatrixContext(workflowContext, Mode.Validation); - expect(context).toEqual(new data.Dictionary()); + expect(context).toEqual(new DescriptionDictionary()); }); }); @@ -161,7 +160,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Completion); expect(context).toEqual( - new data.Dictionary({ + new DescriptionDictionary({ key: "node", value: new data.Array(new data.StringData("12"), new data.StringData("14")) }) @@ -181,7 +180,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); expect(context).toEqual( - new data.Dictionary({ + new DescriptionDictionary({ key: "version", value: new data.Null() }) @@ -195,7 +194,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); expect(context).toEqual( - new data.Dictionary({ + new DescriptionDictionary({ key: "os", value: new data.Array(new data.StringData("ubuntu-latest"), new data.StringData("windows-latest")) }) @@ -210,7 +209,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); expect(context).toEqual( - new data.Dictionary( + new DescriptionDictionary( { key: "os", value: new data.Array(new data.StringData("ubuntu-latest"), new data.StringData("windows-latest")) @@ -238,7 +237,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); expect(context).toEqual( - new data.Dictionary( + new DescriptionDictionary( { key: "os", value: new data.Array( @@ -272,7 +271,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); expect(context).toEqual( - new data.Dictionary( + new DescriptionDictionary( { key: "site", value: new data.Array(new data.StringData("production"), new data.StringData("staging")) @@ -306,7 +305,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); expect(context).toEqual( - new data.Dictionary( + new DescriptionDictionary( { key: "os", value: new data.Array(new data.StringData("macos-latest"), new data.StringData("windows-latest")) @@ -340,7 +339,7 @@ describe("matrix context", () => { const context = getMatrixContext(workflowContext, Mode.Validation); - expect(context).toEqual(new data.Dictionary()); + expect(context).toEqual(new DescriptionDictionary()); }); }); }); diff --git a/actions-languageservice/src/context-providers/matrix.ts b/actions-languageservice/src/context-providers/matrix.ts index 99b37b9..b233d57 100644 --- a/actions-languageservice/src/context-providers/matrix.ts +++ b/actions-languageservice/src/context-providers/matrix.ts @@ -1,4 +1,4 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {isBasicExpression, isMapping, isSequence, isString} from "@github/actions-workflow-parser"; import {KeyValuePair} from "@github/actions-workflow-parser/templates/tokens/key-value-pair"; import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/mapping-token"; @@ -10,7 +10,7 @@ export function getMatrixContext(workflowContext: WorkflowContext, mode: Mode): // https://docs.github.com/en/actions/learn-github-actions/contexts#matrix-context const strategy = workflowContext.job?.strategy; if (!strategy || !isMapping(strategy)) { - return new data.Dictionary(); + return new DescriptionDictionary(); } const matrix = strategy.find("matrix"); @@ -25,7 +25,7 @@ export function getMatrixContext(workflowContext: WorkflowContext, mode: Mode): return new data.Null(); } - const d = new data.Dictionary(); + const d = new DescriptionDictionary(); for (const [key, value] of properties) { if (value === undefined) { d.add(key, new data.Null()); diff --git a/actions-languageservice/src/context-providers/needs.ts b/actions-languageservice/src/context-providers/needs.ts index af11b9d..e6cb66d 100644 --- a/actions-languageservice/src/context-providers/needs.ts +++ b/actions-languageservice/src/context-providers/needs.ts @@ -1,10 +1,10 @@ -import {data} from "@github/actions-expressions"; +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 {WorkflowContext} from "../context/workflow-context"; -export function getNeedsContext(workflowContext: WorkflowContext): data.Dictionary { - const d = new data.Dictionary(); +export function getNeedsContext(workflowContext: WorkflowContext): DescriptionDictionary { + const d = new DescriptionDictionary(); if (!workflowContext.job || !workflowContext.job.needs) { return d; } @@ -17,9 +17,9 @@ export function getNeedsContext(workflowContext: WorkflowContext): data.Dictiona return d; } -function needsJobContext(job?: Job): data.Dictionary { +function needsJobContext(job?: Job): DescriptionDictionary { // https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context - const d = new data.Dictionary(); + const d = new DescriptionDictionary(); d.add("outputs", jobOutputs(job)); @@ -28,8 +28,8 @@ function needsJobContext(job?: Job): data.Dictionary { return d; } -function jobOutputs(job?: Job): data.Dictionary { - const d = new data.Dictionary(); +function jobOutputs(job?: Job): DescriptionDictionary { + const d = new DescriptionDictionary(); if (!job?.outputs) { return d; } diff --git a/actions-languageservice/src/context-providers/steps.ts b/actions-languageservice/src/context-providers/steps.ts index beb7217..b07b18e 100644 --- a/actions-languageservice/src/context-providers/steps.ts +++ b/actions-languageservice/src/context-providers/steps.ts @@ -1,9 +1,10 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; 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): data.Dictionary { - const d = new data.Dictionary(); +export function getStepsContext(workflowContext: WorkflowContext): DescriptionDictionary { + const d = new DescriptionDictionary(); if (!workflowContext.job?.steps) { return d; } @@ -26,15 +27,15 @@ export function getStepsContext(workflowContext: WorkflowContext): data.Dictiona return d; } -function stepContext(): data.Dictionary { +function stepContext(): DescriptionDictionary { // https://docs.github.com/en/actions/learn-github-actions/contexts#steps-context - const d = new data.Dictionary(); + const d = new DescriptionDictionary(); - d.add("outputs", new data.Null()); + d.add("outputs", new data.Null(), getDescription("steps", "outputs")); // Can be "success", "failure", "cancelled", or "skipped" - d.add("conclusion", new data.Null()); - d.add("outcome", new data.Null()); + d.add("conclusion", new data.Null(), getDescription("steps", "conclusion")); + d.add("outcome", new data.Null(), getDescription("steps", "outcome")); return d; } diff --git a/actions-languageservice/src/context-providers/strategy.ts b/actions-languageservice/src/context-providers/strategy.ts index 0142cf0..0090936 100644 --- a/actions-languageservice/src/context-providers/strategy.ts +++ b/actions-languageservice/src/context-providers/strategy.ts @@ -1,22 +1,22 @@ -import {data} from "@github/actions-expressions"; +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {isMapping, isScalar, isString} from "@github/actions-workflow-parser"; import {WorkflowContext} from "../context/workflow-context"; import {scalarToData} from "../utils/scalar-to-data"; -export function getStrategyContext(workflowContext: WorkflowContext): data.Dictionary { +export function getStrategyContext(workflowContext: WorkflowContext): DescriptionDictionary { // https://docs.github.com/en/actions/learn-github-actions/contexts#strategy-context const keys = ["fail-fast", "job-index", "job-total", "max-parallel"]; const strategy = workflowContext.job?.strategy; if (!strategy || !isMapping(strategy)) { - return new data.Dictionary( + return new DescriptionDictionary( ...keys.map(key => { return {key, value: new data.Null()}; }) ); } - const strategyContext = new data.Dictionary(); + const strategyContext = new DescriptionDictionary(); for (const pair of strategy) { if (!isString(pair.key)) { continue; From c5029e72878db1f4e2f1f44c6c31756082e976e9 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 09:59:36 -0800 Subject: [PATCH 05/50] Remove double await Co-authored-by: Josh Gross --- actions-languageserver/src/context-providers/secrets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions-languageserver/src/context-providers/secrets.ts b/actions-languageserver/src/context-providers/secrets.ts index d979375..25b923f 100644 --- a/actions-languageserver/src/context-providers/secrets.ts +++ b/actions-languageserver/src/context-providers/secrets.ts @@ -13,7 +13,7 @@ export async function getSecrets( environmentSecrets: StringData[]; }> { return { - repoSecrets: await await cache.get(`${repo.owner}/${repo.name}/secrets`, undefined, () => + repoSecrets: await cache.get(`${repo.owner}/${repo.name}/secrets`, undefined, () => fetchSecrets(octokit, repo.owner, repo.name) ), environmentSecrets: From 4ff09b2a8adcd18cc9e724e308aedb82b012ab9a Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 10:59:06 -0800 Subject: [PATCH 06/50] Move description dictionary to a new file --- actions-expressions/src/completion.test.ts | 3 +- actions-expressions/src/completion.ts | 33 ++----------------- .../completion/descriptionDictionary.test.ts | 30 +++++++++++++++++ .../src/completion/descriptionDictionary.ts | 32 ++++++++++++++++++ actions-expressions/src/index.ts | 3 +- 5 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 actions-expressions/src/completion/descriptionDictionary.test.ts create mode 100644 actions-expressions/src/completion/descriptionDictionary.ts diff --git a/actions-expressions/src/completion.test.ts b/actions-expressions/src/completion.test.ts index 9a4257d..559f540 100644 --- a/actions-expressions/src/completion.test.ts +++ b/actions-expressions/src/completion.test.ts @@ -1,4 +1,5 @@ -import {complete, CompletionItem, DescriptionDictionary, trimTokenVector} from "./completion"; +import {complete, CompletionItem, trimTokenVector} from "./completion"; +import {DescriptionDictionary} from "./completion/descriptionDictionary"; import {BooleanData} from "./data/boolean"; import {Dictionary} from "./data/dictionary"; import {StringData} from "./data/string"; diff --git a/actions-expressions/src/completion.ts b/actions-expressions/src/completion.ts index f647dfa..b6a965b 100644 --- a/actions-expressions/src/completion.ts +++ b/actions-expressions/src/completion.ts @@ -1,5 +1,6 @@ +import {DescriptionPair} from "./completion/descriptionDictionary"; import {Dictionary, isDictionary} from "./data/dictionary"; -import {ExpressionData, Kind, Pair} from "./data/expressiondata"; +import {ExpressionData} from "./data/expressiondata"; import {Evaluator} from "./evaluator"; import {wellKnownFunctions} from "./funcs"; import {FunctionInfo} from "./funcs/info"; @@ -12,36 +13,6 @@ export type CompletionItem = { function: boolean; }; -export type DescriptionPair = Pair & {description?: string}; - -export class DescriptionDictionary extends Dictionary { - private readonly descriptions = new Map(); - - constructor(...pairs: DescriptionPair[]) { - super(); - - for (const p of pairs) { - this.add(p.key, p.value, p.description); - } - } - - override add(key: string, value: ExpressionData, description?: string): void { - super.add(key, value); - if (description) { - this.descriptions.set(key, description); - } - } - - override pairs(): DescriptionPair[] { - const pairs = super.pairs(); - return pairs.map(p => ({...p, description: this.descriptions.get(p.key)})); - } -} - -export function isDescriptionDictionary(x: ExpressionData): x is DescriptionDictionary { - return x.kind === Kind.Dictionary && x instanceof DescriptionDictionary; -} - // Complete returns a list of completion items for the given expression. // // The main functionality is auto-completing functions and context access: diff --git a/actions-expressions/src/completion/descriptionDictionary.test.ts b/actions-expressions/src/completion/descriptionDictionary.test.ts new file mode 100644 index 0000000..960c289 --- /dev/null +++ b/actions-expressions/src/completion/descriptionDictionary.test.ts @@ -0,0 +1,30 @@ +import {StringData} from "../data"; +import {DescriptionDictionary} from "./descriptionDictionary"; + +describe("description dictionary", () => { + it("pairs contains all values", () => { + const d = new DescriptionDictionary(); + d.add("ABC", new StringData("val")); + + expect(d.pairs()).toEqual([{key: "ABC", value: new StringData("val")}]); + }); + + it("does not add duplicate entries", () => { + const d = new DescriptionDictionary(); + d.add("ABC", new StringData("val1")); + d.add("abc", new StringData("val2")); + + expect(d.pairs()).toEqual([{key: "ABC", value: new StringData("val1")}]); + }); + + it("can set optional descriptions", () => { + const d = new DescriptionDictionary(); + d.add("ABC", new StringData("val"), "desc"); + d.add("DEF", new StringData("val")); + + expect(d.pairs()).toEqual([ + {key: "ABC", value: new StringData("val"), description: "desc"}, + {key: "DEF", value: new StringData("val")} + ]); + }); +}); diff --git a/actions-expressions/src/completion/descriptionDictionary.ts b/actions-expressions/src/completion/descriptionDictionary.ts new file mode 100644 index 0000000..8e07bb3 --- /dev/null +++ b/actions-expressions/src/completion/descriptionDictionary.ts @@ -0,0 +1,32 @@ +import {Dictionary} from "../data/dictionary"; +import {ExpressionData, Kind, Pair} from "../data/expressiondata"; + +export type DescriptionPair = Pair & {description?: string}; + +export function isDescriptionDictionary(x: ExpressionData): x is DescriptionDictionary { + return x.kind === Kind.Dictionary && x instanceof DescriptionDictionary; +} + +export class DescriptionDictionary extends Dictionary { + private readonly descriptions = new Map(); + + constructor(...pairs: DescriptionPair[]) { + super(); + + for (const p of pairs) { + this.add(p.key, p.value, p.description); + } + } + + override add(key: string, value: ExpressionData, description?: string): void { + super.add(key, value); + if (description) { + this.descriptions.set(key, description); + } + } + + override pairs(): DescriptionPair[] { + const pairs = super.pairs(); + return pairs.map(p => ({...p, description: this.descriptions.get(p.key)})); + } +} diff --git a/actions-expressions/src/index.ts b/actions-expressions/src/index.ts index 53fc82a..06eda82 100644 --- a/actions-expressions/src/index.ts +++ b/actions-expressions/src/index.ts @@ -1,5 +1,6 @@ export {Expr} from "./ast"; -export {complete, CompletionItem, DescriptionDictionary, DescriptionPair, isDescriptionDictionary} from "./completion"; +export {complete, CompletionItem} from "./completion"; +export {DescriptionDictionary, DescriptionPair, isDescriptionDictionary} from "./completion/descriptionDictionary"; export * as data from "./data"; export {ExpressionError} from "./errors"; export {Evaluator} from "./evaluator"; From 28aac582c23a9629bff766f68b193acb9efa8920 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 11:27:34 -0800 Subject: [PATCH 07/50] Sort secrets --- .../src/context-providers.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/actions-languageserver/src/context-providers.ts b/actions-languageserver/src/context-providers.ts index 96a4f44..bc45283 100644 --- a/actions-languageserver/src/context-providers.ts +++ b/actions-languageserver/src/context-providers.ts @@ -47,12 +47,18 @@ export function contextProviders( const secrets = await getSecrets(octokit, cache, repo, environmentName); defaultContext = defaultContext || new DescriptionDictionary(); - secrets.repoSecrets.forEach(secret => - defaultContext!.add(secret.value, new data.StringData("***"), "Repository secret") - ); - secrets.environmentSecrets.forEach(secret => - defaultContext!.add(secret.value, new data.StringData("***"), `Secret for environment \`${environmentName}\``) - ); + secrets.repoSecrets + .sort((a, b) => a.value.localeCompare(b.value)) + .forEach(secret => defaultContext!.add(secret.value, new data.StringData("***"), "Repository secret")); + secrets.environmentSecrets + .sort((a, b) => a.value.localeCompare(b.value)) + .forEach(secret => + defaultContext!.add( + secret.value, + new data.StringData("***"), + `Secret for environment \`${environmentName}\`` + ) + ); return defaultContext; } case "steps": { From 436e9ce3266c3d0cca56794be3f5c5a32c578826 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 11:28:12 -0800 Subject: [PATCH 08/50] Link to non language specific docs --- .../src/context-providers/descriptions.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/actions-languageservice/src/context-providers/descriptions.json b/actions-languageservice/src/context-providers/descriptions.json index 1439451..406fde0 100644 --- a/actions-languageservice/src/context-providers/descriptions.json +++ b/actions-languageservice/src/context-providers/descriptions.json @@ -3,7 +3,7 @@ "$schema": "./descriptionsSchema.json", "github": { "action": { - "description": "The name of the action currently running, or the [`id`](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsid) of a step. GitHub Actions removes special characters, and uses the name `__run` when the current step runs a script without an `id`. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name `__run`, and the second script will be named `__run_2`. Similarly, the second invocation of `actions/checkout` will be `actionscheckout2`." + "description": "The name of the action currently running, or the [`id`](https://docs.github.com/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsid) of a step. GitHub Actions removes special characters, and uses the name `__run` when the current step runs a script without an `id`. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name `__run`, and the second script will be named `__run_2`. Similarly, the second invocation of `actions/checkout` will be `actionscheckout2`." }, "action_path": { "description": "The path where an action is located. This property is only supported in composite actions. You can use this path to access files located in the same repository as the action." @@ -27,10 +27,10 @@ "description": "The `base_ref` or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either `pull_request` or `pull_request_target`." }, "env": { - "description": "Path on the runner to the file that sets environment variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see [Workflow commands](https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#setting-an-environment-variable)." + "description": "Path on the runner to the file that sets environment variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see [Workflow commands](https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#setting-an-environment-variable)." }, "event": { - "description": "The full event webhook payload. You can access individual properties of the event using this context. This object is identical to the webhook payload of the event that triggered the workflow run, and is different for each event. The webhooks for each GitHub Actions event is linked in [Event that trigger workflows](/articles/events-that-trigger-workflows/). For example, for a workflow run triggered by the [`push` event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push), this object contains the contents of the [push webhook payload](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push)." + "description": "The full event webhook payload. You can access individual properties of the event using this context. This object is identical to the webhook payload of the event that triggered the workflow run, and is different for each event. The webhooks for each GitHub Actions event is linked in [Event that trigger workflows](/articles/events-that-trigger-workflows/). For example, for a workflow run triggered by the [`push` event](https://docs.github.com/actions/using-workflows/events-that-trigger-workflows#push), this object contains the contents of the [push webhook payload](https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push)." }, "event_name": { "description": "The name of the event that triggered the workflow run." @@ -76,7 +76,7 @@ } }, "path": { - "description": "Path on the runner to the file that sets system `PATH` variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see [Workflow commands](https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#adding-a-system-path)." + "description": "Path on the runner to the file that sets system `PATH` variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see [Workflow commands](https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#adding-a-system-path)." }, "repository": { "description": "The owner and repository name. For example, `Codertocat/Hello-World`." @@ -114,10 +114,10 @@ "description": "The URL of the GitHub server. For example: `https://github.com`." }, "sha": { - "description": "The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see [Events that trigger workflows.](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) For example, `ffac537e6cbbf934b08745a378932722df287a53`." + "description": "The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see [Events that trigger workflows.](https://docs.github.com/actions/using-workflows/events-that-trigger-workflows) For example, `ffac537e6cbbf934b08745a378932722df287a53`." }, "token": { - "description": "A token to authenticate on behalf of the GitHub App installed on your repository. This is functionally equivalent to the `GITHUB_TOKEN` secret. For more information, see [Automatic token authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication).\nNote: This context property is set by the Actions runner, and is only available within the execution `steps` of a job. Otherwise, the value of this property will be `null`." + "description": "A token to authenticate on behalf of the GitHub App installed on your repository. This is functionally equivalent to the `GITHUB_TOKEN` secret. For more information, see [Automatic token authentication](https://docs.github.com/actions/security-guides/automatic-token-authentication).\nNote: This context property is set by the Actions runner, and is only available within the execution `steps` of a job. Otherwise, the value of this property will be `null`." }, "triggering_actor": { "description": "The username of the user that initiated the workflow run. If the workflow run is a re-run, this value may differ from `github.actor`. Any workflow re-runs will use the privileges of `github.actor`, even if the actor initiating the re-run (`github.triggering_actor`) has different privileges." @@ -131,7 +131,7 @@ }, "secrets": { "GITHUB_TOKEN": { - "description": "`GITHUB_TOKEN` is a secret that is automatically created for every workflow run, and is always included in the secrets context. For more information, see [Automatic token authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication)." + "description": "`GITHUB_TOKEN` is a secret that is automatically created for every workflow run, and is always included in the secrets context. For more information, see [Automatic token authentication](https://docs.github.com/actions/security-guides/automatic-token-authentication)." } }, "steps": { From 031e1b474b7dcc59ba951e2ae95becfe59fe7b1f Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 11 Jan 2023 20:05:45 +0000 Subject: [PATCH 09/50] v0.1.81 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 326ae41..86d846f 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.80", + "version": "0.1.81", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index a9ec1b8..d0f7589 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.80", + "version": "0.1.81", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.80", - "@github/actions-workflow-parser": "^0.1.80", + "@github/actions-languageservice": "^0.1.81", + "@github/actions-workflow-parser": "^0.1.81", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index d3d35a8..a8654b0 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.80", + "version": "0.1.81", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.80", - "@github/actions-workflow-parser": "^0.1.80", + "@github/actions-expressions": "^0.1.81", + "@github/actions-workflow-parser": "^0.1.81", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 1fea2a8..5ba4251 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.80", + "version": "0.1.81", "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.80", + "@github/actions-expressions": "^0.1.81", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 0b0ebe6..099e8ba 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.80", + "version": "0.1.81", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.80", + "@github/actions-languageserver": "^0.1.81", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 10449ca..c6f7171 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.80" + "version": "0.1.81" } diff --git a/package-lock.json b/package-lock.json index ba17b07..50fb3ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.80", + "version": "0.1.81", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.80", + "version": "0.1.81", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.80", - "@github/actions-workflow-parser": "^0.1.80", + "@github/actions-languageservice": "^0.1.81", + "@github/actions-workflow-parser": "^0.1.81", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.80", + "version": "0.1.81", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.80", - "@github/actions-workflow-parser": "^0.1.80", + "@github/actions-expressions": "^0.1.81", + "@github/actions-workflow-parser": "^0.1.81", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.80", + "version": "0.1.81", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.80", + "@github/actions-expressions": "^0.1.81", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.80", + "version": "0.1.81", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.80", + "@github/actions-languageserver": "^0.1.81", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.80", - "@github/actions-workflow-parser": "^0.1.80", + "@github/actions-languageservice": "^0.1.81", + "@github/actions-workflow-parser": "^0.1.81", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.80", - "@github/actions-workflow-parser": "^0.1.80", + "@github/actions-expressions": "^0.1.81", + "@github/actions-workflow-parser": "^0.1.81", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.80", + "@github/actions-expressions": "^0.1.81", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.80", + "@github/actions-languageserver": "^0.1.81", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From b322bcb32bfb0e207d6c7da005951a8da1e1ed1a Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 13:28:53 -0800 Subject: [PATCH 10/50] Do not add duplicate entries to description dictionary --- .../src/completion/descriptionDictionary.test.ts | 3 ++- actions-expressions/src/completion/descriptionDictionary.ts | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/actions-expressions/src/completion/descriptionDictionary.test.ts b/actions-expressions/src/completion/descriptionDictionary.test.ts index 960c289..67811f4 100644 --- a/actions-expressions/src/completion/descriptionDictionary.test.ts +++ b/actions-expressions/src/completion/descriptionDictionary.test.ts @@ -12,7 +12,8 @@ describe("description dictionary", () => { it("does not add duplicate entries", () => { const d = new DescriptionDictionary(); d.add("ABC", new StringData("val1")); - d.add("abc", new StringData("val2")); + d.add("ABC", new StringData("val2")); + d.add("abc", new StringData("val3")); expect(d.pairs()).toEqual([{key: "ABC", value: new StringData("val1")}]); }); diff --git a/actions-expressions/src/completion/descriptionDictionary.ts b/actions-expressions/src/completion/descriptionDictionary.ts index 8e07bb3..08a4eda 100644 --- a/actions-expressions/src/completion/descriptionDictionary.ts +++ b/actions-expressions/src/completion/descriptionDictionary.ts @@ -19,6 +19,11 @@ export class DescriptionDictionary extends Dictionary { } override add(key: string, value: ExpressionData, description?: string): void { + if (this.get(key) !== undefined) { + // Key already added, ignore + return; + } + super.add(key, value); if (description) { this.descriptions.set(key, description); From e3a450dde7521c9dd1cfe9fd4116753df9a956a5 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 13:29:02 -0800 Subject: [PATCH 11/50] Sort and merge secrets --- .../src/context-providers.ts | 41 ++---------- .../src/context-providers/secrets.ts | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/actions-languageserver/src/context-providers.ts b/actions-languageserver/src/context-providers.ts index bc45283..c0824ce 100644 --- a/actions-languageserver/src/context-providers.ts +++ b/actions-languageserver/src/context-providers.ts @@ -1,7 +1,6 @@ -import {data, DescriptionDictionary} from "@github/actions-expressions"; +import {DescriptionDictionary} from "@github/actions-expressions"; import {ContextProviderConfig} from "@github/actions-languageservice"; import {WorkflowContext} from "@github/actions-languageservice/context/workflow-context"; -import {isMapping, isString} from "@github/actions-workflow-parser"; import {Octokit} from "@octokit/rest"; import {getSecrets} from "./context-providers/secrets"; import {getStepsContext} from "./context-providers/steps"; @@ -27,43 +26,11 @@ export function contextProviders( workflowContext: WorkflowContext ) => { switch (name) { - case "secrets": { - let environmentName: string | undefined; - if (workflowContext?.job?.environment) { - if (isString(workflowContext.job.environment)) { - environmentName = workflowContext.job.environment.value; - } else if (isMapping(workflowContext.job.environment)) { - for (const x of workflowContext.job.environment) { - if (isString(x.key) && x.key.value === "name") { - if (isString(x.value)) { - environmentName = x.value.value; - } - break; - } - } - } - } + case "secrets": + return await getSecrets(workflowContext, octokit, cache, repo, defaultContext); - const secrets = await getSecrets(octokit, cache, repo, environmentName); - - defaultContext = defaultContext || new DescriptionDictionary(); - secrets.repoSecrets - .sort((a, b) => a.value.localeCompare(b.value)) - .forEach(secret => defaultContext!.add(secret.value, new data.StringData("***"), "Repository secret")); - secrets.environmentSecrets - .sort((a, b) => a.value.localeCompare(b.value)) - .forEach(secret => - defaultContext!.add( - secret.value, - new data.StringData("***"), - `Secret for environment \`${environmentName}\`` - ) - ); - return defaultContext; - } - case "steps": { + case "steps": return await getStepsContext(octokit, cache, defaultContext, workflowContext); - } } }; diff --git a/actions-languageserver/src/context-providers/secrets.ts b/actions-languageserver/src/context-providers/secrets.ts index 25b923f..c8c262a 100644 --- a/actions-languageserver/src/context-providers/secrets.ts +++ b/actions-languageserver/src/context-providers/secrets.ts @@ -1,9 +1,74 @@ +import {data, DescriptionDictionary} from "@github/actions-expressions"; import {StringData} from "@github/actions-expressions/data/string"; +import {WorkflowContext} from "@github/actions-languageservice/context/workflow-context"; +import {isMapping, isString} from "@github/actions-workflow-parser"; import {Octokit} from "@octokit/rest"; import {RepositoryContext} from "../initializationOptions"; import {TTLCache} from "../utils/cache"; export async function getSecrets( + workflowContext: WorkflowContext, + octokit: Octokit, + cache: TTLCache, + repo: RepositoryContext, + defaultContext: DescriptionDictionary | undefined +): Promise { + let environmentName: string | undefined; + if (workflowContext?.job?.environment) { + if (isString(workflowContext.job.environment)) { + environmentName = workflowContext.job.environment.value; + } else if (isMapping(workflowContext.job.environment)) { + for (const x of workflowContext.job.environment) { + if (isString(x.key) && x.key.value === "name") { + if (isString(x.value)) { + environmentName = x.value.value; + } + break; + } + } + } + } + + const secrets = await getRemoteSecrets(octokit, cache, repo, environmentName); + + // Build combined map of secrets + const secretsMap = new Map< + string, + { + key: string; + value: data.StringData; + description?: string; + } + >(); + + secrets.repoSecrets.forEach(secret => + secretsMap.set(secret.value.toLowerCase(), { + key: secret.value, + value: new data.StringData("***"), + description: "Repository secret" + }) + ); + + // Override repo secrets with environment secrets (if defined) + secrets.environmentSecrets.forEach(secret => + secretsMap.set(secret.value.toLowerCase(), { + key: secret.value, + value: new data.StringData("***"), + description: `Secret for environment \`${environmentName}\`` + }) + ); + + const secretsContext = defaultContext || new DescriptionDictionary(); + + // Sort secrets by key and add to context + Array.from(secretsMap.values()) + .sort((a, b) => a.key.localeCompare(b.key)) + .forEach(secret => secretsContext?.add(secret.key, secret.value, secret.description)); + + return secretsContext; +} + +async function getRemoteSecrets( octokit: Octokit, cache: TTLCache, repo: RepositoryContext, From 70843ea8d4c84a8a67c56ab86226868d1ad300cc Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 11 Jan 2023 13:53:20 -0800 Subject: [PATCH 12/50] Add root level --- .../src/context-providers/default.ts | 4 +- .../src/context-providers/descriptions.json | 38 +++++++++++++++++++ .../src/context-providers/descriptions.ts | 2 + 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/actions-languageservice/src/context-providers/default.ts b/actions-languageservice/src/context-providers/default.ts index eb8c5b8..1d38d99 100644 --- a/actions-languageservice/src/context-providers/default.ts +++ b/actions-languageservice/src/context-providers/default.ts @@ -2,7 +2,7 @@ import {data, DescriptionDictionary} from "@github/actions-expressions"; import {Kind} from "@github/actions-expressions/data/expressiondata"; import {WorkflowContext} from "../context/workflow-context"; import {ContextProviderConfig} from "./config"; -import {getDescription} from "./descriptions"; +import {getDescription, RootContext} from "./descriptions"; import {getEnvContext} from "./env"; import {getGithubContext} from "./github"; import {getInputsContext} from "./inputs"; @@ -40,7 +40,7 @@ export async function getContext( value = (await config?.getContext(contextName, value, workflowContext)) || value; - context.add(contextName, value); + context.add(contextName, value, getDescription(RootContext, contextName)); } return context; diff --git a/actions-languageservice/src/context-providers/descriptions.json b/actions-languageservice/src/context-providers/descriptions.json index 406fde0..f2b35b6 100644 --- a/actions-languageservice/src/context-providers/descriptions.json +++ b/actions-languageservice/src/context-providers/descriptions.json @@ -1,6 +1,44 @@ { "$schema": "./descriptionsSchema.json", + "root": { + "github": { + "description": "Information about the workflow run. For more information, see [`github` context](https://docs.github.com/actions/learn-github-actions/contexts#github-context)." + }, + "env": { + "description": "Contains variables set in a workflow, job, or step. For more information, see [`env` context](https://docs.github.com/actions/learn-github-actions/contexts#env-context)." + }, + "vars": { + "description": "Contains variables set at the repository, organization, or environment levels. For more information, see [`vars` context](https://docs.github.com/actions/learn-github-actions/contexts#vars-context)." + }, + "job": { + "description": "Information about the currently running job. For more information, see [`job` context](https://docs.github.com/actions/learn-github-actions/contexts#job-context)." + }, + "jobs": { + "description": "For reusable workflows only, contains outputs of jobs from the reusable workflow. For more information, see [`jobs` context](https://docs.github.com/actions/learn-github-actions/contexts#jobs-context)." + }, + "steps": { + "description": "Information about the steps that have been run in the current job. For more information, see [`steps` context](https://docs.github.com/actions/learn-github-actions/contexts#steps-context)." + }, + "runner": { + "description": "Information about the runner that is running the current job. For more information, see [`runner` context](https://docs.github.com/actions/learn-github-actions/contexts#runner-context)." + }, + "secrets": { + "description": "Contains the names and values of secrets that are available to a workflow run. For more information, see [`secrets` context](https://docs.github.com/actions/learn-github-actions/contexts#secrets-context)." + }, + "strategy": { + "description": "Information about the matrix execution strategy for the current job. For more information, see [`strategy` context](https://docs.github.com/actions/learn-github-actions/contexts#strategy-context)." + }, + "matrix": { + "description": "Contains the matrix properties defined in the workflow that apply to the current job. For more information, see [`matrix` context](https://docs.github.com/actions/learn-github-actions/contexts#matrix-context)." + }, + "needs": { + "description": "Contains the outputs of all jobs that are defined as a dependency of the current job. For more information, see [`needs` context](https://docs.github.com/actions/learn-github-actions/contexts#needs-context)." + }, + "inputs": { + "description": "Contains the inputs of a reusable or manually triggered workflow. For more information, see [`inputs` context](https://docs.github.com/actions/learn-github-actions/contexts#inputs-context)." + } + }, "github": { "action": { "description": "The name of the action currently running, or the [`id`](https://docs.github.com/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsid) of a step. GitHub Actions removes special characters, and uses the name `__run` when the current step runs a script without an `id`. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name `__run`, and the second script will be named `__run_2`. Similarly, the second invocation of `actions/checkout` will be `actionscheckout2`." diff --git a/actions-languageservice/src/context-providers/descriptions.ts b/actions-languageservice/src/context-providers/descriptions.ts index 73b5281..766a442 100644 --- a/actions-languageservice/src/context-providers/descriptions.ts +++ b/actions-languageservice/src/context-providers/descriptions.ts @@ -1,5 +1,7 @@ import descriptions from "./descriptions.json"; +export const RootContext = "root"; + /** * Get a description for a built-in context * @param context Name of the context, for example `github` From ef56b080b98a20819afb9756a951774999cf83fe Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 11 Jan 2023 22:15:54 +0000 Subject: [PATCH 13/50] v0.1.82 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 86d846f..6b580f6 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.81", + "version": "0.1.82", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index d0f7589..3e8acbc 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.81", + "version": "0.1.82", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.81", - "@github/actions-workflow-parser": "^0.1.81", + "@github/actions-languageservice": "^0.1.82", + "@github/actions-workflow-parser": "^0.1.82", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index a8654b0..aff3631 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.81", + "version": "0.1.82", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.81", - "@github/actions-workflow-parser": "^0.1.81", + "@github/actions-expressions": "^0.1.82", + "@github/actions-workflow-parser": "^0.1.82", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 5ba4251..324a7b8 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.81", + "version": "0.1.82", "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.81", + "@github/actions-expressions": "^0.1.82", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 099e8ba..2a832de 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.81", + "version": "0.1.82", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.81", + "@github/actions-languageserver": "^0.1.82", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index c6f7171..4c3847b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.81" + "version": "0.1.82" } diff --git a/package-lock.json b/package-lock.json index 50fb3ae..42ab15b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.81", + "version": "0.1.82", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.81", + "version": "0.1.82", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.81", - "@github/actions-workflow-parser": "^0.1.81", + "@github/actions-languageservice": "^0.1.82", + "@github/actions-workflow-parser": "^0.1.82", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.81", + "version": "0.1.82", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.81", - "@github/actions-workflow-parser": "^0.1.81", + "@github/actions-expressions": "^0.1.82", + "@github/actions-workflow-parser": "^0.1.82", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.81", + "version": "0.1.82", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.81", + "@github/actions-expressions": "^0.1.82", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.81", + "version": "0.1.82", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.81", + "@github/actions-languageserver": "^0.1.82", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.81", - "@github/actions-workflow-parser": "^0.1.81", + "@github/actions-languageservice": "^0.1.82", + "@github/actions-workflow-parser": "^0.1.82", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.81", - "@github/actions-workflow-parser": "^0.1.81", + "@github/actions-expressions": "^0.1.82", + "@github/actions-workflow-parser": "^0.1.82", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.81", + "@github/actions-expressions": "^0.1.82", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.81", + "@github/actions-languageserver": "^0.1.82", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From c0fc4312f514a3011020381cb6ea7b8abb762c68 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 11 Jan 2023 22:45:07 +0000 Subject: [PATCH 14/50] v0.1.83 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 6b580f6..0d7a847 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.82", + "version": "0.1.83", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 3e8acbc..5304047 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.82", + "version": "0.1.83", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.82", - "@github/actions-workflow-parser": "^0.1.82", + "@github/actions-languageservice": "^0.1.83", + "@github/actions-workflow-parser": "^0.1.83", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index aff3631..2cb99d6 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.82", + "version": "0.1.83", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.82", - "@github/actions-workflow-parser": "^0.1.82", + "@github/actions-expressions": "^0.1.83", + "@github/actions-workflow-parser": "^0.1.83", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 324a7b8..12525e9 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.82", + "version": "0.1.83", "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.82", + "@github/actions-expressions": "^0.1.83", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 2a832de..e5b0539 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.82", + "version": "0.1.83", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.82", + "@github/actions-languageserver": "^0.1.83", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 4c3847b..71c334b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.82" + "version": "0.1.83" } diff --git a/package-lock.json b/package-lock.json index 42ab15b..d6bdc11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.82", + "version": "0.1.83", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.82", + "version": "0.1.83", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.82", - "@github/actions-workflow-parser": "^0.1.82", + "@github/actions-languageservice": "^0.1.83", + "@github/actions-workflow-parser": "^0.1.83", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.82", + "version": "0.1.83", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.82", - "@github/actions-workflow-parser": "^0.1.82", + "@github/actions-expressions": "^0.1.83", + "@github/actions-workflow-parser": "^0.1.83", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.82", + "version": "0.1.83", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.82", + "@github/actions-expressions": "^0.1.83", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.82", + "version": "0.1.83", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.82", + "@github/actions-languageserver": "^0.1.83", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.82", - "@github/actions-workflow-parser": "^0.1.82", + "@github/actions-languageservice": "^0.1.83", + "@github/actions-workflow-parser": "^0.1.83", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.82", - "@github/actions-workflow-parser": "^0.1.82", + "@github/actions-expressions": "^0.1.83", + "@github/actions-workflow-parser": "^0.1.83", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.82", + "@github/actions-expressions": "^0.1.83", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.82", + "@github/actions-languageserver": "^0.1.83", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From 5a4b6219ff74a7f6dc07964a94212f34a4774007 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Fri, 13 Jan 2023 11:27:20 -0800 Subject: [PATCH 15/50] Update schema with descriptions --- .../src/workflow-v1.0.json | 251 +++++++++--------- 1 file changed, 126 insertions(+), 125 deletions(-) diff --git a/actions-workflow-parser/src/workflow-v1.0.json b/actions-workflow-parser/src/workflow-v1.0.json index 9613bd7..d182e0b 100644 --- a/actions-workflow-parser/src/workflow-v1.0.json +++ b/actions-workflow-parser/src/workflow-v1.0.json @@ -41,7 +41,7 @@ } }, "workflow-name": { - "description": "The name of the workflow.", + "description": "The name of the workflow that GitHub displays on your repository's 'Actions' tab.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#name)", "string": {} }, "run-name": { @@ -51,10 +51,10 @@ "vars" ], "string": {}, - "description": "The name for workflow runs generated from the workflow. GitHub displays the workflow run name in the list of workflow runs on your repository's 'Actions' tab." + "description": "The name for workflow runs generated from the workflow. GitHub displays the workflow run name in the list of workflow runs on your repository's 'Actions' tab.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#run-name)" }, "on": { - "description": "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows.", + "description": "The GitHub event that triggers the workflow. Events can be a single string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. View a full list of [events that trigger workflows](https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows).\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on)", "one-of": [ "string", "sequence", @@ -71,7 +71,7 @@ } }, "on-strict": { - "description": "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows.", + "description": "The GitHub event that triggers the workflow. Events can be a single string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. View a full list of [events that trigger workflows](https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows).\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on)", "one-of": [ "on-string-strict", "on-sequence-strict", @@ -79,7 +79,7 @@ ] }, "on-mapping-strict": { - "description": "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows.", + "description": "The GitHub event that triggers the workflow. Events can be a single string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. View a full list of [events that trigger workflows](https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows).\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on)", "mapping": { "properties": { "branch_protection_rule": "branch-protection-rule", @@ -187,7 +187,7 @@ } }, "branch-protection-rule-activity": { - "description": "The types of branch protection rule activity that trigger the workflow. Can be one or more of: created, edited, deleted.", + "description": "The types of branch protection rule activity that trigger the workflow. Supported activity types: `created`, `edited`, `deleted`.", "one-of": [ "branch-protection-rule-activity-type", "branch-protection-rule-activity-types" @@ -226,7 +226,7 @@ } }, "check-run-activity": { - "description": "The types of check run activity that trigger the workflow. Can be one or more of: completed, requested, rerequested, or requested-action.", + "description": "The types of check run activity that trigger the workflow. Supported activity types: `created`, `rerequested`, `completed`, `requested_action`.", "one-of": [ "check-run-activity-type", "check-run-activity-types" @@ -266,10 +266,10 @@ } }, "check-suite-activity": { - "description": "The types of check suite activity that trigger the workflow. Currently only completed is supported.", + "description": "The types of check suite activity that trigger the workflow. Supported activity types: `completed`.", "one-of": [ - "check-suite-activity-type", - "check-suite-activity-types" + "check-suite-activity-type", + "check-suite-activity-types" ] }, "check-suite-activity-types": { @@ -323,13 +323,13 @@ "null": {} }, "discussion-string": { - "description": "Runs your workflow when a discussion in the workflow's repository is created or modified. For activity related to comments on a discussion, use the discussion_comment event.", + "description": "Runs your workflow when a discussion in the workflow's repository is created or modified. For activity related to comments on a discussion, use the `discussion_comment` event.", "string": { "constant": "discussion" } }, "discussion": { - "description": "Runs your workflow when a discussion in the workflow's repository is created or modified. For activity related to comments on a discussion, use the discussion_comment event.", + "description": "Runs your workflow when a discussion in the workflow's repository is created or modified. For activity related to comments on a discussion, use the `discussion_comment` event.", "one-of": [ "null", "discussion-mapping" @@ -343,7 +343,7 @@ } }, "discussion-activity": { - "description": "The types of discussion activity that trigger the workflow. Can be one or more of: created, edited, deleted, transferred, pinned, unpinned, labeled, unlabeled, locked, unlocked, category_changed, answered, or unanswered.", + "description": "The types of discussion activity that trigger the workflow. Supported activity types: `created`, `edited`, `deleted`, `transferred`, `pinned`, `unpinned`, `labeled`, `unlabeled`, `locked`, `unlocked`, `category_changed`, `answered`, `unanswered`.", "one-of": [ "discussion-activity-type", "discussion-activity-types" @@ -372,13 +372,13 @@ ] }, "discussion-comment-string": { - "description": "Runs your workflow when a comment on a discussion in the workflow's repository is created or modified. For activity related to a discussion as opposed to comments on the discussion, use the discussion event.", + "description": "Runs your workflow when a comment on a discussion in the workflow's repository is created or modified. For activity related to a discussion as opposed to comments on the discussion, use the `discussion` event.", "string": { "constant": "discussion_comment" } }, "discussion-comment": { - "description": "Runs your workflow when a comment on a discussion in the workflow's repository is created or modified. For activity related to a discussion as opposed to comments on the discussion, use the discussion event.", + "description": "Runs your workflow when a comment on a discussion in the workflow's repository is created or modified. For activity related to a discussion as opposed to comments on the discussion, use the `discussion` event.", "one-of": [ "null", "discussion-comment-mapping" @@ -392,7 +392,7 @@ } }, "discussion-comment-activity": { - "description": "The types of discussion comment activity that trigger the workflow. Can be one or more of: created, edited, or deleted.", + "description": "The types of discussion comment activity that trigger the workflow. Supported activity types: `created`, `edited`, `deleted`.", "one-of": [ "discussion-comment-activity-type", "discussion-comment-activity-types" @@ -451,7 +451,7 @@ } }, "issue-comment-activity": { - "description": "The types of issue comment activity that trigger the workflow. Can be one or more of: created, edited, or deleted.", + "description": "The types of issue comment activity that trigger the workflow. Supported activity types: `created`, `edited`, `deleted`.", "one-of": [ "issue-comment-activity-type", "issue-comment-activity-types" @@ -470,13 +470,13 @@ ] }, "issues-string": { - "description": "Runs your workflow when an issue or pull request comment is created, edited, or deleted.", + "description": "Runs your workflow when an issue in the workflow's repository is created or modified. For activity related to comments in an issue, use the `issue_comment` event.", "string": { "constant": "issues" } }, "issues": { - "description": "Runs your workflow when an issue or pull request comment is created, edited, or deleted.", + "description": "Runs your workflow when an issue in the workflow's repository is created or modified. For activity related to comments in an issue, use the `issue_comment` event.", "one-of": [ "null", "issues-mapping" @@ -490,7 +490,7 @@ } }, "issues-activity": { - "description": "The types of issue activity that trigger the workflow. Can be one or more of: opened, edited, deleted, transferred, pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, locked, unlocked, milestoned, or demilestoned.", + "description": "The types of issue activity that trigger the workflow. Supported activity types: `opened`, `edited`, `deleted`, `transferred`, `pinned`, `unpinned`, `closed`, `reopened`, `assigned`, `unassigned`, `labeled`, `unlabeled`, `locked`, `unlocked`, `milestoned`, `demilestoned`.", "one-of": [ "issues-activity-type", "issues-activity-types" @@ -542,7 +542,7 @@ } }, "label-activity": { - "description": "The types of label activity that trigger the workflow. Can be one or more of: created, edited, or deleted.", + "description": "The types of label activity that trigger the workflow. Supported activity types: `created`, `edited`, `deleted`.", "one-of": [ "label-activity-type", "label-activity-types" @@ -581,7 +581,7 @@ } }, "merge-group-activity": { - "description": "The types of label activity that trigger the workflow. Currently only checks_requested is supported.", + "description": "The types of merge group activity that trigger the workflow. Supported activity types: `checks_requested`.", "one-of": [ "merge-group-activity-type", "merge-group-activity-types" @@ -618,7 +618,7 @@ } }, "milestone-activity": { - "description": "The types of milestone activity that trigger the workflow. Can be one or more of: created, edited, opened, closed, or deleted.", + "description": "The types of milestone activity that trigger the workflow. Supported activity types: `created`, `closed`, `opened`, `edited`, `deleted`.", "one-of": [ "milestone-activity-type", "milestone-activity-types" @@ -649,13 +649,13 @@ "null": {} }, "project-string": { - "description": "Runs your workflow when a project board is created or modified. For activity related to cards or columns in a project board, use the project_card or project_column events instead.", + "description": "Runs your workflow when a project board is created or modified. For activity related to cards or columns in a project board, use the `project_card` or `project_column` events instead.", "string": { "constant": "project" } }, "project": { - "description": "Runs your workflow when a project board is created or modified. For activity related to cards or columns in a project board, use the project_card or project_column events instead.", + "description": "Runs your workflow when a project board is created or modified. For activity related to cards or columns in a project board, use the `project_card` or `project_column` events instead.", "one-of": [ "null", "project-mapping" @@ -669,7 +669,7 @@ } }, "project-activity": { - "description": "The types of project activity that trigger the workflow. Can be one or more of: created, edited, opened, closed, or deleted.", + "description": "The types of project activity that trigger the workflow. Supported activity types: `created`, `closed`, `reopened`, `edited`, `deleted`.", "one-of": [ "project-activity-type", "project-activity-types" @@ -684,19 +684,19 @@ "allowed-values": [ "created", "closed", - "opened", + "reopened", "edited", "deleted" ] }, "project-card-string": { - "description": "Runs your workflow when a card on a project board is created or modified. For activity related to project boards or columns in a project board, use the project or project_column event instead.", + "description": "Runs your workflow when a card on a project board is created or modified. For activity related to project boards or columns in a project board, use the `project` or `project_column` event instead.", "string": { "constant": "project_card" } }, "project-card": { - "description": "Runs your workflow when a card on a project board is created or modified. For activity related to project boards or columns in a project board, use the project or project_column event instead.", + "description": "Runs your workflow when a card on a project board is created or modified. For activity related to project boards or columns in a project board, use the `project` or `project_column` event instead.", "one-of": [ "null", "project-card-mapping" @@ -710,7 +710,7 @@ } }, "project-card-activity": { - "description": "The types of project card activity that trigger the workflow. Can be one or more of: created, edited, moved, converted, or deleted.", + "description": "The types of project card activity that trigger the workflow. Supported activity types: `created`, `moved`, `converted`, `edited`, `deleted`.", "one-of": [ "project-card-activity-type", "project-card-activity-types" @@ -731,13 +731,13 @@ ] }, "project-column-string": { - "description": "Runs your workflow when a column on a project board is created or modified. For activity related to project boards or cards in a project board, use the project or project_card event instead.", + "description": "Runs your workflow when a column on a project board is created or modified. For activity related to project boards or cards in a project board, use the `project` or `project_card` event instead.", "string": { "constant": "project_column" } }, "project-column": { - "description": "Runs your workflow when a column on a project board is created or modified. For activity related to project boards or cards in a project board, use the project or project_card event instead.", + "description": "Runs your workflow when a column on a project board is created or modified. For activity related to project boards or cards in a project board, use the `project` or `project_card` event instead.", "one-of": [ "null", "project-column-mapping" @@ -751,7 +751,7 @@ } }, "project-column-activity": { - "description": "The types of project column activity that trigger the workflow. Can be one or more of: created, updated, moved, or deleted.", + "description": "The types of project column activity that trigger the workflow. Supported activity types: `created`, `updated`, `moved`, `deleted`.", "one-of": [ "project-column-activity-type", "project-column-activity-types" @@ -781,13 +781,13 @@ "null": {} }, "pull-request-string": { - "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. For example, if no activity types are specified, the workflow runs when a pull request is opened or reopened or when the head branch of the pull request is updated. For activity related to pull request reviews, pull request review comments, or pull request comments, use the pull_request_review, pull_request_review_comment, or issue_comment events instead.", + "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. If no activity types are specified, the workflow runs when a pull request is opened, reopened, or when the head branch of the pull request is updated.", "string": { "constant": "pull_request" } }, "pull-request": { - "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. For example, if no activity types are specified, the workflow runs when a pull request is opened or reopened or when the head branch of the pull request is updated. For activity related to pull request reviews, pull request review comments, or pull request comments, use the pull_request_review, pull_request_review_comment, or issue_comment events instead.", + "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. If no activity types are specified, the workflow runs when a pull request is opened, reopened, or when the head branch of the pull request is updated.", "one-of": [ "null", "pull-request-mapping" @@ -805,7 +805,7 @@ } }, "pull-request-activity": { - "description": "The types of pull request activity that trigger the workflow. Can be one or more of: created, edited, opened, closed, or deleted.", + "description": "The types of pull request activity that trigger the workflow. Supported activity types: `assigned`, `unassigned`, `labeled`, `unlabeled`, `opened`, `edited`, `closed`, `reopened`, `synchronize`, `converted_to_draft`, `ready_for_review`, `locked`, `unlocked`, `review_requested`, `review_request_removed`, `auto_merge_enabled`, `auto_merge_disabled`.", "one-of": [ "pull-request-activity-type", "pull-request-activity-types" @@ -838,26 +838,26 @@ ] }, "pull-request-comment-string": { - "description": "Please use the issue_comment event instead.", + "description": "Please use the `issue_comment` event instead.", "string": { "constant": "pull_request_comment" } }, "pull-request-comment": { - "description": "Please use the issue_comment event instead.", + "description": "Please use the `issue_comment` event instead.", "one-of": [ "null", "issue-comment-mapping" ] }, "pull-request-review-string": { - "description": "Runs your workflow when a pull request review is submitted, edited, or dismissed. A pull request review is a group of pull request review comments in addition to a body comment and a state. For activity related to pull request review comments or pull request comments, use the pull_request_review_comment or issue_comment events instead.", + "description": "Runs your workflow when a pull request review is submitted, edited, or dismissed. A pull request review is a group of pull request review comments in addition to a body comment and a state. For activity related to pull request review comments or pull request comments, use the `pull_request_review_comment` or `issue_comment` events instead.", "string": { "constant": "pull_request_review" } }, "pull-request-review": { - "description": "Runs your workflow when a pull request review is submitted, edited, or dismissed. A pull request review is a group of pull request review comments in addition to a body comment and a state. For activity related to pull request review comments or pull request comments, use the pull_request_review_comment or issue_comment events instead.", + "description": "Runs your workflow when a pull request review is submitted, edited, or dismissed. A pull request review is a group of pull request review comments in addition to a body comment and a state. For activity related to pull request review comments or pull request comments, use the `pull_request_review_comment` or `issue_comment` events instead.", "one-of": [ "null", "pull-request-review-mapping" @@ -871,7 +871,7 @@ } }, "pull-request-review-activity": { - "description": "The types of pull request review activity that trigger the workflow. Can be one or more of: submitted, edited, or dismissed.", + "description": "The types of pull request review activity that trigger the workflow. Supported activity types: `submitted`, `edited`, `dismissed`.", "one-of": [ "pull-request-review-activity-type", "pull-request-review-activity-types" @@ -910,7 +910,7 @@ } }, "pull-request-review-comment-activity": { - "description": "The types of pull request review comment activity that trigger the workflow. Can be one or more of: created, edited, or deleted.", + "description": "The types of pull request review comment activity that trigger the workflow. Supported activity types: `created`, `edited`, `deleted`.", "one-of": [ "pull-request-review-comment-activity-type", "pull-request-review-comment-activity-types" @@ -929,13 +929,13 @@ ] }, "pull-request-target-string": { - "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. For example, if no activity types are specified, the workflow runs when a pull request is opened or reopened or when the head branch of the pull request is updated. This event runs in the context of the base of the pull request, rather than in the context of the merge commit, as the pull_request event does. This prevents execution of unsafe code from the head of the pull request that could alter your repository or steal any secrets you use in your workflow. This event allows your workflow to do things like label or comment on pull requests from forks. Avoid using this event if you need to build or run code from the pull request.", + "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. If no activity types are specified, the workflow runs when a pull request is opened, reopened, or when the head branch of the pull request is updated.\n\nThis event runs in the context of the base of the pull request, rather than in the context of the merge commit, as the `pull_request` event does. This prevents execution of unsafe code from the head of the pull request that could alter your repository or steal any secrets you use in your workflow. This event allows your workflow to do things like label or comment on pull requests from forks. Avoid using this event if you need to build or run code from the pull request.", "string": { "constant": "pull_request_target" } }, "pull-request-target": { - "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. For example, if no activity types are specified, the workflow runs when a pull request is opened or reopened or when the head branch of the pull request is updated. This event runs in the context of the base of the pull request, rather than in the context of the merge commit, as the pull_request event does. This prevents execution of unsafe code from the head of the pull request that could alter your repository or steal any secrets you use in your workflow. This event allows your workflow to do things like label or comment on pull requests from forks. Avoid using this event if you need to build or run code from the pull request.", + "description": "Runs your workflow when activity on a pull request in the workflow's repository occurs. If no activity types are specified, the workflow runs when a pull request is opened, reopened, or when the head branch of the pull request is updated.\n\nThis event runs in the context of the base of the pull request, rather than in the context of the merge commit, as the `pull_request` event does. This prevents execution of unsafe code from the head of the pull request that could alter your repository or steal any secrets you use in your workflow. This event allows your workflow to do things like label or comment on pull requests from forks. Avoid using this event if you need to build or run code from the pull request.", "one-of": [ "null", "pull-request-target-mapping" @@ -953,7 +953,7 @@ } }, "pull-request-target-activity": { - "description": "The types of pull request activity that trigger the workflow. Can be one or more of: assigned, unassigned, labeled, unlabeled, opened, edited, closed, reopened, synchronize, converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, or auto_merge_disabled.", + "description": "The types of pull request activity that trigger the workflow. Supported activity types: `assigned`, `unassigned`, `labeled`, `unlabeled`, `opened`, `edited`, `closed`, `reopened`, `synchronize`, `converted_to_draft`, `ready_for_review`, `locked`, `unlocked`, `review_requested`, `review_request_removed`, `auto_merge_enabled`, `auto_merge_disabled`.", "one-of": [ "pull-request-target-activity-type", "pull-request-target-activity-types" @@ -1031,7 +1031,7 @@ } }, "registry-package-activity": { - "description": "The types of registry package activity that trigger the workflow. Can be one or more of: published or updated.", + "description": "The types of registry package activity that trigger the workflow. Supported activity types: `published`, `updated`.", "one-of": [ "registry-package-activity-type", "registry-package-activity-types" @@ -1069,7 +1069,7 @@ } }, "release-activity": { - "description": "The types of release activity that trigger the workflow. Can be one or more of: published, unpublished, created, edited, deleted, prereleased, or released.", + "description": "The types of release activity that trigger the workflow. Supported activity types: `published`, `unpublished`, `created`, `edited`, `deleted`, `prereleased`, `released`.", "one-of": [ "release-activity-type", "release-activity-types" @@ -1092,25 +1092,25 @@ ] }, "schedule-string": { - "description": "The schedule event allows you to trigger a workflow at a scheduled time. You can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes. GitHub Actions does not support the non-standard syntax @yearly, @monthly, @weekly, @daily, @hourly, and @reboot.", + "description": "The `schedule` event allows you to trigger a workflow at a scheduled time.\n\nYou can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes. GitHub Actions does not support the non-standard syntax `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly`, and `@reboot`.", "string": { "constant": "schedule" } }, "schedule": { - "description": "The schedule event allows you to trigger a workflow at a scheduled time. You can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes. GitHub Actions does not support the non-standard syntax @yearly, @monthly, @weekly, @daily, @hourly, and @reboot.", + "description": "The `schedule` event allows you to trigger a workflow at a scheduled time.\n\nYou can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes. GitHub Actions does not support the non-standard syntax `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly`, and `@reboot`.", "sequence": { "item-type": "cron-mapping" } }, "status-string": { - "description": "Runs your workflow when the status of a Git commit changes. For example, commits can be marked as error, failure, pending, or success. If you want to provide more details about the status change, you may want to use the check_run event.", + "description": "Runs your workflow when the status of a Git commit changes. For example, commits can be marked as `error`, `failure`, `pending`, or `success`. If you want to provide more details about the status change, you may want to use the `check_run` event.", "string": { "constant": "status" } }, "status": { - "description": "Runs your workflow when the status of a Git commit changes. For example, commits can be marked as error, failure, pending, or success. If you want to provide more details about the status change, you may want to use the check_run event.", + "description": "Runs your workflow when the status of a Git commit changes. For example, commits can be marked as `error`, `failure`, `pending`, or `success`. If you want to provide more details about the status change, you may want to use the `check_run` event.", "null": {} }, "watch-string": { @@ -1134,7 +1134,7 @@ } }, "watch-activity": { - "description": "The types of watch activity that trigger the workflow. Currently, the only supported type is started.", + "description": "The types of watch activity that trigger the workflow. Supported activity types: `started`.", "one-of": [ "watch-activity-type", "watch-activity-types" @@ -1151,13 +1151,13 @@ ] }, "workflow-run-string": { - "description": "This event occurs when a workflow run is requested or completed. It allows you to execute a workflow based on execution or completion of another workflow. The workflow started by the workflow_run event is able to access secrets and write tokens, even if the previous workflow was not. This is useful in cases where the previous workflow is intentionally not privileged, but you need to take a privileged action in a later workflow.", + "description": "This event occurs when a workflow run is requested or completed. It allows you to execute a workflow based on execution or completion of another workflow. The workflow started by the `workflow_run` event is able to access secrets and write tokens, even if the previous workflow was not. This is useful in cases where the previous workflow is intentionally not privileged, but you need to take a privileged action in a later workflow.", "string": { "constant": "workflow_run" } }, "workflow-run": { - "description": "This event occurs when a workflow run is requested or completed. It allows you to execute a workflow based on execution or completion of another workflow. The workflow started by the workflow_run event is able to access secrets and write tokens, even if the previous workflow was not. This is useful in cases where the previous workflow is intentionally not privileged, but you need to take a privileged action in a later workflow.", + "description": "This event occurs when a workflow run is requested or completed. It allows you to execute a workflow based on execution or completion of another workflow. The workflow started by the `workflow_run` event is able to access secrets and write tokens, even if the previous workflow was not. This is useful in cases where the previous workflow is intentionally not privileged, but you need to take a privileged action in a later workflow.", "one-of": [ "null", "workflow-run-mapping" @@ -1174,14 +1174,14 @@ } }, "workflow-run-workflows": { - "description": "The name of the workflow that triggers the workflow_run event. The workflow must be in the same repository as the workflow that uses the workflow_run event.", + "description": "The name of the workflow that triggers the `workflow_run` event. The workflow must be in the same repository as the workflow that uses the `workflow_run` event.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "workflow-run-activity": { - "description": "The types of workflow run activity that trigger the workflow. Can be one or more of: requested or completed.", + "description": "The types of workflow run activity that trigger the workflow. Suupported activity types: `completed`, `requested`, `in_progress`.", "one-of": [ "workflow-run-activity-type", "workflow-run-activity-types" @@ -1200,55 +1200,55 @@ ] }, "event-branches": { - "description": "Use the branches filter to configure your workflow to only run when an event occurs on specific branches. If you use the branches filter and other filters (such as branches-ignore), the workflow will only run when all filters are satisfied.", + "description": "Use the `branches` filter when you want to include branch name patterns or when you want to both include and exclude branch name patterns. You cannot use both the `branches` and `branches-ignore` filters for the same event in a workflow.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "event-branches-ignore": { - "description": "You can use the branches-ignore filter to configure your workflow to not run when an event occurs on specific branches. If you use the branches-ignore filter and other filters (such as branches), the workflow will only run when all filters are satisfied.", + "description": "Use the `branches-ignore` filter when you only want to exclude branch name patterns. You cannot use both the `branches` and `branches-ignore` filters for the same event in a workflow.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "event-tags": { - "description": "Use the tags filter to configure your workflow to only run when an event occurs on specific tags. If you use the tags filter and other filters (such as tags-ignore), the workflow will only run when all filters are satisfied.", + "description": "Use the `tags` filter when you want to include tag name patterns or when you want to both include and exclude tag names patterns. You cannot use both the `tags` and `tags-ignore` filters for the same event in a workflow.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "event-tags-ignore": { - "description": "You can use the tags-ignore filter to configure your workflow to not run when an event occurs on specific tags. If you use the tags-ignore filter and other filters (such as tags), the workflow will only run when all filters are satisfied.", + "description": "Use the `tags-ignore` filter when you only want to exclude tag name patterns. You cannot use both the `tags` and `tags-ignore` filters for the same event in a workflow.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "event-paths": { - "description": "Configure your workflow to only run when an event changes specific files. If you use both the paths filter and other filters (such as paths-ignore), the workflow will only run when all filters are satisfied.", + "description": "Use the `paths` filter when you want to include file path patterns or when you want to both include and exclude file path patterns. You cannot use both the `paths` and `paths-ignore` filters for the same event in a workflow.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "event-paths-ignore": { - "description": "You can use the paths-ignore filter to configure your workflow to not run when an event changes specific files. If you use both the paths-ignore filter and other filters (such as paths), the workflow will only run when all filters are satisfied.", + "description": "Use the `paths-ignore` filter when you only want to exclude file path patterns. You cannot use both the `paths` and `paths-ignore` filters for the same event in a workflow.", "one-of": [ "non-empty-string", "sequence-of-non-empty-string" ] }, "repository-dispatch-string": { - "description": "You can use the GitHub API to trigger a webhook event called repository_dispatch when you want to trigger a workflow for activity that happens outside of GitHub. For more information, see https://developer.github.com/v3/repos/#create-a-repository-dispatch-event. To trigger the custom repository_dispatch webhook event, you must send a POST request to a GitHub API endpoint and provide an event_type name to describe the activity type. To trigger a workflow run, you must also configure your workflow to use the repository_dispatch event.", + "description": "You can use the GitHub API to trigger a webhook event called `repository_dispatch` when you want to trigger a workflow for activity that happens outside of GitHub. For more information, visit the [online documentation](https://docs.github.com/en/rest/repos/repos#create-a-repository-dispatch-event).", "string": { "constant": "branch_protection_rule" } }, "repository-dispatch": { - "description": "You can use the GitHub API to trigger a webhook event called repository_dispatch when you want to trigger a workflow for activity that happens outside of GitHub. For more information, see https://developer.github.com/v3/repos/#create-a-repository-dispatch-event. To trigger the custom repository_dispatch webhook event, you must send a POST request to a GitHub API endpoint and provide an event_type name to describe the activity type. To trigger a workflow run, you must also configure your workflow to use the repository_dispatch event.", + "description": "You can use the GitHub API to trigger a webhook event called `repository_dispatch` when you want to trigger a workflow for activity that happens outside of GitHub. For more information, visit the [online documentation](https://docs.github.com/en/rest/repos/repos#create-a-repository-dispatch-event).", "one-of": [ "null", "repository-dispatch-mapping" @@ -1262,13 +1262,13 @@ } }, "workflow-call-string": { - "description": "Allows workflows to be reused by other workflows.", + "description": "The `workflow_call` event is used to indicate that a workflow can be called by another workflow. When a workflow is triggered with the `workflow_call` event, the event payload in the called workflow is the same event payload from the calling workflow.", "string": { "constant": "workflow_call" } }, "workflow-call": { - "description": "Allows workflows to be reused by other workflows.", + "description": "The `workflow_call` event is used to indicate that a workflow can be called by another workflow. When a workflow is triggered with the `workflow_call` event, the event payload in the called workflow is the same event payload from the calling workflow.", "one-of": [ "null", "workflow-call-mapping" @@ -1284,7 +1284,7 @@ } }, "workflow-call-inputs": { - "description": "When using the workflow_call keyword, you can optionally specify inputs that are passed to the called workflow from the caller workflow.", + "description": "Inputs that are passed to the called workflow from the caller workflow.", "mapping": { "loose-key-type": "non-empty-string", "loose-value-type": "workflow-call-input-definition" @@ -1303,14 +1303,14 @@ }, "required": { "type": "boolean", - "description": "A boolean to indicate whether the action requires the input parameter. Set to true when the parameter is required." + "description": "A boolean to indicate whether the action requires the input parameter. Set to `true` when the parameter is required." }, "default": "workflow-call-input-default" } } }, "workflow-call-input-type": { - "description": "Required if input is defined for the on.workflow_call keyword. The value of this parameter is a string specifying the data type of the input. This must be one of: boolean, number, or string.", + "description": "Required if input is defined for the `on.workflow_call` keyword. The value of this parameter is a string specifying the data type of the input. This must be one of: `boolean`, `number`, or `string`.", "one-of": [ "input-type-string", "input-type-boolean", @@ -1343,7 +1343,7 @@ } }, "workflow-call-input-default": { - "description": "The default value is used when an input parameter isn't specified in a workflow file.", + "description": "If a `default` parameter is not set, the default value of the input is `false` for boolean, `0` for a number, and `\"\"` for a string.", "context": [ "github", "inputs", @@ -1356,7 +1356,7 @@ ] }, "workflow-call-secrets": { - "description": "A map of the secrets that can be used in the called workflow. Within the called workflow, you can use the secrets context to refer to a secret.", + "description": "A map of the secrets that can be used in the called workflow. Within the called workflow, you can use the `secrets` context to refer to a secret.", "mapping": { "loose-key-type": "workflow-call-secret-name", "loose-value-type": "workflow-call-secret-definition" @@ -1389,7 +1389,7 @@ } }, "workflow-call-outputs": { - "description": "When using the workflow_call keyword, you can optionally specify outputs that are provided by the called workflow to the caller workflow.", + "description": "A reusable workflow may generate data that you want to use in the caller workflow. To use these outputs, you must specify them as the outputs of the reusable workflow.", "mapping": { "loose-key-type": "workflow-call-output-name", "loose-value-type": "workflow-call-output-definition" @@ -1399,7 +1399,7 @@ "string": { "require-non-empty": true }, - "description": "A string identifier to associate with the output. The value of is a map of the input's metadata. The must be a unique identifier within the outputs object. The must start with a letter or _ and contain only alphanumeric characters, -, or _." + "description": "A string identifier to associate with the output." }, "workflow-call-output-definition": { "mapping": { @@ -1426,13 +1426,13 @@ "string": {} }, "workflow-dispatch-string": { - "description": "You can now create workflows that are manually triggered with the new workflow_dispatch event. You will then see a 'Run workflow' button on the Actions tab, enabling you to easily trigger a run.", + "description": "The `workflow_dispatch` event allows you to manually trigger a workflow run. A workflow can be manually triggered using the GitHub API, GitHub CLI, or GitHub browser interface.", "string": { "constant": "workflow_dispatch" } }, "workflow-dispatch": { - "description": "You can now create workflows that are manually triggered with the new workflow_dispatch event. You will then see a 'Run workflow' button on the Actions tab, enabling you to easily trigger a run.", + "description": "The `workflow_dispatch` event allows you to manually trigger a workflow run. A workflow can be manually triggered using the GitHub API, GitHub CLI, or GitHub browser interface.", "one-of": [ "null", "workflow-dispatch-mapping" @@ -1446,7 +1446,7 @@ } }, "workflow-dispatch-inputs": { - "description": "Input parameters allow you to specify data that the action expects to use during runtime. GitHub stores input parameters as environment variables. Input ids with uppercase letters are converted to lowercase during runtime. We recommended using lowercase input ids.", + "description": "You can configure custom-defined input properties, default input values, and required inputs for the event directly in your workflow. When you trigger the event, you can provide the `ref` and any `inputs`. When the workflow runs, you can access the input values in the `inputs` context.", "mapping": { "loose-key-type": "workflow-dispatch-input-name", "loose-value-type": "workflow-dispatch-input" @@ -1481,7 +1481,7 @@ } }, "workflow-dispatch-input-type": { - "description": "A string representing the type of the input. This must be one of: boolean, number, string, choice, or environment.", + "description": "A string representing the type of the input. This must be one of: `boolean`, `number`, `string`, `choice`, or `environment`.", "one-of": [ "input-type-string", "input-type-boolean", @@ -1499,7 +1499,7 @@ ] }, "permissions": { - "description": "You can modify the default permissions granted to the GITHUB_TOKEN, adding or removing access as required, so that you only allow the minimum required access.", + "description": "You can use `permissions` to modify the default permissions granted to the `GITHUB_TOKEN`, adding or removing access as required, so that you only allow the minimum required access.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions)", "one-of": [ "permissions-mapping", "permission-level-shorthand-read-all", @@ -1526,7 +1526,7 @@ } }, "permission-level-any": { - "description": "The permission level for the GITHUB_TOKEN.", + "description": "The permission level for the `GITHUB_TOKEN`.", "one-of": [ "permission-level-read", "permission-level-write", @@ -1546,36 +1546,37 @@ ] }, "permission-level-read": { - "description": "The permission level for the GITHUB_TOKEN. Grants write permission for the specified scope.", + "description": "The permission level for the `GITHUB_TOKEN`. Grants `read` permission for the specified scope.", "string": { "constant": "read" } }, "permission-level-write": { - "description": "The permission level for the GITHUB_TOKEN. Grants write permission for the specified scope.", + "description": "The permission level for the `GITHUB_TOKEN`. Grants `write` permission for the specified scope.", "string": { "constant": "write" } }, "permission-level-no-access": { - "description": "The permission level for the GITHUB_TOKEN. Restricts all access for the specified scope.", + "description": "The permission level for the `GITHUB_TOKEN`. Restricts all access for the specified scope.", "string": { "constant": "none" } }, "permission-level-shorthand-read-all": { - "description": "The permission level for the GITHUB_TOKEN. Grants read access for all scopes.", + "description": "The permission level for the `GITHUB_TOKEN`. Grants `read` access for all scopes.", "string": { "constant": "read-all" } }, "permission-level-shorthand-write-all": { - "description": "The permission level for the GITHUB_TOKEN. Grants write access for all scopes.", + "description": "The permission level for the `GITHUB_TOKEN`. Grants `write` access for all scopes.", "string": { "constant": "write-all" } }, "workflow-defaults": { + "description": "Use `defaults` to create a map of default settings that will apply to all jobs in the workflow. You can also set default settings that are only available to a job.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#defaults)", "mapping": { "properties": { "run": "workflow-defaults-run" @@ -1591,7 +1592,7 @@ } }, "workflow-env": { - "description": "To set custom environment variables, you need to specify the variables in the workflow file. You can define environment variables for a step, job, or entire workflow using the jobs..steps[*].env, jobs..env, and env keywords. For more information, see https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsenv", + "description": "A map of environment variables that are available to the steps of all jobs in the workflow. You can also set environment variables that are only available to the steps of a single job or to a single step.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#env)", "context": [ "github", "inputs", @@ -1604,7 +1605,7 @@ } }, "jobs": { - "description": "A workflow run is made up of one or more jobs. Jobs run in parallel by default. To run jobs sequentially, you can define dependencies on other jobs using the jobs..needs keyword. Each job runs in a fresh instance of the virtual environment specified by runs-on. You can run an unlimited number of jobs as long as you are within the workflow usage limits. For more information, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#usage-limits.", + "description": "A workflow run is made up of one or more `jobs`, which run in parallel by default. To run jobs sequentially, you can define dependencies on other jobs using the `jobs..needs` keyword. Each job runs in a runner environment specified by `runs-on`.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobs)", "mapping": { "loose-key-type": "job-id", "loose-value-type": "job" @@ -1614,10 +1615,10 @@ "string": { "require-non-empty": true }, - "description": "A string identifier to associate with the job. The value of is a map of the input's metadata. The must be a unique identifier within the inputs object. The must start with a letter or _ and contain only alphanumeric characters, -, or _." + "description": "A unique identifier for the job. The identifier must start with a letter or _ and contain only alphanumeric characters, -, or _." }, "job": { - "description": "Each job must have an id to associate with the job. The key job_id is a string and its value is a map of the job's configuration data. You must replace with a string that is unique to the jobs object. The must start with a letter or _ and contain only alphanumeric characters, -, or _.", + "description": "Each job must have an id to associate with the job. The key `job_id` is a string and its value is a map of the job's configuration data. You must replace `` with a string that is unique to the jobs object. The `` must start with a letter or _ and contain only alphanumeric characters, -, or _.", "one-of": [ "job-factory", "workflow-job" @@ -1666,7 +1667,7 @@ "description": "The name of the job displayed on GitHub." }, "uses": { - "description": "The location and version of a reusable workflow file to run as a job, of the form './{path/to}/{localfile}.yml' or '{owner}/{repo}/{path}/{filename}@{ref}'. {ref} can be a SHA, a release tag, or a branch name. Using the commit SHA is the safest for stability and security.", + "description": "The location and version of a reusable workflow file to run as a job. Use one of the following syntaxes:\n\n* `{owner}/{repo}/.github/workflows/{filename}@{ref}` for reusable workflows in public and private repositories.\n* `./.github/workflows/{filename}` for reusable workflows in the same repository.\n\n{ref} can be a SHA, a release tag, or a branch name. Using the commit SHA is the safest for stability and security.", "type": "non-empty-string", "required": true }, @@ -1681,14 +1682,14 @@ } }, "workflow-job-with": { - "description": "A map of inputs that are passed to the called workflow. Any inputs that you pass must match the input specifications defined in the called workflow. Unlike 'jobs..steps[*].with', the inputs you pass with 'jobs..with' are not be available as environment variables in the called workflow. Instead, you can reference the inputs by using the inputs context.", + "description": "When a job is used to call a reusable workflow, you can use `with` to provide a map of inputs that are passed to the called workflow.\n\nAny inputs that you pass must match the input specifications defined in the called workflow.", "mapping": { "loose-key-type": "non-empty-string", "loose-value-type": "scalar-needs-context" } }, "workflow-job-secrets": { - "description": "When a job is used to call a reusable workflow, you can use 'secrets' to provide a map of secrets that are passed to the called workflow. Any secrets that you pass must match the names defined in the called workflow.", + "description": "When a job is used to call a reusable workflow, you can use `secrets` to provide a map of secrets that are passed to the called workflow.\n\nAny secrets that you pass must match the names defined in the called workflow.", "one-of": [ "workflow-job-secrets-mapping", "workflow-job-secrets-inherit" @@ -1706,14 +1707,14 @@ } }, "needs": { - "description": "Identifies any jobs that must complete successfully before this job will run. It can be a string or array of strings. If a job fails, all jobs that need it are skipped unless the jobs use a conditional statement that causes the job to continue.", + "description": "Use `needs` to identify any jobs that must complete successfully before this job will run. It can be a string or array of strings. If a job fails, all jobs that need it are skipped unless the jobs use a conditional expression that causes the job to continue. If a run contains a series of jobs that need each other, a failure applies to all jobs in the dependency chain from the point of failure onwards.", "one-of": [ "sequence-of-non-empty-string", "non-empty-string" ] }, "job-if": { - "description": "You can use the if conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional. Expressions in an if conditional do not require the bracketed expression syntax. For more information, see https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions.", + "description": "You can use the `if` conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional.", "context": [ "github", "inputs", @@ -1749,7 +1750,7 @@ ] }, "strategy": { - "description": "A strategy creates a build matrix for your jobs. You can define different variations of an environment to run each job in.", + "description": "Use `strategy` to use a matrix strategy for your jobs. A matrix strategy lets you use variables in a single job definition to automatically create multiple job runs that are based on the combinations of the variables. ", "context": [ "github", "inputs", @@ -1760,27 +1761,27 @@ "properties": { "fail-fast": { "type": "boolean", - "description": "When set to true, GitHub cancels all in-progress jobs if any matrix job fails. Default: true" + "description": "Setting `fail-fast` to `false` prevents GitHub from canceling all in-progress jobs if any matrix job fails. Default: `true`" }, "max-parallel": { "type": "number", - "description": "The maximum number of jobs that can run simultaneously when using a matrix job strategy. By default, GitHub will maximize the number of jobs run in parallel depending on the available runners on GitHub-hosted virtual machines." + "description": "The maximum number of jobs that can run simultaneously when using a matrix job strategy. By default, GitHub will maximize the number of jobs run in parallel depending on runner availability." }, "matrix": "matrix" } } }, "matrix": { - "description": "A build matrix is a set of different configurations of the virtual environment. For example you might run a job against more than one supported version of a language, operating system, or tool. Each configuration is a copy of the job that runs and reports a status. You can specify a matrix by supplying an array for the configuration options. For example, if the GitHub virtual environment supports Node.js versions 6, 8, and 10 you could specify an array of those versions in the matrix. When you define a matrix of operating systems, you must set the required runs-on keyword to the operating system of the current job, rather than hard-coding the operating system name. To access the operating system name, you can use the matrix.os context parameter to set runs-on. For more information, see https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions.", + "description": "Use `matrix` to define a matrix of different job configurations. Within your matrix, define one or more variables followed by an array of values.", "mapping": { "properties": { "include": { "type": "matrix-filter", - "description": "Use include to expand existing matrix configurations or to add new configurations. The value of include is a list of objects." + "description": "Use `include` to expand existing matrix configurations or to add new configurations. The value of `include` is a list of objects.\n\nFor each object in the `include` list, the key:value pairs in the object will be added to each of the matrix combinations if none of the key:value pairs overwrite any of the original matrix values. If the object cannot be added to any of the matrix combinations, a new matrix combination will be created instead. Note that the original matrix values will not be overwritten, but added matrix values can be overwritten." }, "exclude": { "type": "matrix-filter", - "description": "To remove specific configurations defined in the matrix, use exclude. An excluded configuration only has to be a partial match for it to be excluded." + "description": "To remove specific configurations defined in the matrix, use `exclude`. An excluded configuration only has to be a partial match for it to be excluded." } }, "loose-key-type": "non-empty-string", @@ -1799,7 +1800,7 @@ } }, "runs-on": { - "description": "The type of machine to run the job on. The machine can be either a GitHub-hosted runner, or a self-hosted runner.", + "description": "Use `runs-on` to define the type of machine to run the job on.\n* The destination machine can be either a GitHub-hosted runner, larger runner, or a self-hosted runner.\n* You can target runners based on the labels assigned to them, or their group membership, or a combination of these.\n* You can provide `runs-on` as a single string or as an array of strings.\n* If you specify an array of strings, your workflow will execute on any runner that matches all of the specified `runs-on` values.\n* If you would like to run your workflow on multiple machines, use `jobs..strategy`.", "context": [ "github", "inputs", @@ -1833,7 +1834,7 @@ ] }, "job-env": { - "description": "A map of environment variables that are available to all steps in the job.", + "description": "A map of variables that are available to all steps in the job.", "context": [ "github", "inputs", @@ -1849,7 +1850,7 @@ } }, "workflow-concurrency": { - "description": "Concurrency ensures that only a single workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can use any context except for the secrets context. You can also specify concurrency at the workflow level.", + "description": "Concurrency ensures that only a single job or workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression.\n\nYou can also specify `concurrency` at the job level.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency)", "context": [ "github", "inputs", @@ -1861,7 +1862,7 @@ ] }, "job-concurrency": { - "description": "Concurrency ensures that only a single job using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can use any context except for the secrets context. You can also specify concurrency at the workflow level.", + "description": "Concurrency ensures that only a single job using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can use any context except for the `secrets` context.\n\nYou can also specify `concurrency` at the workflow level.", "context": [ "github", "inputs", @@ -1876,13 +1877,13 @@ ] }, "concurrency-mapping": { - "description": "Concurrency ensures that only a single job or workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can use any context except for the secrets context. You can also specify concurrency at the workflow level.", + "description": "Concurrency ensures that only a single job or workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression.\n\nYou can also specify `concurrency` at the job level.\n\n[Documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency)", "mapping": { "properties": { "group": { "type": "non-empty-string", "required": true, - "description": "When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. Any previously pending job or workflow in the concurrency group will be canceled." + "description": "When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be `pending`. Any previously pending job or workflow in the concurrency group will be canceled. To also cancel any currently running job or workflow in the same concurrency group, specify `cancel-in-progress: true`." }, "cancel-in-progress": { "type": "boolean", @@ -1921,7 +1922,7 @@ } }, "job-environment-name": { - "description": "The name of the environment.", + "description": "The name of the environment used by the job.", "context": [ "github", "inputs", @@ -1933,7 +1934,7 @@ "string": {} }, "job-defaults": { - "description": "A map of default settings that will apply to all steps in the job.", + "description": "A map of default settings that will apply to all steps in the job. You can also set default settings for the entire workflow.", "mapping": { "properties": { "run": "job-defaults-run" @@ -1958,14 +1959,14 @@ } }, "job-outputs": { - "description": "A map of outputs for a job. Job outputs are available to all downstream jobs that depend on this job.", + "description": "A map of outputs for a called workflow. Called workflow outputs are available to all downstream jobs in the caller workflow. Each output has an identifier, an optional `description,` and a `value`. The `value` must be set to the value of an output from a job within the called workflow.", "mapping": { "loose-key-type": "non-empty-string", "loose-value-type": "string-runner-context" } }, "steps": { - "description": "A job contains a sequence of tasks called steps. Steps can run commands, run setup tasks, or run an action in your repository, a public repository, or an action published in a Docker registry. Not all steps run actions, but all actions run as a step. Each step runs in its own process in the virtual environment and has access to the workspace and filesystem. Because steps run in their own process, changes to environment variables are not preserved between steps. GitHub provides built-in steps to set up and complete a job. Must contain either `uses` or `run`.", + "description": "A job contains a sequence of tasks called `steps`. Steps can run commands, run setup tasks, or run an action in your repository, a public repository, or an action published in a Docker registry. Not all steps run actions, but all actions run as a step. Each step runs in its own process in the runner environment and has access to the workspace and filesystem. Because steps run in their own process, changes to environment variables are not preserved between steps. GitHub provides built-in steps to set up and complete a job. Must contain either `uses` or `run`.", "sequence": { "item-type": "steps-item" } @@ -1985,7 +1986,7 @@ "timeout-minutes": "step-timeout-minutes", "run": { "type": "string-steps-context", - "description": "Runs command-line programs using the operating system's shell. If you do not provide a name, the step name will default to the text specified in the run command. Commands run using non-login shells by default. You can choose a different shell and customize the shell used to run commands. Each run keyword represents a new process and shell in the virtual environment. When you provide multi-line commands, each line runs in the same shell.", + "description": "Runs command-line programs using the operating system's shell. If you do not provide a `name`, the step name will default to the text specified in the `run` command. Commands run using non-login shells by default. You can choose a different shell and customize the shell used to run commands. Each `run` keyword represents a new process and shell in the virtual environment. When you provide multi-line commands, each line runs in the same shell.", "required": true }, "continue-on-error": "step-continue-on-error", @@ -2004,7 +2005,7 @@ "continue-on-error": "step-continue-on-error", "timeout-minutes": "step-timeout-minutes", "uses": { - "description": "Selects an action to run as part of a step in your job. An action is a reusable unit of code. You can use an action defined in the same repository as the workflow, a public repository, or in a published Docker container image (https://hub.docker.com/).", + "description": "Selects an action to run as part of a step in your job. An action is a reusable unit of code. You can use an action defined in the same repository as the workflow, a public repository, or in a published Docker container image.", "type": "non-empty-string", "required": true }, @@ -2029,13 +2030,13 @@ "hashFiles(1,255)" ], "boolean": {}, - "description": "Prevents a job from failing when a step fails. Set to true to allow a job to pass when this step fails." + "description": "Prevents a job from failing when a step fails. Set to `true` to allow a job to pass when this step fails." }, "step-id": { "string": { "require-non-empty": true }, - "description": "A unique identifier for the step. You can use the id to reference the step in contexts." + "description": "A unique identifier for the step. You can use the `id` to reference the step in contexts." }, "step-if": { "context": [ @@ -2055,7 +2056,7 @@ "success(0,0)", "hashFiles(1,255)" ], - "description": "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional. Expressions in an if conditional do not require the bracketed expression syntax.", + "description": "Use the `if` conditional to prevent a step from running unless a condition is met. Any supported context and expression can be used to create a conditional. Expressions in an `if` conditional do not require the bracketed expression syntax. When you use expressions in an `if` conditional, you may omit the expression syntax because GitHub automatically evaluates the `if` conditional as an expression.", "string": { "is-expression": true } @@ -2087,7 +2088,7 @@ ] }, "step-env": { - "description": "Sets environment variables for steps to use in the virtual environment. You can also set environment variables for the entire workflow or a job.", + "description": "Sets variables for steps to use in the runner environment. You can also set variables for the entire workflow or a job.", "context": [ "github", "inputs", @@ -2144,7 +2145,7 @@ "description": "The maximum number of minutes to run the step before killing the process." }, "step-with": { - "description": "A map of the input parameters defined by the action. Each input parameter is a key/value pair. Input parameters are set as environment variables. The variable is prefixed with INPUT_ and converted to upper case.", + "description": "A map of the input parameters defined by the action. Each input parameter is a key/value pair. Input parameters are set as variables. When you specify an input in a workflow file or use a default input value, GitHub creates a variable for the input with the name `INPUT_`. The variable created converts input names to uppercase letters and replaces spaces with `_`.", "context": [ "github", "inputs", @@ -2165,7 +2166,7 @@ } }, "container": { - "description": "A container to run any steps in a job that don't already specify a container. If you have steps that use both script and container actions, the container actions will run as sibling containers on the same network with the same volume mounts. If you do not set a container, all steps will run directly on the host specified by runs-on unless a step refers to an action configured to run in a container.", + "description": "A container to run any steps in a job that don't already specify a container. If you have steps that use both script and container actions, the container actions will run as sibling containers on the same network with the same volume mounts.\n\nIf you do not set a container, all steps will run directly on the host specified by runs-on unless a step refers to an action configured to run in a container.", "context": [ "github", "inputs", @@ -2184,20 +2185,20 @@ "properties": { "image": { "type": "non-empty-string", - "description": "The Docker image to use as the container to run the job. The value can be the Docker Hub image name or a registry name." + "description": "Use `jobs..container.image` to define the Docker image to use as the container to run the action. The value can be the Docker Hub image or a registry name." }, "options": { "type": "non-empty-string", - "description": "Additional Docker container resource options. For a list of options, see https://docs.docker.com/engine/reference/commandline/create/#options." + "description": "Use `jobs..container.options` to configure additional Docker container resource options." }, "env": "container-env", "ports": { "type": "sequence-of-non-empty-string", - "description": "Sets an array of ports to expose on the container." + "description": "Use `jobs..container.ports` to set an array of ports to expose on the container." }, "volumes": { "type": "sequence-of-non-empty-string", - "description": "Sets an array of volumes for the container to use. You can use volumes to share data between services or other steps in a job. You can specify named Docker volumes, anonymous Docker volumes, or bind mounts on the host.\nTo specify a volume, you specify the source and destination path: :\nThe is a volume name or an absolute path on the host machine, and is an absolute path in the container." + "description": "Use `jobs..container.volumes` to set an array of volumes for the container to use. You can use volumes to share data between services or other steps in a job. You can specify named Docker volumes, anonymous Docker volumes, or bind mounts on the host." }, "credentials": "container-registry-credentials" } @@ -2233,7 +2234,7 @@ ] }, "container-registry-credentials": { - "description": "If the image's container registry requires authentication to pull the image, you can use credentials to set a map of the username and password. The credentials are the same values that you would provide to the `docker login` command.", + "description": "If the image's container registry requires authentication to pull the image, you can use `jobs..container.credentials` to set a map of the username and password. The credentials are the same values that you would provide to the `docker login` command.", "context": [ "github", "inputs", @@ -2249,7 +2250,7 @@ } }, "container-env": { - "description": "Sets an array of environment variables in the container.", + "description": "Use `jobs..container.env` to set a map of variables in the container.", "mapping": { "loose-key-type": "non-empty-string", "loose-value-type": "string-runner-context" @@ -2442,13 +2443,13 @@ "string": { "require-non-empty": true }, - "description": "You can override the default shell settings in the runner's operating system using the shell keyword. You can use built-in shell keywords, or you can define a custom set of shell options." + "description": "Use `shell` to override the default shell settings in the runner's operating system. You can use built-in shell keywords, or you can define a custom set of shell options. The shell command that is run internally executes a temporary file that contains the comands specified in `run`." }, "working-directory": { "string": { "require-non-empty": true }, - "description": "Using the working-directory keyword, you can specify the working directory of where to run the command." + "description": "The `working-directory` keyword specifies the working directory where the command is run." }, "cron-mapping": { "mapping": { From 27b50dfb53baf8d5976bb9e019b92d2c83eb8817 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Fri, 13 Jan 2023 12:32:08 -0800 Subject: [PATCH 16/50] Update tests for updated schema --- actions-languageservice/src/complete.test.ts | 10 ++++------ actions-languageservice/src/hover.test.ts | 8 +++----- actions-workflow-parser/src/index.test.ts | 6 ++---- .../testdata/reader/events-mapping-all.yml | 4 ++-- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/actions-languageservice/src/complete.test.ts b/actions-languageservice/src/complete.test.ts index 2ba5a6f..20c9dd1 100644 --- a/actions-languageservice/src/complete.test.ts +++ b/actions-languageservice/src/complete.test.ts @@ -312,7 +312,7 @@ jobs: // Includes detail when available. Using continue-on-error as a sample here. expect(result.map(x => (x.documentation as MarkupContent)?.value)).toContain( - "Prevents a job from failing when a step fails. Set to true to allow a job to pass when this step fails." + "Prevents a job from failing when a step fails. Set to `true` to allow a job to pass when this step fails." ); }); @@ -337,9 +337,7 @@ o| const result = await complete(...getPositionFromCursor(input)); const onResult = result.find(x => x.label === "on"); expect(onResult).not.toBeUndefined(); - expect((onResult!.documentation as MarkupContent).value).toEqual( - "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows." - ); + expect((onResult!.documentation as MarkupContent).value).toContain("The GitHub event that triggers the workflow."); }); it("event list includes descriptions when available ", async () => { @@ -348,8 +346,8 @@ o| const result = await complete(...getPositionFromCursor(input)); const dispatchResult = result.find(x => x.label === "workflow_dispatch"); expect(dispatchResult).not.toBeUndefined(); - expect((dispatchResult!.documentation as MarkupContent).value).toEqual( - "You can now create workflows that are manually triggered with the new workflow_dispatch event. You will then see a 'Run workflow' button on the Actions tab, enabling you to easily trigger a run." + expect((dispatchResult!.documentation as MarkupContent).value).toContain( + "The `workflow_dispatch` event allows you to manually trigger a workflow run." ); }); diff --git a/actions-languageservice/src/hover.test.ts b/actions-languageservice/src/hover.test.ts index c1a0dc3..1fce7e9 100644 --- a/actions-languageservice/src/hover.test.ts +++ b/actions-languageservice/src/hover.test.ts @@ -9,9 +9,7 @@ jobs: runs-on: [self-hosted]`; const result = await hover(...getPositionFromCursor(input)); expect(result).not.toBeUndefined(); - expect(result?.contents).toEqual( - "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows." - ); + expect(result?.contents).toContain("The GitHub event that triggers the workflow."); }); it("on a value", async () => { @@ -44,8 +42,8 @@ jobs: pe|rmissions: read-all`; const result = await hover(...getPositionFromCursor(input)); expect(result).not.toBeUndefined(); - expect(result?.contents).toEqual( - "You can modify the default permissions granted to the GITHUB_TOKEN, adding or removing access as required, so that you only allow the minimum required access." + expect(result?.contents).toContain( + "You can use `permissions` to modify the default permissions granted to the `GITHUB_TOKEN`" ); }); diff --git a/actions-workflow-parser/src/index.test.ts b/actions-workflow-parser/src/index.test.ts index d94034c..de071cb 100644 --- a/actions-workflow-parser/src/index.test.ts +++ b/actions-workflow-parser/src/index.test.ts @@ -92,16 +92,14 @@ jobs: case "name": { const nameKey = pair.key.assertString("name"); expect(nameKey.definition).not.toBeUndefined(); - expect(nameKey.description).toBe("The name of the workflow."); + expect(nameKey.description).toContain("The name of the workflow"); break; } case "on": { const onKey = pair.key.assertString("on"); const onValue = pair.value.assertString("push"); expect(onKey.definition).not.toBeUndefined(); - expect(onKey.description).toBe( - "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows." - ); + expect(onKey.description).toContain("The GitHub event that triggers the workflow."); expect(onValue.definition).not.toBeUndefined(); expect(onValue.description).toBe("Runs your workflow when you push a commit or tag."); break; diff --git a/actions-workflow-parser/testdata/reader/events-mapping-all.yml b/actions-workflow-parser/testdata/reader/events-mapping-all.yml index 70560a1..264c751 100644 --- a/actions-workflow-parser/testdata/reader/events-mapping-all.yml +++ b/actions-workflow-parser/testdata/reader/events-mapping-all.yml @@ -85,7 +85,7 @@ on: types: - created - closed - - opened + - reopened - edited - deleted project_card: @@ -327,7 +327,7 @@ jobs: "types": [ "created", "closed", - "opened", + "reopened", "edited", "deleted" ] From 5d712ecba0e5b4b895ce72e3a8f6e9ef7e16e4d1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 13 Jan 2023 20:37:06 +0000 Subject: [PATCH 17/50] v0.1.84 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 0d7a847..929df96 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.83", + "version": "0.1.84", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 5304047..12b0efd 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.83", + "version": "0.1.84", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.83", - "@github/actions-workflow-parser": "^0.1.83", + "@github/actions-languageservice": "^0.1.84", + "@github/actions-workflow-parser": "^0.1.84", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 2cb99d6..4ee69e8 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.83", + "version": "0.1.84", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.83", - "@github/actions-workflow-parser": "^0.1.83", + "@github/actions-expressions": "^0.1.84", + "@github/actions-workflow-parser": "^0.1.84", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 12525e9..6270a20 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.83", + "version": "0.1.84", "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.83", + "@github/actions-expressions": "^0.1.84", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index e5b0539..9f10f34 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.83", + "version": "0.1.84", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.83", + "@github/actions-languageserver": "^0.1.84", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 71c334b..1bcbf2c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.83" + "version": "0.1.84" } diff --git a/package-lock.json b/package-lock.json index d6bdc11..f7d5659 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.83", + "version": "0.1.84", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.83", + "version": "0.1.84", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.83", - "@github/actions-workflow-parser": "^0.1.83", + "@github/actions-languageservice": "^0.1.84", + "@github/actions-workflow-parser": "^0.1.84", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.83", + "version": "0.1.84", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.83", - "@github/actions-workflow-parser": "^0.1.83", + "@github/actions-expressions": "^0.1.84", + "@github/actions-workflow-parser": "^0.1.84", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.83", + "version": "0.1.84", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.83", + "@github/actions-expressions": "^0.1.84", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.83", + "version": "0.1.84", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.83", + "@github/actions-languageserver": "^0.1.84", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.83", - "@github/actions-workflow-parser": "^0.1.83", + "@github/actions-languageservice": "^0.1.84", + "@github/actions-workflow-parser": "^0.1.84", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.83", - "@github/actions-workflow-parser": "^0.1.83", + "@github/actions-expressions": "^0.1.84", + "@github/actions-workflow-parser": "^0.1.84", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.83", + "@github/actions-expressions": "^0.1.84", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.83", + "@github/actions-languageserver": "^0.1.84", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From fad4e45373fbbcf84bae10f9e63be009c7b5ab73 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Wed, 18 Jan 2023 16:01:13 -0500 Subject: [PATCH 18/50] Add merge group event payload --- .../context-providers/events/eventPayloads.ts | 2 + .../context-providers/events/merge_group.json | 154 ++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 actions-languageservice/src/context-providers/events/merge_group.json diff --git a/actions-languageservice/src/context-providers/events/eventPayloads.ts b/actions-languageservice/src/context-providers/events/eventPayloads.ts index abf08bf..dcfeb69 100644 --- a/actions-languageservice/src/context-providers/events/eventPayloads.ts +++ b/actions-languageservice/src/context-providers/events/eventPayloads.ts @@ -18,6 +18,7 @@ import label from "./label.json"; import marketplace_purchase from "./marketplace_purchase.json"; import member from "./member.json"; import membership from "./membership.json"; +import merge_group from "./merge_group.json"; import meta from "./meta.json"; import milestone from "./milestone.json"; import org_block from "./org_block.json"; @@ -70,6 +71,7 @@ export const eventPayloads: {[key: string]: Object} = { marketplace_purchase, member, membership, + merge_group, meta, milestone, org_block, diff --git a/actions-languageservice/src/context-providers/events/merge_group.json b/actions-languageservice/src/context-providers/events/merge_group.json new file mode 100644 index 0000000..38f53b5 --- /dev/null +++ b/actions-languageservice/src/context-providers/events/merge_group.json @@ -0,0 +1,154 @@ +{ + "action": "checks_requested", + "installation": { + "id": 375706, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMzc1NzA2" + }, + "merge_group": { + "head_sha": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "head_ref": "main", + "base_sha": "f95f852bd8fca8fcc58a9a2d6c842781e32a215e", + "base_ref": "features/branch", + "head_commit": { + "id": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "tree_id": "31b122c26a97cf9af023e9ddab94a82c6e77b0ea", + "message": "Update README.md", + "timestamp": "2019-05-15T15:20:30Z", + "author": { + "name": "Codertocat", + "email": "21031067+Codertocat@users.noreply.github.com" + }, + "committer": { + "name": "Codertocat", + "email": "21031067+Codertocat@users.noreply.github.com" + } + } + }, + "repository": { + "id": 17273051, + "node_id": "MDEwOlJlcG9zaXRvcnkxNzI3MzA1MQ==", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octo-org", + "id": 6811672, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=", + "avatar_url": "https://avatars3.githubusercontent.com/u/6811672?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/octo-org", + "html_url": "https://github.com/octo-org", + "followers_url": "https://api.github.com/users/octo-org/followers", + "following_url": "https://api.github.com/users/octo-org/following{/other_user}", + "gists_url": "https://api.github.com/users/octo-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octo-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octo-org/subscriptions", + "organizations_url": "https://api.github.com/users/octo-org/orgs", + "repos_url": "https://api.github.com/users/octo-org/repos", + "events_url": "https://api.github.com/users/octo-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/octo-org/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": "My first repo on GitHub!", + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments", + "created_at": "2014-02-28T02:42:51Z", + "updated_at": "2018-10-10T15:58:51Z", + "pushed_at": "2018-10-10T15:58:47Z", + "git_url": "git://github.com/octo-org/octo-repo.git", + "ssh_url": "git@github.com:octo-org/octo-repo.git", + "clone_url": "https://github.com/octo-org/octo-repo.git", + "svn_url": "https://github.com/octo-org/octo-repo", + "homepage": "", + "size": 59, + "stargazers_count": 0, + "watchers_count": 0, + "language": "JavaScript", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 1, + "mirror_url": null, + "archived": false, + "open_issues_count": 23, + "license": null, + "forks": 1, + "open_issues": 23, + "watchers": 0, + "default_branch": "main" + }, + "organization": { + "login": "octo-org", + "id": 6811672, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=", + "url": "https://api.github.com/orgs/octo-org", + "repos_url": "https://api.github.com/orgs/octo-org/repos", + "events_url": "https://api.github.com/orgs/octo-org/events", + "hooks_url": "https://api.github.com/orgs/octo-org/hooks", + "issues_url": "https://api.github.com/orgs/octo-org/issues", + "members_url": "https://api.github.com/orgs/octo-org/members{/member}", + "public_members_url": "https://api.github.com/orgs/octo-org/public_members{/member}", + "avatar_url": "https://avatars3.githubusercontent.com/u/6811672?v=4", + "description": "Working better together!" + }, + "sender": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file From 39688a11351b0bbb3b0f543bccbcd7f68ef16832 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Wed, 18 Jan 2023 16:14:30 -0500 Subject: [PATCH 19/50] Use example from docs --- .../context-providers/events/merge_group.json | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/actions-languageservice/src/context-providers/events/merge_group.json b/actions-languageservice/src/context-providers/events/merge_group.json index 38f53b5..2669cb8 100644 --- a/actions-languageservice/src/context-providers/events/merge_group.json +++ b/actions-languageservice/src/context-providers/events/merge_group.json @@ -1,18 +1,14 @@ { "action": "checks_requested", - "installation": { - "id": 375706, - "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMzc1NzA2" - }, "merge_group": { - "head_sha": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", - "head_ref": "main", - "base_sha": "f95f852bd8fca8fcc58a9a2d6c842781e32a215e", - "base_ref": "features/branch", + "head_sha": "2ffea6db159f6b6c47a24e778fb9ef40cf6b1c7d", + "head_ref": "refs/heads/gh-readonly-queue/main/pr-104-929f8209d40f77f4abc622a499c93a83babdbe64", + "base_sha": "380387fbc80638b734a49e1be1c4dfec1c01b33c", + "base_ref": "refs/heads/main", "head_commit": { "id": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", "tree_id": "31b122c26a97cf9af023e9ddab94a82c6e77b0ea", - "message": "Update README.md", + "message": "Merge pull request #2048 from octo-repo/update-readme\n\nUpdate README.md", "timestamp": "2019-05-15T15:20:30Z", "author": { "name": "Codertocat", @@ -34,7 +30,7 @@ "login": "octo-org", "id": 6811672, "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=", - "avatar_url": "https://avatars3.githubusercontent.com/u/6811672?v=4", + "avatar_url": "https://avatars.githubusercontent.com/u/6811672?v=4", "gravatar_id": "", "url": "https://api.github.com/users/octo-org", "html_url": "https://github.com/octo-org", @@ -91,29 +87,30 @@ "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments", "created_at": "2014-02-28T02:42:51Z", - "updated_at": "2018-10-10T15:58:51Z", - "pushed_at": "2018-10-10T15:58:47Z", + "updated_at": "2021-03-11T14:54:13Z", + "pushed_at": "2021-03-11T14:54:10Z", "git_url": "git://github.com/octo-org/octo-repo.git", - "ssh_url": "git@github.com:octo-org/octo-repo.git", + "ssh_url": "org-6811672@github.com:octo-org/octo-repo.git", "clone_url": "https://github.com/octo-org/octo-repo.git", "svn_url": "https://github.com/octo-org/octo-repo", "homepage": "", - "size": 59, + "size": 300, "stargazers_count": 0, "watchers_count": 0, "language": "JavaScript", "has_issues": true, - "has_projects": true, + "has_projects": false, "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "forks_count": 1, + "has_wiki": false, + "has_pages": true, + "forks_count": 0, "mirror_url": null, "archived": false, - "open_issues_count": 23, + "disabled": false, + "open_issues_count": 39, "license": null, - "forks": 1, - "open_issues": 23, + "forks": 0, + "open_issues": 39, "watchers": 0, "default_branch": "main" }, @@ -128,7 +125,7 @@ "issues_url": "https://api.github.com/orgs/octo-org/issues", "members_url": "https://api.github.com/orgs/octo-org/members{/member}", "public_members_url": "https://api.github.com/orgs/octo-org/public_members{/member}", - "avatar_url": "https://avatars3.githubusercontent.com/u/6811672?v=4", + "avatar_url": "https://avatars.githubusercontent.com/u/6811672?v=4", "description": "Working better together!" }, "sender": { @@ -150,5 +147,9 @@ "received_events_url": "https://api.github.com/users/Codertocat/received_events", "type": "User", "site_admin": false + }, + "installation": { + "id": 1, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=" } } \ No newline at end of file From 235709c1aff7fc5d5fc64cf1c24ef1c4af5b9f52 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 18 Jan 2023 21:20:37 +0000 Subject: [PATCH 20/50] v0.1.85 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 929df96..1445606 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.84", + "version": "0.1.85", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 12b0efd..2451abc 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.84", + "version": "0.1.85", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.84", - "@github/actions-workflow-parser": "^0.1.84", + "@github/actions-languageservice": "^0.1.85", + "@github/actions-workflow-parser": "^0.1.85", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 4ee69e8..5690346 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.84", + "version": "0.1.85", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.84", - "@github/actions-workflow-parser": "^0.1.84", + "@github/actions-expressions": "^0.1.85", + "@github/actions-workflow-parser": "^0.1.85", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 6270a20..ca03375 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.84", + "version": "0.1.85", "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.84", + "@github/actions-expressions": "^0.1.85", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 9f10f34..b903ba5 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.84", + "version": "0.1.85", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.84", + "@github/actions-languageserver": "^0.1.85", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 1bcbf2c..a4511b8 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.84" + "version": "0.1.85" } diff --git a/package-lock.json b/package-lock.json index f7d5659..a2162bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.84", + "version": "0.1.85", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.84", + "version": "0.1.85", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.84", - "@github/actions-workflow-parser": "^0.1.84", + "@github/actions-languageservice": "^0.1.85", + "@github/actions-workflow-parser": "^0.1.85", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.84", + "version": "0.1.85", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.84", - "@github/actions-workflow-parser": "^0.1.84", + "@github/actions-expressions": "^0.1.85", + "@github/actions-workflow-parser": "^0.1.85", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.84", + "version": "0.1.85", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.84", + "@github/actions-expressions": "^0.1.85", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.84", + "version": "0.1.85", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.84", + "@github/actions-languageserver": "^0.1.85", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.84", - "@github/actions-workflow-parser": "^0.1.84", + "@github/actions-languageservice": "^0.1.85", + "@github/actions-workflow-parser": "^0.1.85", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.84", - "@github/actions-workflow-parser": "^0.1.84", + "@github/actions-expressions": "^0.1.85", + "@github/actions-workflow-parser": "^0.1.85", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.84", + "@github/actions-expressions": "^0.1.85", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.84", + "@github/actions-languageserver": "^0.1.85", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From f840cd259978654d974304153555570994eb5a72 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 18 Jan 2023 14:50:51 -0800 Subject: [PATCH 21/50] Validate expressions even when calling `fromJson` --- actions-expressions/src/errors.ts | 2 + actions-expressions/src/evaluator.test.ts | 49 ++++++++++++------- actions-expressions/src/evaluator.ts | 19 +++---- actions-expressions/src/funcs/fromjson.ts | 8 ++- actions-expressions/src/index.ts | 3 +- actions-expressions/tsconfig.json | 1 + .../src/validate.expressions.test.ts | 22 +++++++-- actions-languageservice/src/validate.ts | 29 ++++++++++- 8 files changed, 97 insertions(+), 36 deletions(-) diff --git a/actions-expressions/src/errors.ts b/actions-expressions/src/errors.ts index 5edba0e..0a2db07 100644 --- a/actions-expressions/src/errors.ts +++ b/actions-expressions/src/errors.ts @@ -50,3 +50,5 @@ function errorDescription(typ: ErrorType): string { return "Unknown error"; } } + +export class ExpressionEvaluationError extends Error {} diff --git a/actions-expressions/src/evaluator.test.ts b/actions-expressions/src/evaluator.test.ts index cb282eb..e1fa8fd 100644 --- a/actions-expressions/src/evaluator.test.ts +++ b/actions-expressions/src/evaluator.test.ts @@ -1,27 +1,42 @@ import * as data from "./data"; +import {ExpressionEvaluationError} from "./errors"; import {Evaluator} from "./evaluator"; import {Lexer} from "./lexer"; import {Parser} from "./parser"; -test("evaluator", () => { - const input = "foo['']"; +describe("evaluator", () => { + const lexAndParse = (input: string) => { + const lexer = new Lexer(input); + const result = lexer.lex(); - const lexer = new Lexer(input); - const result = lexer.lex(); + // Parse + const parser = new Parser(result.tokens, ["foo"], []); + const expr = parser.parse(); + return expr; + }; - // Parse - const parser = new Parser(result.tokens, ["foo"], []); - const expr = parser.parse(); + it("basic evaluation", () => { + const expr = lexAndParse("foo['']"); - // Evaluate expression - const evaluator = new Evaluator( - expr, - new data.Dictionary({ - key: "foo", - value: new data.Dictionary({key: "bar", value: new data.NumberData(42)}) - }) - ); - const eresult = evaluator.evaluate(); + // Evaluate expression + const evaluator = new Evaluator( + expr, + new data.Dictionary({ + key: "foo", + value: new data.Dictionary({key: "bar", value: new data.NumberData(42)}) + }) + ); + const eresult = evaluator.evaluate(); - expect(eresult.kind).toBe(data.Kind.Null); + expect(eresult.kind).toBe(data.Kind.Null); + }); + + it("handle runtime errors", () => { + const expr = lexAndParse("fromJson('test') == 123"); + const evaluator = new Evaluator(expr, new data.Dictionary()); + + expect(() => evaluator.evaluate()).toThrowError( + new ExpressionEvaluationError("Error parsing JSON when evaluating fromJson") + ); + }); }); diff --git a/actions-expressions/src/evaluator.ts b/actions-expressions/src/evaluator.ts index 65556ff..a1c76b3 100644 --- a/actions-expressions/src/evaluator.ts +++ b/actions-expressions/src/evaluator.ts @@ -14,14 +14,13 @@ import { import * as data from "./data"; import {FilteredArray} from "./filtered_array"; import {wellKnownFunctions} from "./funcs"; +import {FunctionDefinition} from "./funcs/info"; import {idxHelper} from "./idxHelper"; import {TokenType} from "./lexer"; import {equals, falsy, greaterThan, lessThan, truthy} from "./result"; -export class EvaluationError extends Error {} - export class Evaluator implements ExprVisitor { - constructor(private n: Expr, private context: data.Dictionary) {} + constructor(private n: Expr, private context: data.Dictionary, private functions?: Map) {} public evaluate(): data.ExpressionData { return this.eval(this.n); @@ -109,7 +108,7 @@ export class Evaluator implements ExprVisitor { try { idxResult = this.eval(ia.index); } catch (e) { - throw new Error(`could not evaluate index for index access: ${e}`); + throw new Error(`could not evaluate index for index access: ${e}`, {cause: e}); } idx = new idxHelper(false, idxResult); } @@ -150,16 +149,14 @@ export class Evaluator implements ExprVisitor { // Evaluate arguments const args = functionCall.args.map(arg => this.eval(arg)); - return fcall(functionCall, args); + // Get function definitions + const functionName = functionCall.functionName.lexeme.toLowerCase(); + const f = this.functions?.get(functionName) || wellKnownFunctions[functionName]; + + return f.call(...args); } } -function fcall(fc: FunctionCall, args: data.ExpressionData[]): data.ExpressionData { - const f = wellKnownFunctions[fc.functionName.lexeme.toLowerCase()]; - - return f.call(...args); -} - function filteredArrayAccess(fa: FilteredArray, idx: idxHelper): data.ExpressionData { const result = new FilteredArray(); diff --git a/actions-expressions/src/funcs/fromjson.ts b/actions-expressions/src/funcs/fromjson.ts index b014400..6546b2a 100644 --- a/actions-expressions/src/funcs/fromjson.ts +++ b/actions-expressions/src/funcs/fromjson.ts @@ -1,5 +1,6 @@ import {ExpressionData} from "../data"; import {reviver} from "../data/reviver"; +import {ExpressionEvaluationError} from "../errors"; import {FunctionDefinition} from "./info"; export const fromjson: FunctionDefinition = { @@ -16,7 +17,10 @@ export const fromjson: FunctionDefinition = { throw new Error("empty input"); } - const d = JSON.parse(is, reviver); - return d; + try { + return JSON.parse(is, reviver); + } catch (e) { + throw new ExpressionEvaluationError("Error parsing JSON when evaluating fromJson", {cause: e}); + } } }; diff --git a/actions-expressions/src/index.ts b/actions-expressions/src/index.ts index 06eda82..72e53c3 100644 --- a/actions-expressions/src/index.ts +++ b/actions-expressions/src/index.ts @@ -2,7 +2,8 @@ export {Expr} from "./ast"; export {complete, CompletionItem} from "./completion"; export {DescriptionDictionary, DescriptionPair, isDescriptionDictionary} from "./completion/descriptionDictionary"; export * as data from "./data"; -export {ExpressionError} from "./errors"; +export {ExpressionError, ExpressionEvaluationError} from "./errors"; export {Evaluator} from "./evaluator"; +export {wellKnownFunctions} from "./funcs"; export {Lexer, Result} from "./lexer"; export {Parser} from "./parser"; diff --git a/actions-expressions/tsconfig.json b/actions-expressions/tsconfig.json index bbc5196..7da45bc 100644 --- a/actions-expressions/tsconfig.json +++ b/actions-expressions/tsconfig.json @@ -3,6 +3,7 @@ "compilerOptions": { "module": "esnext", "target": "ES2020", + "lib": ["ES2022"], "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "sourceMap": true, diff --git a/actions-languageservice/src/validate.expressions.test.ts b/actions-languageservice/src/validate.expressions.test.ts index 0233569..be91147 100644 --- a/actions-languageservice/src/validate.expressions.test.ts +++ b/actions-languageservice/src/validate.expressions.test.ts @@ -359,7 +359,7 @@ jobs: runs-on: ubuntu-latest steps: - name: step a - env: + env: step_env: job_a_env run: echo "hello \${{ env.step_env }} `; @@ -376,7 +376,7 @@ env: jobs: a: runs-on: ubuntu-latest - env: + env: envjoba: job_a_env steps: - name: step a @@ -395,7 +395,7 @@ env: jobs: a: runs-on: ubuntu-latest - env: + env: envjoba: job_a_env steps: - name: step a @@ -1185,6 +1185,8 @@ jobs: - run: echo "hello \${{ github.event.inputs.name }}" - run: echo "hello \${{ github.event.inputs.third-name }}" - run: echo "hello \${{ github.event.inputs.random }}" + - run: echo "hello \${{ inputs.random }}" + name: "\${{ fromJSON('test') == inputs.name }}" `; const result = await validate(createDocument("wf.yaml", input)); @@ -1202,6 +1204,20 @@ jobs: } }, severity: DiagnosticSeverity.Warning + }, + { + message: "Context access might be invalid: random", + range: { + end: { + character: 43, + line: 20 + }, + start: { + character: 23, + line: 20 + } + }, + severity: 2 } ]); }); diff --git a/actions-languageservice/src/validate.ts b/actions-languageservice/src/validate.ts index d5e9884..25e2d40 100644 --- a/actions-languageservice/src/validate.ts +++ b/actions-languageservice/src/validate.ts @@ -1,4 +1,11 @@ -import {Evaluator, Lexer, Parser} from "@github/actions-expressions"; +import { + data, + Evaluator, + ExpressionEvaluationError, + Lexer, + Parser, + wellKnownFunctions +} from "@github/actions-expressions"; import {Expr} from "@github/actions-expressions/ast"; import { convertWorkflowTemplate, @@ -202,7 +209,7 @@ async function validateExpression( try { const context = await getContext(namedContexts, contextProviderConfig, workflowContext, Mode.Validation); - const e = new Evaluator(expr, wrapDictionary(context)); + const e = new Evaluator(expr, wrapDictionary(context), validatorFunctions); e.evaluate(); // Any invalid context access would've thrown an error via the `ErrorDictionary`, for now we don't have to check the actual @@ -214,7 +221,25 @@ async function validateExpression( severity: DiagnosticSeverity.Warning, range: mapRange(expression.range) }); + } else if (e instanceof ExpressionEvaluationError) { + diagnostics.push({ + message: `Expression might be invalid: ${e.message}`, + severity: DiagnosticSeverity.Error, + range: mapRange(expression.range) + }); } } } } + +// Custom implementations for standard actions-expression functions used during validation. For example, +// for fromJson we'll most likely not have a valid input. In order to not throw, we'll always return an +// empty dictionary. +const validatorFunctions = new Map( + Object.entries({ + fromjson: { + ...wellKnownFunctions.fromjson, + call: () => new data.Dictionary() + } + }) +); From 05de7282bd0d01faeff79fb92b44d599aa9f7d65 Mon Sep 17 00:00:00 2001 From: Laura Yu <60276246+lauraway@users.noreply.github.com> Date: Wed, 18 Jan 2023 16:31:49 -0800 Subject: [PATCH 22/50] Add variables context provider (#88) --- actions-expressions/src/completion.test.ts | 15 ++ .../src/context-providers.ts | 4 +- .../src/context-providers/variables.ts | 144 ++++++++++++++++++ 3 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 actions-languageserver/src/context-providers/variables.ts diff --git a/actions-expressions/src/completion.test.ts b/actions-expressions/src/completion.test.ts index 0cadab9..0549e2b 100644 --- a/actions-expressions/src/completion.test.ts +++ b/actions-expressions/src/completion.test.ts @@ -35,6 +35,13 @@ const testContext = new Dictionary( value: new BooleanData(true) }) }, + { + key: "vars", + value: new Dictionary({ + key: "VAR_NAME", + value: new BooleanData(true) + }) + }, { key: "hashFiles(1,255)", value: new Dictionary() @@ -110,6 +117,14 @@ describe("auto-complete", () => { expect(testComplete("toJSON(secrets.")).toEqual(expected); }); + it("provides suggestions for variables", () => { + const expected = completionItems("VAR_NAME"); + + expect(testComplete("vars.V")).toEqual(expected); + expect(testComplete("1 == vars.F")).toEqual(expected); + expect(testComplete("toJSON(vars.")).toEqual(expected); + }); + it("provides suggestions for contexts in function call", () => { expect(testComplete("toJSON(env.|)")).toEqual(completionItems("BAR_TEST", "FOO")); }); diff --git a/actions-languageserver/src/context-providers.ts b/actions-languageserver/src/context-providers.ts index c0824ce..5d1f151 100644 --- a/actions-languageserver/src/context-providers.ts +++ b/actions-languageserver/src/context-providers.ts @@ -4,6 +4,7 @@ import {WorkflowContext} from "@github/actions-languageservice/context/workflow- import {Octokit} from "@octokit/rest"; import {getSecrets} from "./context-providers/secrets"; import {getStepsContext} from "./context-providers/steps"; +import {getVariables} from "./context-providers/variables"; import {RepositoryContext} from "./initializationOptions"; import {TTLCache} from "./utils/cache"; @@ -28,7 +29,8 @@ export function contextProviders( switch (name) { case "secrets": return await getSecrets(workflowContext, octokit, cache, repo, defaultContext); - + case "vars": + return await getVariables(workflowContext, octokit, cache, repo, defaultContext); case "steps": return await getStepsContext(octokit, cache, defaultContext, workflowContext); } diff --git a/actions-languageserver/src/context-providers/variables.ts b/actions-languageserver/src/context-providers/variables.ts new file mode 100644 index 0000000..5481bc4 --- /dev/null +++ b/actions-languageserver/src/context-providers/variables.ts @@ -0,0 +1,144 @@ +import {data, DescriptionDictionary} from "@github/actions-expressions"; +import {WorkflowContext} from "@github/actions-languageservice/context/workflow-context"; +import {isMapping, isString} from "@github/actions-workflow-parser"; +import {Octokit} from "@octokit/rest"; +import {Pair} from "@github/actions-expressions/data/expressiondata"; +import {RepositoryContext} from "../initializationOptions"; +import {StringData} from "@github/actions-expressions/data/index"; +import {TTLCache} from "../utils/cache"; + +export async function getVariables( + workflowContext: WorkflowContext, + octokit: Octokit, + cache: TTLCache, + repo: RepositoryContext, + defaultContext: DescriptionDictionary | undefined +): Promise { + let environmentName: string | undefined; + if (workflowContext?.job?.environment) { + if (isString(workflowContext.job.environment)) { + environmentName = workflowContext.job.environment.value; + } else if (isMapping(workflowContext.job.environment)) { + for (const x of workflowContext.job.environment) { + if (isString(x.key) && x.key.value === "name") { + if (isString(x.value)) { + environmentName = x.value.value; + } + break; + } + } + } + } + + const variables = await getRemoteVariables(octokit, cache, repo, environmentName); + + // Build combined map of variables + const variablesMap = new Map< + string, + { + key: string; + value: data.StringData; + description?: string; + } + >(); + + variables.repoVariables.forEach(variable => + variablesMap.set(variable.key.toLowerCase(), { + key: variable.key, + value: new data.StringData(variable.value.coerceString()), + description: `${variable.value.coerceString()} - Repository variable` + }) + ); + + // Override repo variables with environment veriables (if defined) + variables.environmentVariables.forEach(variable => + variablesMap.set(variable.key.toLowerCase(), { + key: variable.key, + value: new data.StringData(variable.value.coerceString()), + description: `${variable.value.coerceString()} - Variable for environment \`${environmentName}\`` + }) + ); + + const variablesContext = defaultContext || new DescriptionDictionary(); + + // Sort variables by key and add to context + Array.from(variablesMap.values()) + .sort((a, b) => a.key.localeCompare(b.key)) + .forEach(variable => variablesContext?.add(variable.key, variable.value, variable.description)); + + return variablesContext; +} + +export async function getRemoteVariables( + octokit: Octokit, + cache: TTLCache, + repo: RepositoryContext, + environmentName?: string +): Promise<{ + repoVariables: Pair[]; + environmentVariables: Pair[]; +}> { + // Repo variables + return { + repoVariables: await cache.get(`${repo.owner}/${repo.name}/vars`, undefined, () => + fetchVariables(octokit, repo.owner, repo.name) + ), + environmentVariables: + (environmentName && + (await cache.get(`${repo.owner}/${repo.name}/vars/environment/${environmentName}`, undefined, () => + fetchEnvironmentVariables(octokit, repo.id, environmentName) + ))) || + [] + }; +} + +async function fetchVariables(octokit: Octokit, owner: string, name: string): Promise { + try { + const response = (await octokit.paginate("GET /repos/{owner}/{repo}/actions/variables{?per_page}", { + owner: owner, + repo: name + })) as { + name: string; + value: string; + created_at: string; + updated_at: string; + }[]; + + return response.map(variable => { + return {key: variable.name, value: new StringData(variable.value)}; + }); + } catch (e) { + console.log("Failure to retrieve variables: ", e); + } + + return []; +} + +async function fetchEnvironmentVariables( + octokit: Octokit, + repositoryId: number, + environmentName: string +): Promise { + try { + const response = (await octokit.paginate( + "GET /repositories/{repository_id}/environments/{environment_name}/variables{?per_page}", + { + repository_id: repositoryId, + environment_name: environmentName + } + )) as { + name: string; + value: string; + created_at: string; + updated_at: string; + }[]; + + return response.map(variable => { + return {key: variable.name, value: new StringData(variable.value)}; + }); + } catch (e) { + console.log("Failure to retrieve environment variables: ", e); + } + + return []; +} From 8eeec23153fd979fe87937bdc15e02fa493a51f1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 19 Jan 2023 00:32:33 +0000 Subject: [PATCH 23/50] v0.1.86 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 1445606..effd44f 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.85", + "version": "0.1.86", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 2451abc..13f2504 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.85", + "version": "0.1.86", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.85", - "@github/actions-workflow-parser": "^0.1.85", + "@github/actions-languageservice": "^0.1.86", + "@github/actions-workflow-parser": "^0.1.86", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 5690346..03c2370 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.85", + "version": "0.1.86", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.85", - "@github/actions-workflow-parser": "^0.1.85", + "@github/actions-expressions": "^0.1.86", + "@github/actions-workflow-parser": "^0.1.86", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index ca03375..9622a67 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.85", + "version": "0.1.86", "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.85", + "@github/actions-expressions": "^0.1.86", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index b903ba5..8780776 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.85", + "version": "0.1.86", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.85", + "@github/actions-languageserver": "^0.1.86", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index a4511b8..f390843 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.85" + "version": "0.1.86" } diff --git a/package-lock.json b/package-lock.json index a2162bd..60a3a05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.85", + "version": "0.1.86", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.85", + "version": "0.1.86", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.85", - "@github/actions-workflow-parser": "^0.1.85", + "@github/actions-languageservice": "^0.1.86", + "@github/actions-workflow-parser": "^0.1.86", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.85", + "version": "0.1.86", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.85", - "@github/actions-workflow-parser": "^0.1.85", + "@github/actions-expressions": "^0.1.86", + "@github/actions-workflow-parser": "^0.1.86", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.85", + "version": "0.1.86", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.85", + "@github/actions-expressions": "^0.1.86", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.85", + "version": "0.1.86", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.85", + "@github/actions-languageserver": "^0.1.86", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.85", - "@github/actions-workflow-parser": "^0.1.85", + "@github/actions-languageservice": "^0.1.86", + "@github/actions-workflow-parser": "^0.1.86", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.85", - "@github/actions-workflow-parser": "^0.1.85", + "@github/actions-expressions": "^0.1.86", + "@github/actions-workflow-parser": "^0.1.86", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.85", + "@github/actions-expressions": "^0.1.86", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.85", + "@github/actions-languageserver": "^0.1.86", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From 7d9132fb6e58db28f5bc4405095d00feccd67a71 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Thu, 19 Jan 2023 09:58:50 -0800 Subject: [PATCH 24/50] Add comments to Evaluator --- actions-expressions/src/evaluator.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/actions-expressions/src/evaluator.ts b/actions-expressions/src/evaluator.ts index a1c76b3..54c27e6 100644 --- a/actions-expressions/src/evaluator.ts +++ b/actions-expressions/src/evaluator.ts @@ -20,6 +20,12 @@ import {TokenType} from "./lexer"; import {equals, falsy, greaterThan, lessThan, truthy} from "./result"; export class Evaluator implements ExprVisitor { + /** + * Creates a new evaluator + * @param n Parsed expression to evaluate + * @param context Context data to use + * @param functions Optional map of function implementations. If given, these will be preferred over the built-in functions. + */ constructor(private n: Expr, private context: data.Dictionary, private functions?: Map) {} public evaluate(): data.ExpressionData { From e01af9616bfddbb50a11fff6af08158ae18c23a0 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Thu, 19 Jan 2023 10:02:13 -0800 Subject: [PATCH 25/50] Add test case for validation in expression --- .../src/validate.expressions.test.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/actions-languageservice/src/validate.expressions.test.ts b/actions-languageservice/src/validate.expressions.test.ts index be91147..85e0a4f 100644 --- a/actions-languageservice/src/validate.expressions.test.ts +++ b/actions-languageservice/src/validate.expressions.test.ts @@ -1185,6 +1185,7 @@ jobs: - run: echo "hello \${{ github.event.inputs.name }}" - run: echo "hello \${{ github.event.inputs.third-name }}" - run: echo "hello \${{ github.event.inputs.random }}" + - run: echo \${{ fromJSON(inputs.random2) }} - run: echo "hello \${{ inputs.random }}" name: "\${{ fromJSON('test') == inputs.name }}" `; @@ -1205,16 +1206,30 @@ jobs: }, severity: DiagnosticSeverity.Warning }, + { + message: "Context access might be invalid: random2", + range: { + end: { + character: 47, + line: 20 + }, + start: { + character: 16, + line: 20 + } + }, + severity: 2 + }, { message: "Context access might be invalid: random", range: { end: { character: 43, - line: 20 + line: 21 }, start: { character: 23, - line: 20 + line: 21 } }, severity: 2 From a7fd04c47d829ee5746fa1301bf767e0cac4b062 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 19 Jan 2023 18:09:21 +0000 Subject: [PATCH 26/50] v0.1.87 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index effd44f..0b71aa9 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.86", + "version": "0.1.87", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 13f2504..2a6b723 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.86", + "version": "0.1.87", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.86", - "@github/actions-workflow-parser": "^0.1.86", + "@github/actions-languageservice": "^0.1.87", + "@github/actions-workflow-parser": "^0.1.87", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 03c2370..fc1f878 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.86", + "version": "0.1.87", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.86", - "@github/actions-workflow-parser": "^0.1.86", + "@github/actions-expressions": "^0.1.87", + "@github/actions-workflow-parser": "^0.1.87", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 9622a67..c3c0c58 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.86", + "version": "0.1.87", "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.86", + "@github/actions-expressions": "^0.1.87", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 8780776..fa67c38 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.86", + "version": "0.1.87", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.86", + "@github/actions-languageserver": "^0.1.87", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index f390843..be67e18 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.86" + "version": "0.1.87" } diff --git a/package-lock.json b/package-lock.json index 60a3a05..1b78857 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.86", + "version": "0.1.87", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.86", + "version": "0.1.87", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.86", - "@github/actions-workflow-parser": "^0.1.86", + "@github/actions-languageservice": "^0.1.87", + "@github/actions-workflow-parser": "^0.1.87", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.86", + "version": "0.1.87", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.86", - "@github/actions-workflow-parser": "^0.1.86", + "@github/actions-expressions": "^0.1.87", + "@github/actions-workflow-parser": "^0.1.87", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.86", + "version": "0.1.87", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.86", + "@github/actions-expressions": "^0.1.87", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.86", + "version": "0.1.87", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.86", + "@github/actions-languageserver": "^0.1.87", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.86", - "@github/actions-workflow-parser": "^0.1.86", + "@github/actions-languageservice": "^0.1.87", + "@github/actions-workflow-parser": "^0.1.87", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.86", - "@github/actions-workflow-parser": "^0.1.86", + "@github/actions-expressions": "^0.1.87", + "@github/actions-workflow-parser": "^0.1.87", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.86", + "@github/actions-expressions": "^0.1.87", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.86", + "@github/actions-languageserver": "^0.1.87", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From e6a2e3eb43879dd2cf5ceebd70516096fcd51165 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Wed, 18 Jan 2023 16:54:53 -0800 Subject: [PATCH 27/50] Fix a bunch of auto-complete issues --- actions-expressions/src/completion.test.ts | 106 +++++++++++++++--- actions-expressions/src/completion.ts | 49 ++++++-- .../src/complete.expressions.test.ts | 33 ++++++ actions-languageservice/src/complete.ts | 22 ++-- .../src/expression-validation/functions.ts | 13 +++ .../src/test-utils/cursor-position.test.ts | 8 ++ actions-languageservice/src/utils/range.ts | 21 ++-- actions-languageservice/src/validate.ts | 22 +--- .../src/templates/template-reader.ts | 1 - .../src/workflows/yaml-object-reader.ts | 12 +- 10 files changed, 214 insertions(+), 73 deletions(-) create mode 100644 actions-languageservice/src/expression-validation/functions.ts diff --git a/actions-expressions/src/completion.test.ts b/actions-expressions/src/completion.test.ts index 0549e2b..3ef485d 100644 --- a/actions-expressions/src/completion.test.ts +++ b/actions-expressions/src/completion.test.ts @@ -3,7 +3,8 @@ import {DescriptionDictionary} from "./completion/descriptionDictionary"; import {BooleanData} from "./data/boolean"; import {Dictionary} from "./data/dictionary"; import {StringData} from "./data/string"; -import {FunctionInfo} from "./funcs/info"; +import {wellKnownFunctions} from "./funcs"; +import {FunctionDefinition, FunctionInfo} from "./funcs/info"; import {Lexer, TokenType} from "./lexer"; const testContext = new Dictionary( @@ -22,11 +23,21 @@ const testContext = new Dictionary( }, { key: "github", - value: new DescriptionDictionary({ - key: "actor", - value: new StringData(""), - description: "The name of the person or app that initiated the workflow. For example, octocat." - }) + value: new DescriptionDictionary( + { + key: "actor", + value: new StringData(""), + description: "The name of the person or app that initiated the workflow. For example, octocat." + }, + { + key: "inputs", + value: new DescriptionDictionary({ + key: "name", + value: new StringData("monalisa"), + description: "The name of a person" + }) + } + ) }, { key: "secrets", @@ -50,11 +61,11 @@ const testContext = new Dictionary( const testFunctions: FunctionInfo[] = []; -const testComplete = (input: string): CompletionItem[] => { +const testComplete = (input: string, functions?: Map): CompletionItem[] => { const pos = input.indexOf("|"); input = input.replace("|", ""); - const results = complete(input.slice(0, pos >= 0 ? pos : input.length), testContext, testFunctions); + const results = complete(input.slice(0, pos >= 0 ? pos : input.length), testContext, testFunctions, functions); return results; }; @@ -75,6 +86,7 @@ describe("auto-complete", () => { expect(testComplete("to")).toContainEqual(expected); expect(testComplete("toJs")).toContainEqual(expected); expect(testComplete("1 == toJS")).toContainEqual(expected); + expect(testComplete("1 == (toJS")).toContainEqual(expected); expect(testComplete("toJS| == 1")).toContainEqual(expected); }); @@ -92,21 +104,51 @@ describe("auto-complete", () => { }); }); + describe("functions", () => { + it("uses provided function definitions", () => { + expect( + testComplete( + "fromJson('invalid').|", + new Map( + Object.entries({ + fromjson: { + ...wellKnownFunctions.fromjson, + call: () => + new Dictionary({ + key: "foo", + value: new StringData("bar") + }) + } + }) + ) + ) + ).toEqual([{label: "foo", function: false}]); + }); + }); + describe("for contexts", () => { - it("provides suggestions for env", () => { + it("provides suggestions for top-level context", () => { const expected = completionItems("BAR_TEST", "FOO"); expect(testComplete("env.X")).toEqual(expected); expect(testComplete("1 == env.F")).toEqual(expected); expect(testComplete("env.")).toEqual(expected); expect(testComplete("env.FOO")).toEqual(expected); + expect(testComplete("(env).")).toEqual(expected); }); - it("includes descriptions", () => { - expect(testComplete("github.")).toContainEqual({ - label: "actor", - function: false, - description: "The name of the person or app that initiated the workflow. For example, octocat." - }); + it("provides suggestions for nested context", () => { + const expected: CompletionItem[] = [ + { + label: "name", + function: false, + description: "The name of a person" + } + ]; + expect(testComplete("github.inputs.|")).toEqual(expected); + expect(testComplete("(github).inputs.|")).toEqual(expected); + expect(testComplete("(github.inputs).|")).toEqual(expected); + expect(testComplete("'test' == github.inputs.|")).toEqual(expected); + expect(testComplete("github.inputs.| == 'monalisa'")).toEqual(expected); }); it("provides suggestions for secrets", () => { @@ -127,6 +169,25 @@ describe("auto-complete", () => { it("provides suggestions for contexts in function call", () => { expect(testComplete("toJSON(env.|)")).toEqual(completionItems("BAR_TEST", "FOO")); + expect(testComplete("toJSON(secrets.")).toEqual(completionItems("AWS_TOKEN")); + }); + + describe("with descriptions", () => { + it("top-level", () => { + expect(testComplete("github.")).toContainEqual({ + label: "actor", + function: false, + description: "The name of the person or app that initiated the workflow. For example, octocat." + }); + }); + + it("nested", () => { + expect(testComplete("github.inputs.")).toContainEqual({ + label: "name", + function: false, + description: "The name of a person" + }); + }); }); }); }); @@ -152,6 +213,21 @@ describe("trimTokenVector", () => { input: "github.mona == github.act", expected: [TokenType.IDENTIFIER, TokenType.DOT, TokenType.IDENTIFIER, TokenType.EOF] }, + { + input: "github.mona == (github).act", + expected: [ + TokenType.LEFT_PAREN, + TokenType.IDENTIFIER, + TokenType.RIGHT_PAREN, + TokenType.DOT, + TokenType.IDENTIFIER, + TokenType.EOF + ] + }, + { + input: "github.mona == (github.", + expected: [TokenType.IDENTIFIER, TokenType.DOT, TokenType.EOF] + }, { input: "github['test'].", expected: [ diff --git a/actions-expressions/src/completion.ts b/actions-expressions/src/completion.ts index b6a965b..252bb44 100644 --- a/actions-expressions/src/completion.ts +++ b/actions-expressions/src/completion.ts @@ -3,7 +3,7 @@ import {Dictionary, isDictionary} from "./data/dictionary"; import {ExpressionData} from "./data/expressiondata"; import {Evaluator} from "./evaluator"; import {wellKnownFunctions} from "./funcs"; -import {FunctionInfo} from "./funcs/info"; +import {FunctionDefinition, FunctionInfo} from "./funcs/info"; import {Lexer, Token, TokenType} from "./lexer"; import {Parser} from "./parser"; @@ -13,15 +13,27 @@ export type CompletionItem = { function: boolean; }; -// Complete returns a list of completion items for the given expression. -// -// The main functionality is auto-completing functions and context access: -// We can only provide assistance if the input is in one of the following forms (with | denoting the cursor position): -// - context.path.inp| or context.path['inp| -- auto-complete context access -// - context.path.| or context.path['| -- auto-complete context access -// - toJS| -- auto-complete function call or top-level -// - | -- auto-complete function call or top-level context access -export function complete(input: string, context: Dictionary, extensionFunctions: FunctionInfo[]): CompletionItem[] { +/** + * Complete returns a list of completion items for the given expression. + * The main functionality is auto-completing functions and context access: + * We can only provide assistance if the input is in one of the following forms (with | denoting the cursor position): + * - context.path.inp| or context.path['inp| -- auto-complete context access + * - context.path.| or context.path['| -- auto-complete context access + * - toJS| -- auto-complete function call or top-level + * - | -- auto-complete function call or top-level context access + * + * @param input Input expression + * @param context Context available for the expression + * @param extensionFunctions List of functions available + * @param functions Optional map of functions to use during evaluation + * @returns Array of completion items + */ +export function complete( + input: string, + context: Dictionary, + extensionFunctions: FunctionInfo[], + functions?: Map +): CompletionItem[] { // Lex const lexer = new Lexer(input); const lexResult = lexer.lex(); @@ -70,7 +82,7 @@ export function complete(input: string, context: Dictionary, extensionFunctions: ); const expr = p.parse(); - const ev = new Evaluator(expr, context); + const ev = new Evaluator(expr, context, functions); const result = ev.evaluate(); return contextKeys(result); @@ -122,9 +134,24 @@ function completionItemFromContext(pair: DescriptionPair): CompletionItem { export function trimTokenVector(tokenVector: Token[]): Token[] { let tokenIdx = tokenVector.length; + let openParen = 0; + while (tokenIdx > 0) { const token = tokenVector[tokenIdx - 1]; switch (token.type) { + case TokenType.LEFT_PAREN: + if (openParen == 0) { + // Encounterend an open parenthesis witout a closing first, stop here + break; + } + tokenIdx--; + continue; + + case TokenType.RIGHT_PAREN: + openParen++; + tokenIdx--; + continue; + case TokenType.IDENTIFIER: case TokenType.DOT: case TokenType.EOF: diff --git a/actions-languageservice/src/complete.expressions.test.ts b/actions-languageservice/src/complete.expressions.test.ts index 90a5b09..f2269f6 100644 --- a/actions-languageservice/src/complete.expressions.test.ts +++ b/actions-languageservice/src/complete.expressions.test.ts @@ -37,6 +37,10 @@ describe("expressions", () => { expect(test("${{ github.| == 'test' }}")).toBe(" github."); expect(test("test ${{ github.| == 'test' }}")).toBe(" github."); expect(test("${{ vars }} ${{ gh |}}")).toBe(" gh "); + + expect(test("${{ test.|")).toBe(" test."); + expect(test("${{ test.| }}")).toBe(" test."); + expect(test("${{ 1 == (test.|)")).toBe(" 1 == (test."); }); describe("top-level auto-complete", () => { @@ -58,6 +62,16 @@ describe("expressions", () => { ]); }); + it("within parentheses", async () => { + const result = await complete( + ...getPositionFromCursor("run-name: ${{ 1 == (github.|) }}"), + undefined, + contextProviderConfig + ); + + expect(result.map(x => x.label)).toEqual(["event"]); + }); + it("contains description", async () => { const input = "run-name: ${{ github.| }}"; const result = await complete(...getPositionFromCursor(input), undefined, undefined); @@ -202,6 +216,25 @@ jobs: }); }); + it("nested with parentheses", async () => { + const input = `on: + workflow_dispatch: + inputs: + test: + type: string + +jobs: + build: + runs-on: ubuntu-latest + env: + foo: '{}' + steps: + - name: "\${{ fromJSON('test') == (inputs.|) }}"`; + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + + expect(result.map(x => x.label)).toEqual(["test"]); + }); + it("nested auto-complete", async () => { const input = "run-name: ${{ github.| }}"; const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index 44c3c3f..281b235 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -14,6 +14,8 @@ import {CompletionItem, CompletionItemKind, CompletionItemTag, Range, TextEdit} import {ContextProviderConfig} from "./context-providers/config"; import {getContext, Mode} from "./context-providers/default"; import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; +import {validatorFunctions} from "./expression-validation/functions"; +import {error} from "./log"; import {nullTrace} from "./nulltrace"; import {findToken} from "./utils/find-token"; import {guessIndentation} from "./utils/indentation-guesser"; @@ -75,13 +77,14 @@ export async function complete( // Transform the overall position into a node relative position let relCharPos: number = 0; - const lineDiff = newPos.line - token.range!.start[0]; - if (token.range!.start[0] !== token.range!.end[0]) { + const range = mapRange(token.range!); + if (range.start.line !== range.end.line) { const lines = currentInput.split("\n"); + const lineDiff = newPos.line - range.start.line - 1; const linesBeforeCusor = lines.slice(0, lineDiff); - relCharPos = linesBeforeCusor.join("\n").length + 1 + newPos.character; + relCharPos = linesBeforeCusor.join("\n").length + newPos.character + 1; } else { - relCharPos = newPos.character - token.range!.start[1] + 1; + relCharPos = newPos.character - range.start.character; } const expressionInput = (getExpressionInput(currentInput, relCharPos) || "").trim(); @@ -89,9 +92,14 @@ export async function complete( const allowedContext = token.definitionInfo?.allowedContext || []; const context = await getContext(allowedContext, contextProviderConfig, workflowContext, Mode.Completion); - return completeExpression(expressionInput, context, []).map(item => - mapExpressionCompletionItem(item, currentInput[relCharPos]) - ); + try { + return completeExpression(expressionInput, context, [], validatorFunctions).map(item => + mapExpressionCompletionItem(item, currentInput[relCharPos]) + ); + } catch (e: any) { + error(`Error while completing expression: '${e?.message || ""}'`); + return []; + } } } diff --git a/actions-languageservice/src/expression-validation/functions.ts b/actions-languageservice/src/expression-validation/functions.ts new file mode 100644 index 0000000..939cfa6 --- /dev/null +++ b/actions-languageservice/src/expression-validation/functions.ts @@ -0,0 +1,13 @@ +import {data, wellKnownFunctions} from "@github/actions-expressions"; + +// Custom implementations for standard actions-expression functions used during validation and auto-completion. +// For example, for fromJson we'll most likely not have a valid input. In order to not throw, we'll always +// return an empty dictionary. +export const validatorFunctions = new Map( + Object.entries({ + fromjson: { + ...wellKnownFunctions.fromjson, + call: () => new data.Dictionary() + } + }) +); diff --git a/actions-languageservice/src/test-utils/cursor-position.test.ts b/actions-languageservice/src/test-utils/cursor-position.test.ts index 3f33e63..4cc3002 100644 --- a/actions-languageservice/src/test-utils/cursor-position.test.ts +++ b/actions-languageservice/src/test-utils/cursor-position.test.ts @@ -21,4 +21,12 @@ describe("getPositionFromCursor", () => { expect(position).toEqual({line: 0, character: 0}); expect(newDoc.getText()).toEqual("on: push\njobs:"); }); + + it("handles a cursor in the middle of the document", () => { + const input = "on: push\n jobs|:\n build:"; + const [newDoc, position] = getPositionFromCursor(input); + + expect(position).toEqual({line: 1, character: 6}); + expect(newDoc.getText()).toEqual("on: push\n jobs:\n build:"); + }); }); diff --git a/actions-languageservice/src/utils/range.ts b/actions-languageservice/src/utils/range.ts index d16085a..13e6c5a 100644 --- a/actions-languageservice/src/utils/range.ts +++ b/actions-languageservice/src/utils/range.ts @@ -1,5 +1,5 @@ -import {TokenRange} from "@github/actions-workflow-parser/templates/tokens/token-range"; -import {Range} from "vscode-languageserver-types"; +import {Position as TokenPosition, TokenRange} from "@github/actions-workflow-parser/templates/tokens/token-range"; +import {Position, Range} from "vscode-languageserver-types"; export function mapRange(range: TokenRange | undefined): Range { if (!range) { @@ -16,13 +16,14 @@ export function mapRange(range: TokenRange | undefined): Range { } return { - start: { - line: range.start[0] - 1, - character: range.start[1] - 1 - }, - end: { - line: range.end[0] - 1, - character: range.end[1] - 1 - } + start: mapPosition(range.start), + end: mapPosition(range.end) + }; +} + +export function mapPosition(position: TokenPosition): Position { + return { + line: position[0] - 1, + character: position[1] - 1 }; } diff --git a/actions-languageservice/src/validate.ts b/actions-languageservice/src/validate.ts index 25e2d40..0f82985 100644 --- a/actions-languageservice/src/validate.ts +++ b/actions-languageservice/src/validate.ts @@ -1,11 +1,4 @@ -import { - data, - Evaluator, - ExpressionEvaluationError, - Lexer, - Parser, - wellKnownFunctions -} from "@github/actions-expressions"; +import {Evaluator, ExpressionEvaluationError, Lexer, Parser} from "@github/actions-expressions"; import {Expr} from "@github/actions-expressions/ast"; import { convertWorkflowTemplate, @@ -29,6 +22,7 @@ import {ContextProviderConfig} from "./context-providers/config"; import {getContext, Mode} from "./context-providers/default"; import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; import {AccessError, wrapDictionary} from "./expression-validation/error-dictionary"; +import {validatorFunctions} from "./expression-validation/functions"; import {error} from "./log"; import {nullTrace} from "./nulltrace"; import {findToken} from "./utils/find-token"; @@ -231,15 +225,3 @@ async function validateExpression( } } } - -// Custom implementations for standard actions-expression functions used during validation. For example, -// for fromJson we'll most likely not have a valid input. In order to not throw, we'll always return an -// empty dictionary. -const validatorFunctions = new Map( - Object.entries({ - fromjson: { - ...wellKnownFunctions.fromjson, - call: () => new data.Dictionary() - } - }) -); diff --git a/actions-workflow-parser/src/templates/template-reader.ts b/actions-workflow-parser/src/templates/template-reader.ts index e7f4d87..171ae72 100644 --- a/actions-workflow-parser/src/templates/template-reader.ts +++ b/actions-workflow-parser/src/templates/template-reader.ts @@ -451,7 +451,6 @@ class TemplateReader { const allowedContext = definitionInfo.allowedContext; const raw = token.source || token.value; - // Check if the value is definitely a literal let startExpression: number = raw.indexOf(OPEN_EXPRESSION); if (startExpression < 0) { // Doesn't contain "${{" diff --git a/actions-workflow-parser/src/workflows/yaml-object-reader.ts b/actions-workflow-parser/src/workflows/yaml-object-reader.ts index ce21e07..e4bc3d9 100644 --- a/actions-workflow-parser/src/workflows/yaml-object-reader.ts +++ b/actions-workflow-parser/src/workflows/yaml-object-reader.ts @@ -1,6 +1,6 @@ import {isCollection, isDocument, isMap, isPair, isScalar, isSeq, LineCounter, parseDocument, Scalar} from "yaml"; -import {LinePos} from "yaml/dist/errors"; -import {NodeBase} from "yaml/dist/nodes/Node"; +import type {LinePos} from "yaml/dist/errors"; +import type {NodeBase} from "yaml/dist/nodes/Node"; import {ObjectReader} from "../templates/object-reader"; import {EventType, ParseEvent} from "../templates/parse-event"; import {TemplateContext} from "../templates/template-context"; @@ -110,14 +110,8 @@ export class YamlObjectReader implements ObjectReader { case "boolean": return new BooleanToken(fileId, range, value, undefined); case "string": { - // If the string is a YAML block string, include the original source let source: string | undefined; - if ( - (token.type === "BLOCK_LITERAL" || // | multi-line strings - token.type === "BLOCK_FOLDED") && // > multi-line strings - token.srcToken && - token.srcToken.type === "block-scalar" - ) { + if (token.srcToken && "source" in token.srcToken) { source = token.srcToken.source; } From c3fb85be5d4e057a0567139fd44ac89e7d459b61 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Thu, 19 Jan 2023 08:44:37 -0800 Subject: [PATCH 28/50] Fix typos in comment Co-authored-by: Josh Gross --- actions-expressions/src/completion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions-expressions/src/completion.ts b/actions-expressions/src/completion.ts index 252bb44..dfb6d7b 100644 --- a/actions-expressions/src/completion.ts +++ b/actions-expressions/src/completion.ts @@ -141,7 +141,7 @@ export function trimTokenVector(tokenVector: Token[]): Token[] { switch (token.type) { case TokenType.LEFT_PAREN: if (openParen == 0) { - // Encounterend an open parenthesis witout a closing first, stop here + // Encountered an open parenthesis without a closing first, stop here break; } tokenIdx--; From dc65810e7062f799ddea2cfe9b1a41a21eb07b4a Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Thu, 19 Jan 2023 13:15:44 -0800 Subject: [PATCH 29/50] Support multiple unbalanced parentheses --- actions-expressions/src/completion.test.ts | 2 ++ actions-expressions/src/completion.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/actions-expressions/src/completion.test.ts b/actions-expressions/src/completion.test.ts index 3ef485d..cdcb6e8 100644 --- a/actions-expressions/src/completion.test.ts +++ b/actions-expressions/src/completion.test.ts @@ -88,6 +88,8 @@ describe("auto-complete", () => { expect(testComplete("1 == toJS")).toContainEqual(expected); expect(testComplete("1 == (toJS")).toContainEqual(expected); expect(testComplete("toJS| == 1")).toContainEqual(expected); + expect(testComplete("(toJS| == (foo.bar)")).toContainEqual(expected); + expect(testComplete("(((toJS| == (foo.bar)")).toContainEqual(expected); }); it("removes parentheses from passed in function context", () => { diff --git a/actions-expressions/src/completion.ts b/actions-expressions/src/completion.ts index dfb6d7b..7a29a60 100644 --- a/actions-expressions/src/completion.ts +++ b/actions-expressions/src/completion.ts @@ -144,6 +144,7 @@ export function trimTokenVector(tokenVector: Token[]): Token[] { // Encountered an open parenthesis without a closing first, stop here break; } + openParen--; tokenIdx--; continue; From 5a2d53882c40bcf77c4bc481123c09e5107bfea9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 19 Jan 2023 21:20:13 +0000 Subject: [PATCH 30/50] v0.1.88 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 0b71aa9..4752148 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.87", + "version": "0.1.88", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 2a6b723..75e0dac 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.87", + "version": "0.1.88", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.87", - "@github/actions-workflow-parser": "^0.1.87", + "@github/actions-languageservice": "^0.1.88", + "@github/actions-workflow-parser": "^0.1.88", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index fc1f878..166cfe8 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.87", + "version": "0.1.88", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.87", - "@github/actions-workflow-parser": "^0.1.87", + "@github/actions-expressions": "^0.1.88", + "@github/actions-workflow-parser": "^0.1.88", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index c3c0c58..1c0a55d 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.87", + "version": "0.1.88", "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.87", + "@github/actions-expressions": "^0.1.88", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index fa67c38..c167397 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.87", + "version": "0.1.88", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.87", + "@github/actions-languageserver": "^0.1.88", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index be67e18..0c1361a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.87" + "version": "0.1.88" } diff --git a/package-lock.json b/package-lock.json index 1b78857..e3e667e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.87", + "version": "0.1.88", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.87", + "version": "0.1.88", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.87", - "@github/actions-workflow-parser": "^0.1.87", + "@github/actions-languageservice": "^0.1.88", + "@github/actions-workflow-parser": "^0.1.88", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.87", + "version": "0.1.88", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.87", - "@github/actions-workflow-parser": "^0.1.87", + "@github/actions-expressions": "^0.1.88", + "@github/actions-workflow-parser": "^0.1.88", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.87", + "version": "0.1.88", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.87", + "@github/actions-expressions": "^0.1.88", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.87", + "version": "0.1.88", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.87", + "@github/actions-languageserver": "^0.1.88", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.87", - "@github/actions-workflow-parser": "^0.1.87", + "@github/actions-languageservice": "^0.1.88", + "@github/actions-workflow-parser": "^0.1.88", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.87", - "@github/actions-workflow-parser": "^0.1.87", + "@github/actions-expressions": "^0.1.88", + "@github/actions-workflow-parser": "^0.1.88", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.87", + "@github/actions-expressions": "^0.1.88", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.87", + "@github/actions-languageserver": "^0.1.88", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From c6f490c62d1e3278d8d68c3d1c5342ab43225ccb Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Thu, 19 Jan 2023 17:20:37 -0800 Subject: [PATCH 31/50] Improve auto-completion for `if:` properties --- .../src/complete.expressions.test.ts | 89 +++++++++++++++++-- actions-languageservice/src/complete.ts | 8 +- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/actions-languageservice/src/complete.expressions.test.ts b/actions-languageservice/src/complete.expressions.test.ts index f2269f6..5e50813 100644 --- a/actions-languageservice/src/complete.expressions.test.ts +++ b/actions-languageservice/src/complete.expressions.test.ts @@ -30,6 +30,7 @@ describe("expressions", () => { return getExpressionInput(doc.getText(), pos.character); }; + // With ${{ }} expect(test("${{ gh |")).toBe(" gh "); expect(test("${{ gh |}}")).toBe(" gh "); expect(test("${{ vars| == 'test' }}")).toBe(" vars"); @@ -41,6 +42,18 @@ describe("expressions", () => { expect(test("${{ test.|")).toBe(" test."); expect(test("${{ test.| }}")).toBe(" test."); expect(test("${{ 1 == (test.|)")).toBe(" 1 == (test."); + + // Without ${{ }} + expect(test("gh |")).toBe("gh "); + expect(test("gh |}}")).toBe("gh "); + expect(test("vars| == 'test' }}")).toBe("vars"); + expect(test("fromJso|('test').bar == 'test' }}")).toBe("fromJso"); + expect(test("github.| == 'test' }}")).toBe("github."); + expect(test("github.| == 'test' }}")).toBe("github."); + + expect(test("test.|")).toBe("test."); + expect(test("test.| }}")).toBe("test."); + expect(test("1 == (test.|)")).toBe("1 == (test."); }); describe("top-level auto-complete", () => { @@ -250,30 +263,90 @@ jobs: expect(result.map(x => x.label)).toEqual(["arch", "name", "os", "temp", "tool_cache"]); }); - it("job if", async () => { - const input = `on: push + describe("job if", () => { + describe("without ${{", () => { + it("simple", async () => { + const input = `on: push jobs: build: if: github.| runs-on: ubuntu-latest steps: - run: echo`; - const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); - expect(result.map(x => x.label)).toEqual(["event"]); + expect(result.map(x => x.label)).toEqual(["event"]); + }); + + it("complex", async () => { + const input = `on: push +jobs: + build: + if: false && github.| == 'some-repo' + runs-on: ubuntu-latest + steps: + - run: echo`; + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + + expect(result.map(x => x.label)).toEqual(["event"]); + }); + }); + + describe("with ${{", () => { + it("simple", async () => { + const input = `on: push +jobs: + build: + if: \${{ github.| }} + runs-on: ubuntu-latest + steps: + - run: echo`; + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + + expect(result.map(x => x.label)).toEqual(["event"]); + }); + + it("complex", async () => { + const input = `on: push +jobs: + build: + if: \${{ false && github.| == 'some-repo' }} + runs-on: ubuntu-latest + steps: + - run: echo`; + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + + expect(result.map(x => x.label)).toEqual(["event"]); + }); + }); }); - it("step if", async () => { - const input = `on: push + describe("step if", () => { + it("with ${{", async () => { + const input = `on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + - run: echo + if: \${{ github.| }}`; + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + + expect(result.map(x => x.label)).toEqual(["event"]); + }); + + it("without ${{", async () => { + const input = `on: push jobs: build: runs-on: ubuntu-latest steps: - run: echo if: github.|`; - const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); + const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); - expect(result.map(x => x.label)).toEqual(["event"]); + expect(result.map(x => x.label)).toEqual(["event"]); + }); }); }); diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index 281b235..36efd5a 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -27,12 +27,14 @@ import {definitionValues} from "./value-providers/definition"; export function getExpressionInput(input: string, pos: number): string { // Find start marker around the cursor position - const startPos = input.lastIndexOf(OPEN_EXPRESSION, pos); + let startPos = input.lastIndexOf(OPEN_EXPRESSION, pos); if (startPos === -1) { - return input; + startPos = 0; + } else { + startPos += OPEN_EXPRESSION.length; } - return input.substring(startPos + OPEN_EXPRESSION.length, pos); + return input.substring(startPos, pos); } export async function complete( From 675e8f1307247006cd2fd62fcc6c75279375adba Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 20 Jan 2023 17:52:20 +0000 Subject: [PATCH 32/50] v0.1.89 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 4752148..fa9937a 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.88", + "version": "0.1.89", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 75e0dac..c5bcdbe 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.88", + "version": "0.1.89", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.88", - "@github/actions-workflow-parser": "^0.1.88", + "@github/actions-languageservice": "^0.1.89", + "@github/actions-workflow-parser": "^0.1.89", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 166cfe8..c25a8a3 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.88", + "version": "0.1.89", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.88", - "@github/actions-workflow-parser": "^0.1.88", + "@github/actions-expressions": "^0.1.89", + "@github/actions-workflow-parser": "^0.1.89", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 1c0a55d..9da76a5 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.88", + "version": "0.1.89", "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.88", + "@github/actions-expressions": "^0.1.89", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index c167397..54330dd 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.88", + "version": "0.1.89", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.88", + "@github/actions-languageserver": "^0.1.89", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 0c1361a..f8d21b2 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.88" + "version": "0.1.89" } diff --git a/package-lock.json b/package-lock.json index e3e667e..f00955b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.88", + "version": "0.1.89", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.88", + "version": "0.1.89", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.88", - "@github/actions-workflow-parser": "^0.1.88", + "@github/actions-languageservice": "^0.1.89", + "@github/actions-workflow-parser": "^0.1.89", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.88", + "version": "0.1.89", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.88", - "@github/actions-workflow-parser": "^0.1.88", + "@github/actions-expressions": "^0.1.89", + "@github/actions-workflow-parser": "^0.1.89", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.88", + "version": "0.1.89", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.88", + "@github/actions-expressions": "^0.1.89", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.88", + "version": "0.1.89", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.88", + "@github/actions-languageserver": "^0.1.89", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.88", - "@github/actions-workflow-parser": "^0.1.88", + "@github/actions-languageservice": "^0.1.89", + "@github/actions-workflow-parser": "^0.1.89", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.88", - "@github/actions-workflow-parser": "^0.1.88", + "@github/actions-expressions": "^0.1.89", + "@github/actions-workflow-parser": "^0.1.89", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.88", + "@github/actions-expressions": "^0.1.89", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.88", + "@github/actions-languageserver": "^0.1.89", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From 378d2ab7996ecb4ccc836f3fb6d4d5663b706a76 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Fri, 20 Jan 2023 18:38:56 -0500 Subject: [PATCH 33/50] Support `client_payload` for `repository_dispatch` events --- .../src/context-providers/github.ts | 17 +++++++++++++---- .../src/validate.expressions.test.ts | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/actions-languageservice/src/context-providers/github.ts b/actions-languageservice/src/context-providers/github.ts index 14a9e69..1b14af2 100644 --- a/actions-languageservice/src/context-providers/github.ts +++ b/actions-languageservice/src/context-providers/github.ts @@ -89,17 +89,26 @@ function getEventContext(workflowContext: WorkflowContext): ExpressionData { for (const e of events) { const payload = eventPayloads[e]; if (payload) { - merge(d, payload); + const anyKeys = ANY_KEYS[e] || []; + merge(d, payload, anyKeys); } } return d; } -function merge(d: data.Dictionary, toAdd: Object): data.Dictionary { +// These events have a top-level object that can be any type +const ANY_KEYS: Record = { + repository_dispatch: ["client_payload"] +}; + +function merge(d: data.Dictionary, toAdd: Object, anyKeys: string[]): data.Dictionary { for (const [key, value] of Object.entries(toAdd)) { - if (value && typeof value === "object" && !d.get(key)) { - d.add(key, merge(new data.Dictionary(), value)); + if (anyKeys.includes(key)) { + d.add(key, new data.Null()); + } else if (value && typeof value === "object" && !d.get(key)) { + // Only use anyKeys for the top-level object + d.add(key, merge(new data.Dictionary(), value, [])); } else { d.add(key, new data.Null()); } diff --git a/actions-languageservice/src/validate.expressions.test.ts b/actions-languageservice/src/validate.expressions.test.ts index 85e0a4f..9d05070 100644 --- a/actions-languageservice/src/validate.expressions.test.ts +++ b/actions-languageservice/src/validate.expressions.test.ts @@ -1236,5 +1236,23 @@ jobs: } ]); }); + + it("allows any property in client_payload", async () => { + const input = ` +on: + repository_dispatch: + types: [test] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - run: echo \${{ github.event.client_payload.anything }} + - run: echo \${{ github.event.client_payload.branch }}` + + const result = await validate(createDocument("wf.yaml", input)); + + expect(result).toEqual([]); + }); }); }); From eab53474cb3dae9f5d71bc83ccc614117ac42b45 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Fri, 20 Jan 2023 17:20:21 -0800 Subject: [PATCH 34/50] Support webWorker clients --- actions-languageserver/src/index.ts | 27 +++++++++++++++++++++++---- actions-languageserver/tsconfig.json | 3 ++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/actions-languageserver/src/index.ts b/actions-languageserver/src/index.ts index e4ae531..c823c83 100644 --- a/actions-languageserver/src/index.ts +++ b/actions-languageserver/src/index.ts @@ -1,7 +1,26 @@ -import {createConnection} from "vscode-languageserver/node"; +import {Connection} from "vscode-languageserver"; +import { + BrowserMessageReader, + BrowserMessageWriter, + createConnection as createBrowserConnection +} from "vscode-languageserver/browser"; +import {createConnection as createNodeConnection} from "vscode-languageserver/node"; import {initConnection} from "./connection"; -// By default create node connection -const connection = createConnection(); -initConnection(connection); +/** Helper function determining whether we are executing with node runtime */ +function isNode(): boolean { + return typeof process !== "undefined" && process.versions?.node != null; +} + +function getConnection(): Connection { + if (isNode()) { + return createNodeConnection(); + } else { + const messageReader = new BrowserMessageReader(self); + const messageWriter = new BrowserMessageWriter(self); + return createBrowserConnection(messageReader, messageWriter); + } +} + +initConnection(getConnection()); diff --git a/actions-languageserver/tsconfig.json b/actions-languageserver/tsconfig.json index 93b16aa..d2faef8 100644 --- a/actions-languageserver/tsconfig.json +++ b/actions-languageserver/tsconfig.json @@ -7,7 +7,8 @@ "forceConsistentCasingInFileNames": true, "sourceMap": true, "strict": true, - "moduleResolution": "node" + "moduleResolution": "node", + "lib": ["es6", "webworker"] }, "watchOptions": { "watchFile": "useFsEvents", From 4d3c5e8e2bf87be764c913e600aefc1f7fea10f8 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Fri, 20 Jan 2023 17:23:39 -0800 Subject: [PATCH 35/50] Remove work-around --- .../src/service-worker/service-worker.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/browser-playground/src/service-worker/service-worker.ts b/browser-playground/src/service-worker/service-worker.ts index 202ce2d..5cb35c1 100644 --- a/browser-playground/src/service-worker/service-worker.ts +++ b/browser-playground/src/service-worker/service-worker.ts @@ -1,10 +1 @@ -import {BrowserMessageReader, BrowserMessageWriter, createConnection} from "vscode-languageserver/browser.js"; - -import {initConnection} from "@github/actions-languageserver/connection"; - -const messageReader = new BrowserMessageReader(self); -const messageWriter = new BrowserMessageWriter(self); - -const connection = createConnection(messageReader, messageWriter); - -initConnection(connection); +import "@github/actions-languageserver"; From e8bf17771ce4048f046caf48e4ff3791bb9c27cd Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Mon, 23 Jan 2023 11:35:09 -0500 Subject: [PATCH 36/50] Allow `{}` to represent any value in event payloads --- .../events/repository_dispatch.json | 5 +--- .../src/context-providers/github.ts | 24 +++++++++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/actions-languageservice/src/context-providers/events/repository_dispatch.json b/actions-languageservice/src/context-providers/events/repository_dispatch.json index fd32d52..0f3c2b4 100644 --- a/actions-languageservice/src/context-providers/events/repository_dispatch.json +++ b/actions-languageservice/src/context-providers/events/repository_dispatch.json @@ -1,10 +1,7 @@ { "action": "on-demand-test", "branch": "master", - "client_payload": { - "unit": false, - "integration": true - }, + "client_payload": {}, "repository": { "id": 17273051, "node_id": "MDEwOlJlcG9zaXRvcnkxNzI3MzA1MQ==", diff --git a/actions-languageservice/src/context-providers/github.ts b/actions-languageservice/src/context-providers/github.ts index 1b14af2..af43d20 100644 --- a/actions-languageservice/src/context-providers/github.ts +++ b/actions-languageservice/src/context-providers/github.ts @@ -89,26 +89,24 @@ function getEventContext(workflowContext: WorkflowContext): ExpressionData { for (const e of events) { const payload = eventPayloads[e]; if (payload) { - const anyKeys = ANY_KEYS[e] || []; - merge(d, payload, anyKeys); + merge(d, payload); } } return d; } -// These events have a top-level object that can be any type -const ANY_KEYS: Record = { - repository_dispatch: ["client_payload"] -}; - -function merge(d: data.Dictionary, toAdd: Object, anyKeys: string[]): data.Dictionary { +function merge(d: data.Dictionary, toAdd: Object): data.Dictionary { for (const [key, value] of Object.entries(toAdd)) { - if (anyKeys.includes(key)) { - d.add(key, new data.Null()); - } else if (value && typeof value === "object" && !d.get(key)) { - // Only use anyKeys for the top-level object - d.add(key, merge(new data.Dictionary(), value, [])); + if (value && typeof value === "object" && !d.get(key)) { + + if (!Array.isArray(value) && Object.entries(value).length === 0) { + // Allow an empty object to be any value + d.add(key, new data.Null()); + continue; + } + + d.add(key, merge(new data.Dictionary(), value)); } else { d.add(key, new data.Null()); } From 23e2a5c1bc0e1b824d58f1b745357a42f73b8e8e Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 23 Jan 2023 16:42:31 +0000 Subject: [PATCH 37/50] v0.1.90 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index fa9937a..d76e892 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.89", + "version": "0.1.90", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index c5bcdbe..be47fe9 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.89", + "version": "0.1.90", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.89", - "@github/actions-workflow-parser": "^0.1.89", + "@github/actions-languageservice": "^0.1.90", + "@github/actions-workflow-parser": "^0.1.90", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index c25a8a3..2601326 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.89", + "version": "0.1.90", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.89", - "@github/actions-workflow-parser": "^0.1.89", + "@github/actions-expressions": "^0.1.90", + "@github/actions-workflow-parser": "^0.1.90", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 9da76a5..1db63d7 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.89", + "version": "0.1.90", "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.89", + "@github/actions-expressions": "^0.1.90", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 54330dd..fa24e6d 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.89", + "version": "0.1.90", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.89", + "@github/actions-languageserver": "^0.1.90", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index f8d21b2..89c364d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.89" + "version": "0.1.90" } diff --git a/package-lock.json b/package-lock.json index f00955b..6f045fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.89", + "version": "0.1.90", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.89", + "version": "0.1.90", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.89", - "@github/actions-workflow-parser": "^0.1.89", + "@github/actions-languageservice": "^0.1.90", + "@github/actions-workflow-parser": "^0.1.90", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.89", + "version": "0.1.90", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.89", - "@github/actions-workflow-parser": "^0.1.89", + "@github/actions-expressions": "^0.1.90", + "@github/actions-workflow-parser": "^0.1.90", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.89", + "version": "0.1.90", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.89", + "@github/actions-expressions": "^0.1.90", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.89", + "version": "0.1.90", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.89", + "@github/actions-languageserver": "^0.1.90", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.89", - "@github/actions-workflow-parser": "^0.1.89", + "@github/actions-languageservice": "^0.1.90", + "@github/actions-workflow-parser": "^0.1.90", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.89", - "@github/actions-workflow-parser": "^0.1.89", + "@github/actions-expressions": "^0.1.90", + "@github/actions-workflow-parser": "^0.1.90", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.89", + "@github/actions-expressions": "^0.1.90", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.89", + "@github/actions-languageserver": "^0.1.90", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From 0a121960d9fc0726294e49e37d23ab4f8af3f547 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Mon, 23 Jan 2023 10:56:36 -0800 Subject: [PATCH 38/50] Add LICENSE from os template --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index fac6e63..5f9e342 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 GitHub +Copyright GitHub Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file From 4261c466d9e959f357d0e2aed1e85684bd887672 Mon Sep 17 00:00:00 2001 From: Christopher Schleiden Date: Mon, 23 Jan 2023 11:35:22 -0800 Subject: [PATCH 39/50] Add code of conduct --- CODE_OF_CONDUCT.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..8044ebe --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at opensource@github.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file From 48c728771e38751736fea03d50a5bf9ff484a296 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Mon, 23 Jan 2023 16:02:13 -0500 Subject: [PATCH 40/50] Show action input descriptions on hover --- actions-languageserver/src/connection.ts | 5 +- .../src/description-provider.ts | 26 +++++++ .../src/description-providers/action-input.ts | 35 +++++++++ actions-languageservice/src/hover.test.ts | 55 +++++++++++++- actions-languageservice/src/hover.ts | 74 ++++++++++++------- .../src/value-providers/config.ts | 2 +- 6 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 actions-languageserver/src/description-provider.ts create mode 100644 actions-languageserver/src/description-providers/action-input.ts diff --git a/actions-languageserver/src/connection.ts b/actions-languageserver/src/connection.ts index af1bcad..d1650bc 100644 --- a/actions-languageserver/src/connection.ts +++ b/actions-languageserver/src/connection.ts @@ -23,6 +23,7 @@ import {TTLCache} from "./utils/cache"; import {valueProviders} from "./value-providers"; import {getActionInputs} from "./value-providers/action-inputs"; import {Commands} from "./commands"; +import {descriptionProvider} from "./description-provider"; export function initConnection(connection: Connection) { const documents: TextDocuments = new TextDocuments(TextDocument); @@ -120,7 +121,9 @@ export function initConnection(connection: Connection) { }); connection.onHover(async ({position, textDocument}: HoverParams): Promise => { - return hover(documents.get(textDocument.uri)!, position); + return hover(documents.get(textDocument.uri)!, position, { + descriptionProvider: descriptionProvider(sessionToken, cache) + }); }); connection.onRequest("workspace/executeCommand", (params: ExecuteCommandParams) => { diff --git a/actions-languageserver/src/description-provider.ts b/actions-languageserver/src/description-provider.ts new file mode 100644 index 0000000..bd724ed --- /dev/null +++ b/actions-languageserver/src/description-provider.ts @@ -0,0 +1,26 @@ +import {DescriptionProvider} from "@github/actions-languageservice/hover"; +import {Octokit} from "@octokit/rest"; +import {TTLCache} from "./utils/cache"; +import {getActionInputDescription} from "./description-providers/action-input"; + +export function descriptionProvider(sessionToken: string | undefined, cache: TTLCache): DescriptionProvider { + const octokit = + sessionToken && + new Octokit({ + auth: sessionToken + }); + + const getDescription: DescriptionProvider["getDescription"] = async (context, token, path) => { + if (!octokit) { + return undefined; + } + const parent = path[path.length - 1]; + if (context.step && parent.definition?.key === "step-with") { + return await getActionInputDescription(octokit, cache, context.step, token); + } + }; + + return { + getDescription + }; +} diff --git a/actions-languageserver/src/description-providers/action-input.ts b/actions-languageserver/src/description-providers/action-input.ts new file mode 100644 index 0000000..1f26abf --- /dev/null +++ b/actions-languageserver/src/description-providers/action-input.ts @@ -0,0 +1,35 @@ +import {parseActionReference} from "@github/actions-languageservice/action"; +import {isString} from "@github/actions-workflow-parser"; +import {isActionStep} from "@github/actions-workflow-parser/model/type-guards"; +import {Step} from "@github/actions-workflow-parser/model/workflow-template"; +import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token"; +import {Octokit} from "@octokit/rest"; +import {fetchActionMetadata} from "../utils/action-metadata"; +import {TTLCache} from "../utils/cache"; + +export async function getActionInputDescription( + client: Octokit, + cache: TTLCache, + step: Step, + token: TemplateToken +): Promise { + if (!isActionStep(step)) { + return undefined; + } + const action = parseActionReference(step.uses.value); + if (!action) { + return undefined; + } + + const inputName = isString(token) && token.value; + if (!inputName) { + return undefined; + } + + const metadata = await fetchActionMetadata(client, cache, action); + if (!metadata?.inputs) { + return undefined; + } + + return metadata.inputs[inputName]?.description; +} diff --git a/actions-languageservice/src/hover.test.ts b/actions-languageservice/src/hover.test.ts index 1fce7e9..8581a27 100644 --- a/actions-languageservice/src/hover.test.ts +++ b/actions-languageservice/src/hover.test.ts @@ -1,6 +1,25 @@ -import {hover} from "./hover"; +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"; +function testHoverConfig(tokenValue: string, tokenKey: string, description?: string) { + return { + descriptionProvider: { + getDescription: async (_, token, __) => { + if (!isString(token)) { + throw new Error("Test provider only supports string tokens"); + } + + expect((token as StringToken).value).toEqual(tokenValue); + expect(token.definition!.key).toEqual(tokenKey); + + return description; + } + } satisfies DescriptionProvider + } satisfies HoverConfig +} + describe("hover", () => { it("on a key", async () => { const input = `o|n: push @@ -77,3 +96,37 @@ jobs: expect(result?.contents).toEqual("Runs your workflow when you push a commit or tag."); }); }); + +describe("hover with description provider", () => { + it("uses the description provider", async () => { + const input = ` +on: push +jobs: + build: + runs-on: [self-hosted] + steps: + - uses: actions/checkout@v2 + with: + ref|: main +`; + + const result = await hover(...getPositionFromCursor(input), testHoverConfig("ref", "string", "The branch, tag or SHA to checkout.")); + expect(result).not.toBeUndefined(); + expect(result?.contents).toEqual("The branch, tag or SHA to checkout."); + }); + + it("falls back to the token description", async () => { + const input = ` +on: push +jobs: + build: + runs-on: [self-hosted] + steps: + - uses|: actions/checkout@v2 +`; + + const result = await hover(...getPositionFromCursor(input), testHoverConfig("uses", "non-empty-string", undefined)); + expect(result).not.toBeUndefined(); + expect(result?.contents).toEqual("Selects an action to run as part of a step in your job. An action is a reusable unit of code. You can use an action defined in the same repository as the workflow, a public repository, or in a published Docker container image."); + }); +}); diff --git a/actions-languageservice/src/hover.ts b/actions-languageservice/src/hover.ts index 7d39495..4d5ebdd 100644 --- a/actions-languageservice/src/hover.ts +++ b/actions-languageservice/src/hover.ts @@ -1,49 +1,67 @@ -import {parseWorkflow} from "@github/actions-workflow-parser"; +import {convertWorkflowTemplate, parseWorkflow, ParseWorkflowResult} from "@github/actions-workflow-parser"; +import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert"; import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token"; import {File} from "@github/actions-workflow-parser/workflows/file"; import {Position, TextDocument} from "vscode-languageserver-textdocument"; import {Hover} from "vscode-languageserver-types"; +import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; import {info} from "./log"; import {nullTrace} from "./nulltrace"; import {findToken} from "./utils/find-token"; import {mapRange} from "./utils/range"; +export type DescriptionProvider = { + getDescription(context: WorkflowContext, token: TemplateToken, path: TemplateToken[]): Promise; +}; + +export type HoverConfig = { + descriptionProvider?: DescriptionProvider; +}; + // Render value description and Context when hovering over a key in a MappingToken -export async function hover(document: TextDocument, position: Position): Promise { +export async function hover(document: TextDocument, position: Position, config?: HoverConfig): Promise { const file: File = { name: document.uri, content: document.getText() }; const result = parseWorkflow(file.name, [file], nullTrace); - const {token} = findToken(position, result.value); - - if (result.value && token) { - return getHover(token); + const {token, path} = findToken(position, result.value); + if (!token?.definition) { + return null; } - return null; + + info(`Calculating hover for token with definition ${token.definition.key}`); + + let description = await getDescription(document, config, result, token, path); + + if (token.definition.evaluatorContext.length > 0) { + // Only add padding if there is a description + description += `${description.length > 0 ? `\n\n` : ""}**Context:** ${token.definition.evaluatorContext.join( + ", " + )}`; + } + + return { + contents: description, + range: mapRange(token.range) + } satisfies Hover; } -function getHover(token: TemplateToken): Hover | null { - if (token.definition) { - info(`Calculating hover for token with definition ${token.definition.key}`); - - let description = ""; - if (token.description) { - description = token.description; - } - - if (token.definition.evaluatorContext.length > 0) { - // Only add padding if there is a description - description += `${description.length > 0 ? `\n\n` : ""}**Context:** ${token.definition.evaluatorContext.join( - ", " - )}`; - } - - return { - contents: description, - range: mapRange(token.range) - } as Hover; +async function getDescription( + document: TextDocument, + config: HoverConfig | undefined, + result: ParseWorkflowResult | undefined, + token: TemplateToken, + path: TemplateToken[] +) { + const defaultDescription = token.description || ""; + if (!result?.value || !config?.descriptionProvider) { + return defaultDescription; } - return null; + + const template = convertWorkflowTemplate(result.context, result.value, ErrorPolicy.TryConversion); + const workflowContext = getWorkflowContext(document.uri, template, path); + const description = await config.descriptionProvider.getDescription(workflowContext, token, path); + return description || defaultDescription; } diff --git a/actions-languageservice/src/value-providers/config.ts b/actions-languageservice/src/value-providers/config.ts index 916a569..40b88df 100644 --- a/actions-languageservice/src/value-providers/config.ts +++ b/actions-languageservice/src/value-providers/config.ts @@ -4,7 +4,7 @@ export interface Value { /** Label of this value */ label: string; - /** Optional description to show when auto-completing or hovering */ + /** Optional description to show when auto-completing */ description?: string; /** Whether this value is deprecated */ From 37157938ead710a30039e40b3684903210a7d036 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 23 Jan 2023 21:14:10 +0000 Subject: [PATCH 41/50] v0.1.91 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index d76e892..52f6bd9 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.90", + "version": "0.1.91", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index be47fe9..2f373be 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.90", + "version": "0.1.91", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.90", - "@github/actions-workflow-parser": "^0.1.90", + "@github/actions-languageservice": "^0.1.91", + "@github/actions-workflow-parser": "^0.1.91", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 2601326..3278d3b 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.90", + "version": "0.1.91", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.90", - "@github/actions-workflow-parser": "^0.1.90", + "@github/actions-expressions": "^0.1.91", + "@github/actions-workflow-parser": "^0.1.91", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 1db63d7..9302656 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.90", + "version": "0.1.91", "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.90", + "@github/actions-expressions": "^0.1.91", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index fa24e6d..d2d32bb 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.90", + "version": "0.1.91", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.90", + "@github/actions-languageserver": "^0.1.91", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 89c364d..39120ec 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.90" + "version": "0.1.91" } diff --git a/package-lock.json b/package-lock.json index 6f045fa..3009b6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.90", + "version": "0.1.91", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.90", + "version": "0.1.91", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.90", - "@github/actions-workflow-parser": "^0.1.90", + "@github/actions-languageservice": "^0.1.91", + "@github/actions-workflow-parser": "^0.1.91", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.90", + "version": "0.1.91", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.90", - "@github/actions-workflow-parser": "^0.1.90", + "@github/actions-expressions": "^0.1.91", + "@github/actions-workflow-parser": "^0.1.91", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.90", + "version": "0.1.91", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.90", + "@github/actions-expressions": "^0.1.91", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.90", + "version": "0.1.91", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.90", + "@github/actions-languageserver": "^0.1.91", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.90", - "@github/actions-workflow-parser": "^0.1.90", + "@github/actions-languageservice": "^0.1.91", + "@github/actions-workflow-parser": "^0.1.91", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.90", - "@github/actions-workflow-parser": "^0.1.90", + "@github/actions-expressions": "^0.1.91", + "@github/actions-workflow-parser": "^0.1.91", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.90", + "@github/actions-expressions": "^0.1.91", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.90", + "@github/actions-languageserver": "^0.1.91", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From d8d4a3f46a2ee7d2e64e45123f2aa805ff9f33c0 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Mon, 23 Jan 2023 16:20:59 -0500 Subject: [PATCH 42/50] Ensure inherited context is shown on hover --- actions-languageservice/src/hover.test.ts | 26 ++++++++++++++++++++++- actions-languageservice/src/hover.ts | 7 +++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/actions-languageservice/src/hover.test.ts b/actions-languageservice/src/hover.test.ts index 8581a27..a1c172c 100644 --- a/actions-languageservice/src/hover.test.ts +++ b/actions-languageservice/src/hover.test.ts @@ -95,6 +95,27 @@ jobs: expect(result).not.toBeUndefined(); expect(result?.contents).toEqual("Runs your workflow when you push a commit or tag."); }); + + + it("shows context inherited from parent nodes", async () => { + const input = ` +on: push +jobs: + build: + runs-on: [self-hosted] + steps: + - uses: actions/checkout@v2 + with: + ref|: main +`; + + const result = await hover(...getPositionFromCursor(input)); + expect(result).not.toBeUndefined(); + + // The `ref` is a `string` definition and inherits the context from `step-with` + const expected = "**Context:** github, inputs, vars, needs, strategy, matrix, secrets, steps, job, runner, env, hashFiles(1,255)" + expect(result?.contents).toEqual(expected); + }); }); describe("hover with description provider", () => { @@ -112,7 +133,10 @@ jobs: const result = await hover(...getPositionFromCursor(input), testHoverConfig("ref", "string", "The branch, tag or SHA to checkout.")); expect(result).not.toBeUndefined(); - expect(result?.contents).toEqual("The branch, tag or SHA to checkout."); + + const expected = "The branch, tag or SHA to checkout.\n\n" + + "**Context:** github, inputs, vars, needs, strategy, matrix, secrets, steps, job, runner, env, hashFiles(1,255)" + expect(result?.contents).toEqual(expected); }); it("falls back to the token description", async () => { diff --git a/actions-languageservice/src/hover.ts b/actions-languageservice/src/hover.ts index 4d5ebdd..e7bac56 100644 --- a/actions-languageservice/src/hover.ts +++ b/actions-languageservice/src/hover.ts @@ -35,11 +35,10 @@ export async function hover(document: TextDocument, position: Position, config?: let description = await getDescription(document, config, result, token, path); - if (token.definition.evaluatorContext.length > 0) { + const allowedContext = token.definitionInfo?.allowedContext; + if (allowedContext && allowedContext?.length > 0) { // Only add padding if there is a description - description += `${description.length > 0 ? `\n\n` : ""}**Context:** ${token.definition.evaluatorContext.join( - ", " - )}`; + description += `${description.length > 0 ? `\n\n` : ""}**Context:** ${allowedContext.join(", ")}`; } return { From 4a9fe401aff099130855409aca441c3f4876d4cf Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Mon, 23 Jan 2023 19:39:28 -0500 Subject: [PATCH 43/50] Include deprecated and required input status --- .../src/description-providers/action-input.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/actions-languageserver/src/description-providers/action-input.ts b/actions-languageserver/src/description-providers/action-input.ts index 1f26abf..a6b1385 100644 --- a/actions-languageserver/src/description-providers/action-input.ts +++ b/actions-languageserver/src/description-providers/action-input.ts @@ -31,5 +31,23 @@ export async function getActionInputDescription( return undefined; } - return metadata.inputs[inputName]?.description; + const input = metadata.inputs[inputName]; + if (!input) { + return undefined; + } + + let description = input.description; + + const deprecated = input.deprecationMessage !== undefined; + + if (deprecated) { + // Validation will include the deprecation message, so don't duplicate it here + description += `\n\n**Deprecated**`; + } + + if (input.required) { + description += "\n\n**Required**"; + } + + return description; } From 1f3f130a4d11e55423435fc8840b0c80e973e602 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 24 Jan 2023 00:44:38 +0000 Subject: [PATCH 44/50] v0.1.92 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 52f6bd9..57376e9 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.91", + "version": "0.1.92", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 2f373be..d594df9 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.91", + "version": "0.1.92", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.91", - "@github/actions-workflow-parser": "^0.1.91", + "@github/actions-languageservice": "^0.1.92", + "@github/actions-workflow-parser": "^0.1.92", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 3278d3b..fa3e3c6 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.91", + "version": "0.1.92", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.91", - "@github/actions-workflow-parser": "^0.1.91", + "@github/actions-expressions": "^0.1.92", + "@github/actions-workflow-parser": "^0.1.92", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 9302656..4a525b8 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.91", + "version": "0.1.92", "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.91", + "@github/actions-expressions": "^0.1.92", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index d2d32bb..d5656ad 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.91", + "version": "0.1.92", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.91", + "@github/actions-languageserver": "^0.1.92", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 39120ec..99258c8 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.91" + "version": "0.1.92" } diff --git a/package-lock.json b/package-lock.json index 3009b6f..0cb2e1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.91", + "version": "0.1.92", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.91", + "version": "0.1.92", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.91", - "@github/actions-workflow-parser": "^0.1.91", + "@github/actions-languageservice": "^0.1.92", + "@github/actions-workflow-parser": "^0.1.92", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.91", + "version": "0.1.92", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.91", - "@github/actions-workflow-parser": "^0.1.91", + "@github/actions-expressions": "^0.1.92", + "@github/actions-workflow-parser": "^0.1.92", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.91", + "version": "0.1.92", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.91", + "@github/actions-expressions": "^0.1.92", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.91", + "version": "0.1.92", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.91", + "@github/actions-languageserver": "^0.1.92", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.91", - "@github/actions-workflow-parser": "^0.1.91", + "@github/actions-languageservice": "^0.1.92", + "@github/actions-workflow-parser": "^0.1.92", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.91", - "@github/actions-workflow-parser": "^0.1.91", + "@github/actions-expressions": "^0.1.92", + "@github/actions-workflow-parser": "^0.1.92", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.91", + "@github/actions-expressions": "^0.1.92", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.91", + "@github/actions-languageserver": "^0.1.92", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From 4f9c9e6e1c8596e382a92a2d1e48c7d56e6de1d4 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Tue, 24 Jan 2023 13:04:40 -0500 Subject: [PATCH 45/50] Support a 0 step index in test context --- actions-languageserver/src/test-utils/workflow-context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions-languageserver/src/test-utils/workflow-context.ts b/actions-languageserver/src/test-utils/workflow-context.ts index 63841a6..aef5cfe 100644 --- a/actions-languageserver/src/test-utils/workflow-context.ts +++ b/actions-languageserver/src/test-utils/workflow-context.ts @@ -19,7 +19,7 @@ export function createWorkflowContext(workflow: string, job?: string, stepIndex? context.job = template.jobs.find(j => j.id.value === job); } - if (stepIndex) { + if (stepIndex !== undefined) { context.step = context.job?.steps[stepIndex]; } From e11c62667e10e22ba8d1d7581f8b29b496a9fd98 Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Tue, 24 Jan 2023 13:09:36 -0500 Subject: [PATCH 46/50] Replace `nock` with `fetch-mock` --- actions-languageserver/package.json | 2 +- .../src/context-providers/steps.test.ts | 26 +- package-lock.json | 265 +++++++++++++++--- 3 files changed, 237 insertions(+), 56 deletions(-) diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index d594df9..0237323 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -53,8 +53,8 @@ ], "devDependencies": { "@types/jest": "^29.0.3", + "fetch-mock": "^9.11.0", "jest": "^29.0.3", - "nock": "^13.2.9", "prettier": "^2.7.1", "rimraf": "^3.0.2", "ts-jest": "^29.0.3", diff --git a/actions-languageserver/src/context-providers/steps.test.ts b/actions-languageserver/src/context-providers/steps.test.ts index c7d3922..0120216 100644 --- a/actions-languageserver/src/context-providers/steps.test.ts +++ b/actions-languageserver/src/context-providers/steps.test.ts @@ -1,7 +1,8 @@ import {data, DescriptionDictionary} from "@github/actions-expressions"; import {getStepsContext as getDefaultStepsContext} from "@github/actions-languageservice/context-providers/steps"; import {Octokit} from "@octokit/rest"; -import nock from "nock"; +import fetchMock from "fetch-mock"; + import {createWorkflowContext} from "../test-utils/workflow-context"; import {TTLCache} from "../utils/cache"; import {getStepsContext} from "./steps"; @@ -54,14 +55,6 @@ const actionMetadata = { } }; -beforeEach(() => { - nock.disableNetConnect(); -}); - -afterEach(() => { - nock.cleanAll(); -}); - it("returns default context when job is undefined", async () => { const workflowContext = createWorkflowContext(workflow, undefined); const defaultContext = getDefaultStepsContext(workflowContext); @@ -71,12 +64,23 @@ it("returns default context when job is undefined", async () => { }); it("adds action outputs", async () => { - nock("https://api.github.com").get("/repos/actions/cache/contents/action.yml?ref=v3").reply(200, actionMetadata); + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/cache/contents/action.yml?ref=v3", actionMetadata); const workflowContext = createWorkflowContext(workflow, "build"); const defaultContext = getDefaultStepsContext(workflowContext); - const stepsContext = await getStepsContext(new Octokit(), new TTLCache(), defaultContext, workflowContext); + const stepsContext = await getStepsContext( + new Octokit({ + request: { + fetch: mock + } + }), + new TTLCache(), + defaultContext, + workflowContext + ); expect(stepsContext).toBeDefined(); expect(stepsContext).toEqual( diff --git a/package-lock.json b/package-lock.json index 0cb2e1a..1091665 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,8 +46,8 @@ }, "devDependencies": { "@types/jest": "^29.0.3", + "fetch-mock": "^9.11.0", "jest": "^29.0.3", - "nock": "^13.2.9", "prettier": "^2.7.1", "rimraf": "^3.0.2", "ts-jest": "^29.0.3", @@ -655,6 +655,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", @@ -5242,6 +5254,17 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "node_modules/core-js": { + "version": "3.27.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.27.2.tgz", + "integrity": "sha512-9ashVQskuh5AZEZ1JdQWp1GqSoC1e1G87MzRqg2gIfVAQ7Qn9K+uFj8EcniUFA4P2NLZfV+TOlX1SzoKfo+s7w==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -6339,6 +6362,71 @@ "bser": "2.1.1" } }, + "node_modules/fetch-mock": { + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.11.0.tgz", + "integrity": "sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.0.0", + "@babel/runtime": "^7.0.0", + "core-js": "^3.0.0", + "debug": "^4.1.1", + "glob-to-regexp": "^0.4.0", + "is-subset": "^0.1.1", + "lodash.isequal": "^4.5.0", + "path-to-regexp": "^2.2.1", + "querystring": "^0.2.0", + "whatwg-url": "^6.5.0" + }, + "engines": { + "node": ">=4.0.0" + }, + "funding": { + "type": "charity", + "url": "https://www.justgiving.com/refugee-support-europe" + }, + "peerDependencies": { + "node-fetch": "*" + }, + "peerDependenciesMeta": { + "node-fetch": { + "optional": true + } + } + }, + "node_modules/fetch-mock/node_modules/path-to-regexp": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", + "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==", + "dev": true + }, + "node_modules/fetch-mock/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/fetch-mock/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/fetch-mock/node_modules/whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -7696,6 +7784,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "dev": true + }, "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -8844,6 +8938,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, "node_modules/lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -8862,6 +8962,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -9514,21 +9620,6 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, - "node_modules/nock": { - "version": "13.2.9", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", - "integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", - "propagate": "^2.0.0" - }, - "engines": { - "node": ">= 10.13" - } - }, "node_modules/node-addon-api": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", @@ -11021,15 +11112,6 @@ "read": "1" } }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -11103,6 +11185,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11571,6 +11663,12 @@ "node": ">=8" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -14316,6 +14414,15 @@ "@babel/helper-plugin-utils": "^7.19.0" } }, + "@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, "@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", @@ -14432,8 +14539,8 @@ "@github/actions-workflow-parser": "^0.1.92", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", + "fetch-mock": "^9.11.0", "jest": "^29.0.3", - "nock": "^13.2.9", "prettier": "^2.7.1", "rimraf": "^3.0.2", "ts-jest": "^29.0.3", @@ -18025,6 +18132,12 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "core-js": { + "version": "3.27.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.27.2.tgz", + "integrity": "sha512-9ashVQskuh5AZEZ1JdQWp1GqSoC1e1G87MzRqg2gIfVAQ7Qn9K+uFj8EcniUFA4P2NLZfV+TOlX1SzoKfo+s7w==", + "dev": true + }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -18855,6 +18968,58 @@ "bser": "2.1.1" } }, + "fetch-mock": { + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.11.0.tgz", + "integrity": "sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==", + "dev": true, + "requires": { + "@babel/core": "^7.0.0", + "@babel/runtime": "^7.0.0", + "core-js": "^3.0.0", + "debug": "^4.1.1", + "glob-to-regexp": "^0.4.0", + "is-subset": "^0.1.1", + "lodash.isequal": "^4.5.0", + "path-to-regexp": "^2.2.1", + "querystring": "^0.2.0", + "whatwg-url": "^6.5.0" + }, + "dependencies": { + "path-to-regexp": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", + "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==", + "dev": true + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -19903,6 +20068,12 @@ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "dev": true + }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -20791,6 +20962,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -20809,6 +20986,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -21302,18 +21485,6 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, - "nock": { - "version": "13.2.9", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", - "integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", - "propagate": "^2.0.0" - } - }, "node-addon-api": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", @@ -22411,12 +22582,6 @@ "read": "1" } }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true - }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -22473,6 +22638,12 @@ "side-channel": "^1.0.4" } }, + "querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "dev": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -22831,6 +23002,12 @@ "strip-indent": "^3.0.0" } }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", From 416e32e29b1279944bef9d98b29f6f9597ab9efb Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Tue, 24 Jan 2023 13:09:49 -0500 Subject: [PATCH 47/50] Add tests for action input descriptions --- .../action-input.test.ts | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 actions-languageserver/src/description-providers/action-input.test.ts diff --git a/actions-languageserver/src/description-providers/action-input.test.ts b/actions-languageserver/src/description-providers/action-input.test.ts new file mode 100644 index 0000000..b6938e6 --- /dev/null +++ b/actions-languageserver/src/description-providers/action-input.test.ts @@ -0,0 +1,113 @@ +import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token"; +import {Octokit} from "@octokit/rest"; +import fetchMock from "fetch-mock"; + +import {createWorkflowContext} from "../test-utils/workflow-context"; +import {TTLCache} from "../utils/cache"; +import {getActionInputDescription} from "./action-input"; + +const workflow = ` +name: Hello World +on: workflow_dispatch +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 +`; + +// A simplified version of the action.yml file from actions/checkout +const actionMetadataContent = ` +name: 'Checkout' +description: 'Checkout a Git repository at a particular version' +inputs: + repository: + description: Repository name with owner. For example, actions/checkout + default: \${{ github.repository }} + ref: + description: The branch, tag or SHA to checkout. + required: true + token: + description: Personal access token (PAT) used to fetch the repository. + default: \${{ github.token }} + repo: + description: 'Repository name with owner. For example, actions/checkout' + deprecationMessage: 'Use repository instead' +runs: + using: node16 + main: dist/index.js + post: dist/index.js +`; + +// Based on https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3 +const actionMetadata = { + name: "action.yml", + path: "action.yml", + sha: "cab09ebd3a964aba67b57f9727f5f6fff1372b04", + size: 3649, + url: "https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", + html_url: "https://github.com/actions/checkout/blob/v3/action.yml", + git_url: "https://api.github.com/repos/actions/checkout/git/blobs/cab09ebd3a964aba67b57f9727f5f6fff1372b04", + download_url: "https://raw.githubusercontent.com/actions/checkout/v3/action.yml", + type: "file", + content: Buffer.from(actionMetadataContent).toString("base64"), + encoding: "base64", + _links: { + self: "https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", + git: "https://api.github.com/repos/actions/checkout/git/blobs/cab09ebd3a964aba67b57f9727f5f6fff1372b04", + html: "https://github.com/actions/checkout/blob/v3/action.yml" + } +}; + +async function getDescription(input: string, mock: fetchMock.FetchMockSandbox) { + const workflowContext = createWorkflowContext(workflow, "build", 0); + + return await getActionInputDescription( + new Octokit({ + request: { + fetch: mock + } + }), + new TTLCache(), + workflowContext.step!, + new StringToken(undefined, undefined, input, undefined) + ); +} + +describe("action descriptions", () => { + it("optional input", async () => { + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", actionMetadata); + + expect(await getDescription("repository", mock)).toEqual( + "Repository name with owner. For example, actions/checkout" + ); + }); + + it("required input", async () => { + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", actionMetadata); + + expect(await getDescription("ref", mock)).toEqual("The branch, tag or SHA to checkout.\n\n**Required**"); + }); + + it("deprecated input", async () => { + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", actionMetadata); + + expect(await getDescription("repo", mock)).toEqual( + "Repository name with owner. For example, actions/checkout\n\n**Deprecated**" + ); + }); + + it("invalid input", async () => { + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", actionMetadata); + + expect(await getDescription("typo", mock)).toBeUndefined(); + }); +}); From 54261296bb66a64f80c42f4e986c9ddd4ea8ecee Mon Sep 17 00:00:00 2001 From: Josh Gross Date: Tue, 24 Jan 2023 13:29:23 -0500 Subject: [PATCH 48/50] Add tests for errors when fetching actions --- .../action-input.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/actions-languageserver/src/description-providers/action-input.test.ts b/actions-languageserver/src/description-providers/action-input.test.ts index b6938e6..adac8b8 100644 --- a/actions-languageserver/src/description-providers/action-input.test.ts +++ b/actions-languageserver/src/description-providers/action-input.test.ts @@ -110,4 +110,23 @@ describe("action descriptions", () => { expect(await getDescription("typo", mock)).toBeUndefined(); }); + + // TODO: https://github.com/github/c2c-actions-experience/issues/7056 + it.failing("action does not exist", async () => { + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", 404) + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yaml?ref=v3", 404); + + expect(await getDescription("repository", mock)).toBeUndefined(); + }); + + // TODO: https://github.com/github/c2c-actions-experience/issues/7056 + it.failing("invalid permissions", async () => { + const mock = fetchMock + .sandbox() + .getOnce("https://api.github.com/repos/actions/checkout/contents/action.yml?ref=v3", 403); + + expect(await getDescription("repository", mock)).toBeUndefined(); + }); }); From a9a311cf3e7ab71ee7d819ab78db2de086324a8b Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 24 Jan 2023 18:30:37 +0000 Subject: [PATCH 49/50] v0.1.93 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 57376e9..352ab61 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.92", + "version": "0.1.93", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index d594df9..8c370d8 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.92", + "version": "0.1.93", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.92", - "@github/actions-workflow-parser": "^0.1.92", + "@github/actions-languageservice": "^0.1.93", + "@github/actions-workflow-parser": "^0.1.93", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index fa3e3c6..009b60a 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.92", + "version": "0.1.93", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.92", - "@github/actions-workflow-parser": "^0.1.92", + "@github/actions-expressions": "^0.1.93", + "@github/actions-workflow-parser": "^0.1.93", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index 4a525b8..aaaf32e 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.92", + "version": "0.1.93", "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.92", + "@github/actions-expressions": "^0.1.93", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index d5656ad..385a105 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.92", + "version": "0.1.93", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.92", + "@github/actions-languageserver": "^0.1.93", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index 99258c8..d44f217 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.92" + "version": "0.1.93" } diff --git a/package-lock.json b/package-lock.json index 0cb2e1a..bda63c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.92", + "version": "0.1.93", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.92", + "version": "0.1.93", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.92", - "@github/actions-workflow-parser": "^0.1.92", + "@github/actions-languageservice": "^0.1.93", + "@github/actions-workflow-parser": "^0.1.93", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.92", + "version": "0.1.93", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.92", - "@github/actions-workflow-parser": "^0.1.92", + "@github/actions-expressions": "^0.1.93", + "@github/actions-workflow-parser": "^0.1.93", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.92", + "version": "0.1.93", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.92", + "@github/actions-expressions": "^0.1.93", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.92", + "version": "0.1.93", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.92", + "@github/actions-languageserver": "^0.1.93", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14428,8 +14428,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.92", - "@github/actions-workflow-parser": "^0.1.92", + "@github/actions-languageservice": "^0.1.93", + "@github/actions-workflow-parser": "^0.1.93", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "jest": "^29.0.3", @@ -14446,8 +14446,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.92", - "@github/actions-workflow-parser": "^0.1.92", + "@github/actions-expressions": "^0.1.93", + "@github/actions-workflow-parser": "^0.1.93", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14462,7 +14462,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.92", + "@github/actions-expressions": "^0.1.93", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17389,7 +17389,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.92", + "@github/actions-languageserver": "^0.1.93", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", From f459224685a8355e6a9762f4ed9c336bd8bbaf0c Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 24 Jan 2023 18:39:03 +0000 Subject: [PATCH 50/50] v0.1.94 --- actions-expressions/package.json | 2 +- actions-languageserver/package.json | 6 ++--- actions-languageservice/package.json | 6 ++--- actions-workflow-parser/package.json | 4 ++-- browser-playground/package.json | 4 ++-- lerna.json | 2 +- package-lock.json | 34 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/actions-expressions/package.json b/actions-expressions/package.json index 352ab61..6aa1ae3 100755 --- a/actions-expressions/package.json +++ b/actions-expressions/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-expressions", - "version": "0.1.93", + "version": "0.1.94", "license": "MIT", "type": "module", "source": "./src/index.ts", diff --git a/actions-languageserver/package.json b/actions-languageserver/package.json index 0e0bb63..78cf707 100644 --- a/actions-languageserver/package.json +++ b/actions-languageserver/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageserver", - "version": "0.1.93", + "version": "0.1.94", "description": "Language server for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-languageservice": "^0.1.93", - "@github/actions-workflow-parser": "^0.1.93", + "@github/actions-languageservice": "^0.1.94", + "@github/actions-workflow-parser": "^0.1.94", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index 009b60a..5ff7b3c 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-languageservice", - "version": "0.1.93", + "version": "0.1.94", "description": "Language service for GitHub Actions", "license": "MIT", "type": "module", @@ -38,8 +38,8 @@ "watch": "tsc --build tsconfig.build.json --watch" }, "dependencies": { - "@github/actions-expressions": "^0.1.93", - "@github/actions-workflow-parser": "^0.1.93", + "@github/actions-expressions": "^0.1.94", + "@github/actions-workflow-parser": "^0.1.94", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" diff --git a/actions-workflow-parser/package.json b/actions-workflow-parser/package.json index aaaf32e..da1b440 100644 --- a/actions-workflow-parser/package.json +++ b/actions-workflow-parser/package.json @@ -1,6 +1,6 @@ { "name": "@github/actions-workflow-parser", - "version": "0.1.93", + "version": "0.1.94", "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.93", + "@github/actions-expressions": "^0.1.94", "yaml": "^2.0.0-8" }, "engines": { diff --git a/browser-playground/package.json b/browser-playground/package.json index 385a105..075746a 100644 --- a/browser-playground/package.json +++ b/browser-playground/package.json @@ -1,12 +1,12 @@ { "name": "browser-playground", - "version": "0.1.93", + "version": "0.1.94", "description": "", "private": true, "main": "index.js", "type": "module", "dependencies": { - "@github/actions-languageserver": "^0.1.93", + "@github/actions-languageserver": "^0.1.94", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", diff --git a/lerna.json b/lerna.json index d44f217..0fec19f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "0.1.93" + "version": "0.1.94" } diff --git a/package-lock.json b/package-lock.json index aacc7c3..330b6f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "actions-expressions": { "name": "@github/actions-expressions", - "version": "0.1.93", + "version": "0.1.94", "license": "MIT", "devDependencies": { "@types/jest": "^29.0.3", @@ -34,11 +34,11 @@ }, "actions-languageserver": { "name": "@github/actions-languageserver", - "version": "0.1.93", + "version": "0.1.94", "license": "MIT", "dependencies": { - "@github/actions-languageservice": "^0.1.93", - "@github/actions-workflow-parser": "^0.1.93", + "@github/actions-languageservice": "^0.1.94", + "@github/actions-workflow-parser": "^0.1.94", "@octokit/rest": "^19.0.5", "vscode-languageserver": "^8.0.2", "vscode-languageserver-textdocument": "^1.0.7", @@ -59,11 +59,11 @@ }, "actions-languageservice": { "name": "@github/actions-languageservice", - "version": "0.1.93", + "version": "0.1.94", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.93", - "@github/actions-workflow-parser": "^0.1.93", + "@github/actions-expressions": "^0.1.94", + "@github/actions-workflow-parser": "^0.1.94", "vscode-languageserver-textdocument": "^1.0.7", "vscode-languageserver-types": "^3.17.2", "yaml": "^2.1.1" @@ -82,10 +82,10 @@ }, "actions-workflow-parser": { "name": "@github/actions-workflow-parser", - "version": "0.1.93", + "version": "0.1.94", "license": "MIT", "dependencies": { - "@github/actions-expressions": "^0.1.93", + "@github/actions-expressions": "^0.1.94", "yaml": "^2.0.0-8" }, "devDependencies": { @@ -104,10 +104,10 @@ } }, "browser-playground": { - "version": "0.1.93", + "version": "0.1.94", "license": "MIT", "dependencies": { - "@github/actions-languageserver": "^0.1.93", + "@github/actions-languageserver": "^0.1.94", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2", "monaco-languageclient": "^4.0.3", @@ -14535,8 +14535,8 @@ "@github/actions-languageserver": { "version": "file:actions-languageserver", "requires": { - "@github/actions-languageservice": "^0.1.93", - "@github/actions-workflow-parser": "^0.1.93", + "@github/actions-languageservice": "^0.1.94", + "@github/actions-workflow-parser": "^0.1.94", "@octokit/rest": "^19.0.5", "@types/jest": "^29.0.3", "fetch-mock": "^9.11.0", @@ -14553,8 +14553,8 @@ "@github/actions-languageservice": { "version": "file:actions-languageservice", "requires": { - "@github/actions-expressions": "^0.1.93", - "@github/actions-workflow-parser": "^0.1.93", + "@github/actions-expressions": "^0.1.94", + "@github/actions-workflow-parser": "^0.1.94", "@types/jest": "^29.0.3", "jest": "^29.0.3", "prettier": "^2.7.1", @@ -14569,7 +14569,7 @@ "@github/actions-workflow-parser": { "version": "file:actions-workflow-parser", "requires": { - "@github/actions-expressions": "^0.1.93", + "@github/actions-expressions": "^0.1.94", "@types/jest": "^29.0.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", @@ -17496,7 +17496,7 @@ "browser-playground": { "version": "file:browser-playground", "requires": { - "@github/actions-languageserver": "^0.1.93", + "@github/actions-languageserver": "^0.1.94", "css-loader": "^6.7.2", "monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-workers": "^0.34.2",