diff --git a/actions-languageserver/src/context-providers.ts b/actions-languageserver/src/context-providers.ts index d36eb0c..20301c7 100644 --- a/actions-languageserver/src/context-providers.ts +++ b/actions-languageserver/src/context-providers.ts @@ -18,13 +18,14 @@ export function contextProviders( auth: sessionToken }); - const getContext = async (name: string) => { + const getContext = async (name: string, defaultContext: data.Dictionary | undefined) => { switch (name) { case "secrets": const secrets = await getSecrets(octokit, cache, repo.owner, repo.name); - const secretContext = new data.Dictionary(); - secrets.forEach(secret => secretContext.add(secret.value, secret)); - return secretContext; + + defaultContext = defaultContext || new data.Dictionary(); + secrets.forEach(secret => defaultContext!.add(secret.value, new data.StringData("***"))); + return defaultContext; } }; diff --git a/actions-languageserver/src/context-providers/secrets.ts b/actions-languageserver/src/context-providers/secrets.ts index a1755dd..afdb2e7 100644 --- a/actions-languageserver/src/context-providers/secrets.ts +++ b/actions-languageserver/src/context-providers/secrets.ts @@ -2,8 +2,15 @@ import {StringData} from "@github/actions-expressions/data/string"; import {Octokit} from "@octokit/rest"; import {TTLCache} from "../utils/cache"; -export function getSecrets(octokit: Octokit, cache: TTLCache, owner: string, name: string): Promise { - return cache.get(`${owner}/${name}/secrets`, undefined, () => fetchSecrets(octokit, owner, name)); +export async function getSecrets( + octokit: Octokit, + cache: TTLCache, + owner: string, + name: string +): Promise { + const repoSecrets = await cache.get(`${owner}/${name}/secrets`, undefined, () => fetchSecrets(octokit, owner, name)); + + return repoSecrets; } async function fetchSecrets(octokit: Octokit, owner: string, name: string): Promise { diff --git a/actions-languageservice/src/complete.expressions.test.ts b/actions-languageservice/src/complete.expressions.test.ts index 9087375..e8a4715 100644 --- a/actions-languageservice/src/complete.expressions.test.ts +++ b/actions-languageservice/src/complete.expressions.test.ts @@ -1,7 +1,9 @@ import {data} from "@github/actions-expressions"; import {complete, getExpressionInput} from "./complete"; import {ContextProviderConfig} from "./context-providers/config"; +import {registerLogger} from "./log"; import {getPositionFromCursor} from "./test-utils/cursor-position"; +import {TestLogger} from "./test-utils/logger"; const contextProviderConfig: ContextProviderConfig = { getContext: async (context: string) => { @@ -11,17 +13,14 @@ const contextProviderConfig: ContextProviderConfig = { key: "event", value: new data.StringData("push") }); - case "secrets": - return new data.Dictionary({ - key: "DEPLOY_KEY", - value: new data.StringData("DEPLOY_KEY") - }); } return undefined; } }; +registerLogger(new TestLogger()); + describe("expressions", () => { it("input extraction", () => { const test = (input: string) => { @@ -146,7 +145,7 @@ jobs: `; const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig); - expect(result.map(x => x.label)).toEqual(["DEPLOY_KEY"]); + expect(result.map(x => x.label)).toEqual(["GITHUB_TOKEN"]); }); it("needs context only includes referenced jobs", async () => { diff --git a/actions-languageservice/src/complete.test.ts b/actions-languageservice/src/complete.test.ts index 3ec5c2b..ef59c0e 100644 --- a/actions-languageservice/src/complete.test.ts +++ b/actions-languageservice/src/complete.test.ts @@ -1,9 +1,13 @@ import {TextEdit} from "vscode-languageserver-types"; import {complete} from "./complete"; import {WorkflowContext} from "./context/workflow-context"; +import {registerLogger} from "./log"; import {getPositionFromCursor} from "./test-utils/cursor-position"; +import {TestLogger} from "./test-utils/logger"; import {ValueProviderConfig, ValueProviderKind} from "./value-providers/config"; +registerLogger(new TestLogger()); + describe("completion", () => { it("runs-on", async () => { const input = "on: push\njobs:\n build:\n runs-on: |"; diff --git a/actions-languageservice/src/context-providers/config.ts b/actions-languageservice/src/context-providers/config.ts index 08c441f..6b3b49f 100644 --- a/actions-languageservice/src/context-providers/config.ts +++ b/actions-languageservice/src/context-providers/config.ts @@ -3,7 +3,7 @@ import {Dictionary} from "@github/actions-expressions/data/dictionary"; import {ExpressionData, Pair} from "@github/actions-expressions/data/expressiondata"; export type ContextProviderConfig = { - getContext: (name: string) => Promise; + getContext: (name: string, defaultContext: data.Dictionary | undefined) => Promise; }; /** diff --git a/actions-languageservice/src/context-providers/default.ts b/actions-languageservice/src/context-providers/default.ts index 4b35267..2ab205a 100644 --- a/actions-languageservice/src/context-providers/default.ts +++ b/actions-languageservice/src/context-providers/default.ts @@ -16,17 +16,9 @@ export async function getContext( const filteredNames = filterContextNames(names, workflowContext); for (const contextName of filteredNames) { - let value: data.Dictionary | undefined; + let value = (await getDefaultContext(contextName, workflowContext)) || new data.Dictionary(); - value = await getDefaultContext(contextName, workflowContext); - - if (!value) { - value = await config?.getContext(contextName); - } - - if (!value) { - value = new data.Dictionary(); - } + value = (await config?.getContext(contextName, value)) || value; context.add(contextName, value); } @@ -51,6 +43,9 @@ async function getDefaultContext(name: string, workflowContext: WorkflowContext) case "inputs": return getInputsContext(workflowContext); + case "secrets": + return objectToDictionary({GITHUB_TOKEN: "***"}); + case "steps": return getStepsContext(workflowContext); diff --git a/actions-languageservice/src/test-utils/logger.ts b/actions-languageservice/src/test-utils/logger.ts new file mode 100644 index 0000000..4a3a75f --- /dev/null +++ b/actions-languageservice/src/test-utils/logger.ts @@ -0,0 +1,19 @@ +import {Logger} from "../log"; + +export class TestLogger implements Logger { + error(message: string): void { + throw new Error(`Error: ${message}`); + } + + warn(message: string): void { + console.warn(message); + } + + info(message: string): void { + console.info(message); + } + + log(message: string): void { + console.warn(message); + } +} diff --git a/actions-languageservice/src/validate.expressions.test.ts b/actions-languageservice/src/validate.expressions.test.ts index 5b1afd0..152cfe6 100644 --- a/actions-languageservice/src/validate.expressions.test.ts +++ b/actions-languageservice/src/validate.expressions.test.ts @@ -1,7 +1,11 @@ import {DiagnosticSeverity} from "vscode-languageserver-types"; +import {registerLogger} from "./log"; import {createDocument} from "./test-utils/document"; +import {TestLogger} from "./test-utils/logger"; import {validate} from "./validate"; +registerLogger(new TestLogger()); + describe("expression validation", () => { it("access invalid context field", async () => { const result = await validate( diff --git a/actions-languageservice/src/validate.ts b/actions-languageservice/src/validate.ts index d0ca448..39e1177 100644 --- a/actions-languageservice/src/validate.ts +++ b/actions-languageservice/src/validate.ts @@ -22,6 +22,7 @@ import {ContextProviderConfig} from "./context-providers/config"; import {getContext} from "./context-providers/default"; import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; import {AccessError, wrapDictionary} from "./expression-validation/error-dictionary"; +import {error} from "./log"; import {nullTrace} from "./nulltrace"; import {findToken} from "./utils/find-token"; import {mapRange} from "./utils/range"; @@ -74,7 +75,7 @@ export async function validate( }); } } catch (e) { - // TODO: Handle error here + error(`Unhandled error while validating: ${e}`); } return diagnostics; @@ -208,7 +209,7 @@ async function validateExpression( range: mapRange(expression.range) }); } else { - // Ignore error + throw e; } } } diff --git a/package-lock.json b/package-lock.json index 5cb1b0b..efa726b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -648,9 +648,9 @@ "dev": true }, "node_modules/@github/actions-expressions": { - "version": "0.0.6", - "resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.6/b98fa3f0e98aec967c22906c2a5848782d6a2ff2", - "integrity": "sha512-0W7a8PIUHcH39cvQdGIOMaj5+3JMCW0u0STKKA42V4TNEvp6R5tcs4L3w3+PEmslPX9P2j6GPxLxSEaq9armew==", + "version": "0.0.7", + "resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.7/deed2be11b9f74791730303b6e33f9aca701d6a7", + "integrity": "sha512-PG8dQUafOckk/ny5O1wcUcfml5IZM8REoi7WBBY1HfpnRR7mL7gqTczQEmQWNTpoHb9f1VQK47y2hBZTOg9Y7g==", "license": "MIT", "engines": { "node": ">= 16" @@ -10892,9 +10892,9 @@ "dev": true }, "@github/actions-expressions": { - "version": "0.0.6", - "resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.6/b98fa3f0e98aec967c22906c2a5848782d6a2ff2", - "integrity": "sha512-0W7a8PIUHcH39cvQdGIOMaj5+3JMCW0u0STKKA42V4TNEvp6R5tcs4L3w3+PEmslPX9P2j6GPxLxSEaq9armew==" + "version": "0.0.7", + "resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.7/deed2be11b9f74791730303b6e33f9aca701d6a7", + "integrity": "sha512-PG8dQUafOckk/ny5O1wcUcfml5IZM8REoi7WBBY1HfpnRR7mL7gqTczQEmQWNTpoHb9f1VQK47y2hBZTOg9Y7g==" }, "@github/actions-languageserver": { "version": "file:actions-languageserver",