Support descriptions for contexts
This commit is contained in:
@@ -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": {
|
||||
|
||||
@@ -8,28 +8,21 @@ export async function getSecrets(
|
||||
cache: TTLCache,
|
||||
repo: RepositoryContext,
|
||||
environmentName?: string
|
||||
): Promise<StringData[]> {
|
||||
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<StringData[]> {
|
||||
|
||||
@@ -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`."
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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<data.Dictionary | undefined> {
|
||||
): Promise<DescriptionDictionary | undefined> {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user