diff --git a/actions-languageserver/src/context-providers.ts b/actions-languageserver/src/context-providers.ts index 8d37724..2263ff3 100644 --- a/actions-languageserver/src/context-providers.ts +++ b/actions-languageserver/src/context-providers.ts @@ -1,6 +1,7 @@ import {data} 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,7 +28,23 @@ export function contextProviders( ) => { switch (name) { case "secrets": { - const secrets = await getSecrets(octokit, cache, repo.owner, repo.name); + 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 getSecrets(octokit, cache, repo, environmentName); defaultContext = defaultContext || new data.Dictionary(); secrets.forEach(secret => defaultContext!.add(secret.value, new data.StringData("***"))); diff --git a/actions-languageserver/src/context-providers/secrets.ts b/actions-languageserver/src/context-providers/secrets.ts index afdb2e7..c9ca049 100644 --- a/actions-languageserver/src/context-providers/secrets.ts +++ b/actions-languageserver/src/context-providers/secrets.ts @@ -1,16 +1,35 @@ import {StringData} from "@github/actions-expressions/data/string"; import {Octokit} from "@octokit/rest"; +import {RepositoryContext} from "../initializationOptions"; import {TTLCache} from "../utils/cache"; export async function getSecrets( octokit: Octokit, cache: TTLCache, - owner: string, - name: string + repo: RepositoryContext, + environmentName?: string ): Promise { - const repoSecrets = await cache.get(`${owner}/${name}/secrets`, undefined, () => fetchSecrets(octokit, owner, name)); + const secrets: StringData[] = []; - return repoSecrets; + // 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(); } async function fetchSecrets(octokit: Octokit, owner: string, name: string): Promise { @@ -27,3 +46,22 @@ async function fetchSecrets(octokit: Octokit, owner: string, name: string): Prom return []; } + +async function fetchEnvironmentSecrets( + octokit: Octokit, + repositoryId: number, + environmentName: string +): Promise { + try { + const response = await octokit.actions.listEnvironmentSecrets({ + repository_id: repositoryId, + environment_name: environmentName + }); + + return response.data.secrets.map(secret => new StringData(secret.name)); + } catch (e) { + console.log("Failure to retrieve environment secrets: ", e); + } + + return []; +} diff --git a/actions-languageservice/src/context-providers/default.ts b/actions-languageservice/src/context-providers/default.ts index f554bb8..6f62792 100644 --- a/actions-languageservice/src/context-providers/default.ts +++ b/actions-languageservice/src/context-providers/default.ts @@ -47,12 +47,18 @@ export async function getContext( function getDefaultContext(name: string, workflowContext: WorkflowContext, mode: Mode): ContextValue | undefined { switch (name) { + case "env": + return getEnvContext(workflowContext); + case "github": return getGithubContext(workflowContext); case "inputs": return getInputsContext(workflowContext); + case "job": + return getJobContext(workflowContext); + case "matrix": return getMatrixContext(workflowContext, mode); @@ -76,12 +82,6 @@ function getDefaultContext(name: string, workflowContext: WorkflowContext, mode: case "strategy": return getStrategyContext(workflowContext); - - case "job": - return getJobContext(workflowContext); - - case "env": - return getEnvContext(workflowContext); } return undefined; diff --git a/package-lock.json b/package-lock.json index 4358410..90f027e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -702,9 +702,9 @@ "link": true }, "node_modules/@github/actions-workflow-parser": { - "version": "0.0.41", - "resolved": "https://npm.pkg.github.com/download/@github/actions-workflow-parser/0.0.41/234e6042ee06199b4314589ad77dfd7fe0debe6d", - "integrity": "sha512-s27gUhNH80YhFmkcQ5GE5BA5D15xbQ48YjwKCwYKN+ndldaOhpqa+v5Q+NfZlNwBmJ/8lJZob09/IiGRgFq7ag==", + "version": "0.0.42", + "resolved": "https://npm.pkg.github.com/download/@github/actions-workflow-parser/0.0.42/e511c44db93c2c8b522e48ca54fe733063902dd3", + "integrity": "sha512-Qd4vmYjNdFxHBer0P3RympLnBqDCigRqrxvMFRFEfLhUQ1oeBHmmvF6sCEgQ+JtKFlwVPvOoJLmfN/r8o5NEBQ==", "license": "MIT", "dependencies": { "@github/actions-expressions": "*", @@ -13565,9 +13565,9 @@ } }, "@github/actions-workflow-parser": { - "version": "0.0.41", - "resolved": "https://npm.pkg.github.com/download/@github/actions-workflow-parser/0.0.41/234e6042ee06199b4314589ad77dfd7fe0debe6d", - "integrity": "sha512-s27gUhNH80YhFmkcQ5GE5BA5D15xbQ48YjwKCwYKN+ndldaOhpqa+v5Q+NfZlNwBmJ/8lJZob09/IiGRgFq7ag==", + "version": "0.0.42", + "resolved": "https://npm.pkg.github.com/download/@github/actions-workflow-parser/0.0.42/e511c44db93c2c8b522e48ca54fe733063902dd3", + "integrity": "sha512-Qd4vmYjNdFxHBer0P3RympLnBqDCigRqrxvMFRFEfLhUQ1oeBHmmvF6sCEgQ+JtKFlwVPvOoJLmfN/r8o5NEBQ==", "requires": { "@github/actions-expressions": "*", "yaml": "^2.0.0-8"