Merge branch 'main' into joshmgross/workflow_call-validation
This commit is contained in:
@@ -12,14 +12,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 16.x
|
||||
- name: Use Node.js 16.15
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 16.15
|
||||
cache: 'npm'
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
- run: npm ci
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: npm run format-check -ws
|
||||
- run: npm run build -ws
|
||||
- run: npm test -ws
|
||||
|
||||
@@ -3,3 +3,4 @@ dist
|
||||
*.md
|
||||
*.js
|
||||
*.json
|
||||
*.d.ts
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-expressions",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"source": "./src/index.ts",
|
||||
@@ -37,7 +37,7 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
@@ -45,7 +45,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.7.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-languageserver",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"description": "Language server for GitHub Actions",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
@@ -38,15 +38,15 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-languageservice": "^0.1.100",
|
||||
"@github/actions-workflow-parser": "^0.1.100",
|
||||
"@octokit/rest": "^19.0.5",
|
||||
"@github/actions-languageservice": "^0.1.109",
|
||||
"@github/actions-workflow-parser": "^0.1.109",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"vscode-languageserver": "^8.0.2",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"yaml": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
@@ -55,7 +55,7 @@
|
||||
"@types/jest": "^29.0.3",
|
||||
"fetch-mock": "^9.11.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import {Octokit} from "@octokit/rest";
|
||||
|
||||
export function getClient(token: string, userAgent?: string): Octokit {
|
||||
return new Octokit({
|
||||
auth: token,
|
||||
userAgent: userAgent || `GitHub Actions Language Server`
|
||||
});
|
||||
}
|
||||
@@ -16,19 +16,20 @@ import {
|
||||
TextDocumentSyncKind
|
||||
} from "vscode-languageserver";
|
||||
import {TextDocument} from "vscode-languageserver-textdocument";
|
||||
import {getClient} from "./client";
|
||||
import {Commands} from "./commands";
|
||||
import {contextProviders} from "./context-providers";
|
||||
import {descriptionProvider} from "./description-provider";
|
||||
import {InitializationOptions, RepositoryContext} from "./initializationOptions";
|
||||
import {onCompletion} from "./on-completion";
|
||||
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<TextDocument> = new TextDocuments(TextDocument);
|
||||
|
||||
let sessionToken: string | undefined;
|
||||
let client: Octokit | undefined;
|
||||
let repos: RepositoryContext[] = [];
|
||||
const cache = new TTLCache();
|
||||
|
||||
@@ -49,7 +50,11 @@ export function initConnection(connection: Connection) {
|
||||
);
|
||||
|
||||
const options: InitializationOptions = params.initializationOptions;
|
||||
sessionToken = options.sessionToken;
|
||||
|
||||
if (options.sessionToken) {
|
||||
client = getClient(options.sessionToken, options.userAgent);
|
||||
}
|
||||
|
||||
if (options.repos) {
|
||||
repos = options.repos;
|
||||
}
|
||||
@@ -93,15 +98,13 @@ export function initConnection(connection: Connection) {
|
||||
const repoContext = repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri));
|
||||
|
||||
const config: ValidationConfig = {
|
||||
valueProviderConfig: valueProviders(sessionToken, repoContext, cache),
|
||||
contextProviderConfig: contextProviders(sessionToken, repoContext, cache),
|
||||
valueProviderConfig: valueProviders(client, repoContext, cache),
|
||||
contextProviderConfig: contextProviders(client, repoContext, cache),
|
||||
getActionInputs: async action => {
|
||||
if (sessionToken) {
|
||||
const octokit = new Octokit({
|
||||
auth: sessionToken
|
||||
});
|
||||
return await getActionInputs(octokit, cache, action);
|
||||
if (client) {
|
||||
return await getActionInputs(client, cache, action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
@@ -114,7 +117,7 @@ export function initConnection(connection: Connection) {
|
||||
return await onCompletion(
|
||||
position,
|
||||
documents.get(textDocument.uri)!,
|
||||
sessionToken,
|
||||
client,
|
||||
repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri)),
|
||||
cache
|
||||
);
|
||||
@@ -122,7 +125,7 @@ export function initConnection(connection: Connection) {
|
||||
|
||||
connection.onHover(async ({position, textDocument}: HoverParams): Promise<Hover | null> => {
|
||||
return hover(documents.get(textDocument.uri)!, position, {
|
||||
descriptionProvider: descriptionProvider(sessionToken, cache)
|
||||
descriptionProvider: descriptionProvider(client, cache)
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,18 +9,14 @@ import {RepositoryContext} from "./initializationOptions";
|
||||
import {TTLCache} from "./utils/cache";
|
||||
|
||||
export function contextProviders(
|
||||
sessionToken: string | undefined,
|
||||
client: Octokit | undefined,
|
||||
repo: RepositoryContext | undefined,
|
||||
cache: TTLCache
|
||||
): ContextProviderConfig {
|
||||
if (!repo || !sessionToken) {
|
||||
if (!repo || !client) {
|
||||
return {getContext: (_: string) => Promise.resolve(undefined)};
|
||||
}
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: sessionToken
|
||||
});
|
||||
|
||||
const getContext = async (
|
||||
name: string,
|
||||
defaultContext: DescriptionDictionary | undefined,
|
||||
@@ -28,11 +24,11 @@ export function contextProviders(
|
||||
) => {
|
||||
switch (name) {
|
||||
case "secrets":
|
||||
return await getSecrets(workflowContext, octokit, cache, repo, defaultContext);
|
||||
return await getSecrets(workflowContext, client, cache, repo, defaultContext);
|
||||
case "vars":
|
||||
return await getVariables(workflowContext, octokit, cache, repo, defaultContext);
|
||||
return await getVariables(workflowContext, client, cache, repo, defaultContext);
|
||||
case "steps":
|
||||
return await getStepsContext(octokit, cache, defaultContext, workflowContext);
|
||||
return await getStepsContext(client, cache, defaultContext, workflowContext);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,15 @@ export async function getSecrets(
|
||||
}
|
||||
>();
|
||||
|
||||
secrets.orgSecrets.forEach(secret =>
|
||||
secretsMap.set(secret.value.toLowerCase(), {
|
||||
key: secret.value,
|
||||
value: new data.StringData("***"),
|
||||
description: "Organization secret"
|
||||
})
|
||||
);
|
||||
|
||||
// Override org secrets with repo secrets
|
||||
secrets.repoSecrets.forEach(secret =>
|
||||
secretsMap.set(secret.value.toLowerCase(), {
|
||||
key: secret.value,
|
||||
@@ -76,6 +85,7 @@ async function getRemoteSecrets(
|
||||
): Promise<{
|
||||
repoSecrets: StringData[];
|
||||
environmentSecrets: StringData[];
|
||||
orgSecrets: StringData[];
|
||||
}> {
|
||||
return {
|
||||
repoSecrets: await cache.get(`${repo.owner}/${repo.name}/secrets`, undefined, () =>
|
||||
@@ -86,18 +96,22 @@ async function getRemoteSecrets(
|
||||
(await cache.get(`${repo.owner}/${repo.name}/secrets/environment/${environmentName}`, undefined, () =>
|
||||
fetchEnvironmentSecrets(octokit, repo.id, environmentName)
|
||||
))) ||
|
||||
[]
|
||||
[],
|
||||
orgSecrets: await cache.get(`${repo.owner}/secrets`, undefined, () => fetchOrganizationSecrets(octokit, repo))
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchSecrets(octokit: Octokit, owner: string, name: string): Promise<StringData[]> {
|
||||
try {
|
||||
const response = await octokit.actions.listRepoSecrets({
|
||||
owner,
|
||||
repo: name
|
||||
});
|
||||
|
||||
return response.data.secrets.map(secret => new StringData(secret.name));
|
||||
return await octokit.paginate(
|
||||
octokit.actions.listRepoSecrets,
|
||||
{
|
||||
owner,
|
||||
repo: name,
|
||||
per_page: 100
|
||||
},
|
||||
response => response.data.map(secret => new StringData(secret.name))
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("Failure to retrieve secrets: ", e);
|
||||
}
|
||||
@@ -111,15 +125,37 @@ async function fetchEnvironmentSecrets(
|
||||
environmentName: string
|
||||
): Promise<StringData[]> {
|
||||
try {
|
||||
const response = await octokit.actions.listEnvironmentSecrets({
|
||||
repository_id: repositoryId,
|
||||
environment_name: environmentName
|
||||
});
|
||||
|
||||
return response.data.secrets.map(secret => new StringData(secret.name));
|
||||
return await octokit.paginate(
|
||||
octokit.actions.listEnvironmentSecrets,
|
||||
{
|
||||
repository_id: repositoryId,
|
||||
environment_name: environmentName,
|
||||
per_page: 100
|
||||
},
|
||||
response => response.data.map(secret => new StringData(secret.name))
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("Failure to retrieve environment secrets: ", e);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
async function fetchOrganizationSecrets(octokit: Octokit, repo: RepositoryContext): Promise<StringData[]> {
|
||||
if (!repo.organizationOwned) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const secrets: {name: string}[] = await octokit.paginate("GET /repos/{owner}/{repo}/actions/organization-secrets", {
|
||||
owner: repo.owner,
|
||||
repo: repo.name,
|
||||
per_page: 100
|
||||
});
|
||||
return secrets.map(secret => new StringData(secret.name));
|
||||
} catch (e) {
|
||||
console.log("Failure to retrieve organization secrets: ", e);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -42,6 +42,15 @@ export async function getVariables(
|
||||
}
|
||||
>();
|
||||
|
||||
variables.organizationVariables.forEach(variable =>
|
||||
variablesMap.set(variable.key.toLowerCase(), {
|
||||
key: variable.key,
|
||||
value: new data.StringData(variable.value.coerceString()),
|
||||
description: `${variable.value.coerceString()} - Organization variable`
|
||||
})
|
||||
);
|
||||
|
||||
// Override org variables with repo variables
|
||||
variables.repoVariables.forEach(variable =>
|
||||
variablesMap.set(variable.key.toLowerCase(), {
|
||||
key: variable.key,
|
||||
@@ -77,6 +86,7 @@ export async function getRemoteVariables(
|
||||
): Promise<{
|
||||
repoVariables: Pair[];
|
||||
environmentVariables: Pair[];
|
||||
organizationVariables: Pair[];
|
||||
}> {
|
||||
// Repo variables
|
||||
return {
|
||||
@@ -88,25 +98,27 @@ export async function getRemoteVariables(
|
||||
(await cache.get(`${repo.owner}/${repo.name}/vars/environment/${environmentName}`, undefined, () =>
|
||||
fetchEnvironmentVariables(octokit, repo.id, environmentName)
|
||||
))) ||
|
||||
[]
|
||||
[],
|
||||
organizationVariables: await cache.get(`${repo.owner}/vars`, undefined, () =>
|
||||
fetchOrganizationVariables(octokit, repo)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchVariables(octokit: Octokit, owner: string, name: string): Promise<Pair[]> {
|
||||
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)};
|
||||
});
|
||||
return await octokit.paginate(
|
||||
octokit.actions.listRepoVariables,
|
||||
{
|
||||
owner: owner,
|
||||
repo: name,
|
||||
per_page: 100
|
||||
},
|
||||
response =>
|
||||
response.data.map(variable => {
|
||||
return {key: variable.name, value: new StringData(variable.value)};
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("Failure to retrieve variables: ", e);
|
||||
}
|
||||
@@ -120,25 +132,45 @@ async function fetchEnvironmentVariables(
|
||||
environmentName: string
|
||||
): Promise<Pair[]> {
|
||||
try {
|
||||
const response = (await octokit.paginate(
|
||||
"GET /repositories/{repository_id}/environments/{environment_name}/variables{?per_page}",
|
||||
return await octokit.paginate(
|
||||
octokit.actions.listEnvironmentVariables,
|
||||
{
|
||||
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)};
|
||||
});
|
||||
environment_name: environmentName,
|
||||
per_page: 100
|
||||
},
|
||||
response =>
|
||||
response.data.map(variable => {
|
||||
return {key: variable.name, value: new StringData(variable.value)};
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("Failure to retrieve environment variables: ", e);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
async function fetchOrganizationVariables(octokit: Octokit, repo: RepositoryContext): Promise<Pair[]> {
|
||||
if (!repo.organizationOwned) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const variables: {name: string; value: string}[] = await octokit.paginate(
|
||||
"GET /repos/{owner}/{repo}/actions/organization-variables",
|
||||
{
|
||||
owner: repo.owner,
|
||||
repo: repo.name,
|
||||
per_page: 100
|
||||
}
|
||||
);
|
||||
return variables.map(variable => {
|
||||
return {key: variable.name, value: new StringData(variable.value)};
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Failure to retrieve organization variables: ", e);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
import {DescriptionProvider} from "@github/actions-languageservice/hover";
|
||||
import {Octokit} from "@octokit/rest";
|
||||
import {TTLCache} from "./utils/cache";
|
||||
import {getActionInputDescription} from "./description-providers/action-input";
|
||||
import {TTLCache} from "./utils/cache";
|
||||
|
||||
export function descriptionProvider(sessionToken: string | undefined, cache: TTLCache): DescriptionProvider {
|
||||
const octokit =
|
||||
sessionToken &&
|
||||
new Octokit({
|
||||
auth: sessionToken
|
||||
});
|
||||
|
||||
export function descriptionProvider(client: Octokit | undefined, cache: TTLCache): DescriptionProvider {
|
||||
const getDescription: DescriptionProvider["getDescription"] = async (context, token, path) => {
|
||||
if (!octokit) {
|
||||
if (!client) {
|
||||
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 await getActionInputDescription(client, cache, context.step, token);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@ export interface InitializationOptions {
|
||||
*/
|
||||
sessionToken?: string;
|
||||
|
||||
/**
|
||||
* Optional user agent to use when making calls to github.com
|
||||
*/
|
||||
userAgent?: string;
|
||||
|
||||
/**
|
||||
* List of repositories that the language server should be aware of
|
||||
*/
|
||||
@@ -31,6 +36,11 @@ export interface RepositoryContext {
|
||||
*/
|
||||
owner: string;
|
||||
|
||||
/**
|
||||
* Indicates if the repository is owned by an organization
|
||||
*/
|
||||
organizationOwned: boolean;
|
||||
|
||||
/**
|
||||
* Repository name
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {complete} from "@github/actions-languageservice/complete";
|
||||
import {Octokit} from "@octokit/rest";
|
||||
import {CompletionItem, Position} from "vscode-languageserver";
|
||||
import {TextDocument} from "vscode-languageserver-textdocument";
|
||||
import {contextProviders} from "./context-providers";
|
||||
@@ -9,14 +10,14 @@ import {valueProviders} from "./value-providers";
|
||||
export async function onCompletion(
|
||||
position: Position,
|
||||
document: TextDocument,
|
||||
sessionToken: string | undefined,
|
||||
client: Octokit | undefined,
|
||||
repoContext: RepositoryContext | undefined,
|
||||
cache: TTLCache
|
||||
): Promise<CompletionItem[]> {
|
||||
return await complete(
|
||||
document,
|
||||
position,
|
||||
repoContext && valueProviders(sessionToken, repoContext, cache),
|
||||
repoContext && contextProviders(sessionToken, repoContext, cache)
|
||||
repoContext && valueProviders(client, repoContext, cache),
|
||||
repoContext && contextProviders(client, repoContext, cache)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,34 +9,30 @@ import {getEnvironments} from "./value-providers/job-environment";
|
||||
import {getRunnerLabels} from "./value-providers/runs-on";
|
||||
|
||||
export function valueProviders(
|
||||
sessionToken: string | undefined,
|
||||
client: Octokit | undefined,
|
||||
repo: RepositoryContext | undefined,
|
||||
cache: TTLCache
|
||||
): ValueProviderConfig {
|
||||
if (!repo || !sessionToken) {
|
||||
if (!repo || !client) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: sessionToken
|
||||
});
|
||||
|
||||
return {
|
||||
"job-environment": {
|
||||
kind: ValueProviderKind.AllowedValues,
|
||||
get: (_: WorkflowContext) => getEnvironments(octokit, cache, repo.owner, repo.name)
|
||||
get: (_: WorkflowContext) => getEnvironments(client, cache, repo.owner, repo.name)
|
||||
},
|
||||
"job-environment-name": {
|
||||
kind: ValueProviderKind.AllowedValues,
|
||||
get: (_: WorkflowContext) => getEnvironments(octokit, cache, repo.owner, repo.name)
|
||||
get: (_: WorkflowContext) => getEnvironments(client, cache, repo.owner, repo.name)
|
||||
},
|
||||
"runs-on": {
|
||||
kind: ValueProviderKind.SuggestedValues,
|
||||
get: (_: WorkflowContext) => getRunnerLabels(octokit, cache, repo.owner, repo.name)
|
||||
get: (_: WorkflowContext) => getRunnerLabels(client, cache, repo.owner, repo.name)
|
||||
},
|
||||
"step-with": {
|
||||
kind: ValueProviderKind.AllowedValues,
|
||||
get: (context: WorkflowContext) => getActionInputValues(octokit, cache, context)
|
||||
get: (context: WorkflowContext) => getActionInputValues(client, cache, context)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import {Value} from "@github/actions-languageservice/value-providers/config";
|
||||
import {Octokit} from "@octokit/rest";
|
||||
import {TTLCache} from "../utils/cache";
|
||||
|
||||
// Limitation: getRunnerLabels returns default hosted labels and labels for repository self-hosted runners.
|
||||
// It doesn't return labels for organization runners visible to the repository.
|
||||
export async function getRunnerLabels(client: Octokit, cache: TTLCache, owner: string, name: string): Promise<Value[]> {
|
||||
const defaultLabels = [
|
||||
"ubuntu-latest",
|
||||
@@ -33,14 +35,17 @@ export async function getRunnerLabels(client: Octokit, cache: TTLCache, owner: s
|
||||
async function fetchRunnerLabels(client: Octokit, owner: string, name: string): Promise<Set<string>> {
|
||||
const labels = new Set<string>();
|
||||
try {
|
||||
const response = await client.actions.listSelfHostedRunnersForRepo({
|
||||
const itor = client.paginate.iterator(client.actions.listSelfHostedRunnersForRepo, {
|
||||
owner,
|
||||
repo: name
|
||||
repo: name,
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
for (const runner of response.data.runners) {
|
||||
for (const label of runner.labels) {
|
||||
labels.add(label.name);
|
||||
for await (const response of itor) {
|
||||
for (const runner of response.data) {
|
||||
for (const label of runner.labels) {
|
||||
labels.add(label.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"lib": ["es6", "webworker"]
|
||||
"lib": ["es6", "webworker"],
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"watchOptions": {
|
||||
"watchFile": "useFsEvents",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-languageservice",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"description": "Language service for GitHub Actions",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
@@ -38,14 +38,14 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "^0.1.100",
|
||||
"@github/actions-workflow-parser": "^0.1.100",
|
||||
"@github/actions-expressions": "^0.1.109",
|
||||
"@github/actions-workflow-parser": "^0.1.109",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"vscode-languageserver-types": "^3.17.2",
|
||||
"yaml": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
@@ -54,7 +54,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
|
||||
@@ -255,6 +255,13 @@ jobs:
|
||||
expect(result.map(x => x.label)).toEqual(["event"]);
|
||||
});
|
||||
|
||||
it("auto-complete partial", async () => {
|
||||
const input = "run-name: ${{ github.ev| }}";
|
||||
const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig);
|
||||
|
||||
expect(result.map(x => x.label)).toEqual(["event"]);
|
||||
});
|
||||
|
||||
it("using default context provider", async () => {
|
||||
const input =
|
||||
"on: push\njobs:\n build:\n runs-on: ubuntu-latest\n environment:\n url: ${{ runner.| }}\n steps:\n - run: echo";
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import {complete as completeExpression} from "@github/actions-expressions";
|
||||
import {DescriptionDictionary, complete as completeExpression} from "@github/actions-expressions";
|
||||
import {CompletionItem as ExpressionCompletionItem} from "@github/actions-expressions/completion";
|
||||
import {convertWorkflowTemplate, isSequence, isString, parseWorkflow} from "@github/actions-workflow-parser";
|
||||
import {
|
||||
convertWorkflowTemplate,
|
||||
isBasicExpression,
|
||||
isSequence,
|
||||
isString,
|
||||
parseWorkflow
|
||||
} from "@github/actions-workflow-parser";
|
||||
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
|
||||
import {DefinitionType} from "@github/actions-workflow-parser/templates/schema/definition-type";
|
||||
import {StringDefinition} from "@github/actions-workflow-parser/templates/schema/string-definition";
|
||||
@@ -24,6 +30,7 @@ import {transform} from "./utils/transform";
|
||||
import {Value, ValueProviderConfig} from "./value-providers/config";
|
||||
import {defaultValueProviders} from "./value-providers/default";
|
||||
import {definitionValues} from "./value-providers/definition";
|
||||
import {TokenRange} from "@github/actions-workflow-parser/templates/tokens/token-range";
|
||||
|
||||
export function getExpressionInput(input: string, pos: number): string {
|
||||
// Find start marker around the cursor position
|
||||
@@ -71,37 +78,14 @@ export async function complete(
|
||||
// If we are inside an expression, take a different code-path. The workflow parser does not correctly create
|
||||
// expression nodes for invalid expressions and during editing expressions are invalid most of the time.
|
||||
if (token) {
|
||||
const isExpression =
|
||||
token.definition?.definitionType === DefinitionType.String && (token.definition as StringDefinition).isExpression;
|
||||
const containsExpression = isString(token) && token.value.indexOf(OPEN_EXPRESSION) >= 0;
|
||||
if (isString(token) && (isExpression || containsExpression)) {
|
||||
const currentInput = token.source || token.value;
|
||||
|
||||
// Transform the overall position into a node relative position
|
||||
let relCharPos: number = 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 + newPos.character + 1;
|
||||
} else {
|
||||
relCharPos = newPos.character - range.start.character;
|
||||
}
|
||||
|
||||
const expressionInput = (getExpressionInput(currentInput, relCharPos) || "").trim();
|
||||
const isStringExpressionToken = isStringExpression(token);
|
||||
const isBasicExpressionToken = isBasicExpression(token) && token.isExpression;
|
||||
|
||||
if (isStringExpressionToken || isBasicExpressionToken) {
|
||||
const allowedContext = token.definitionInfo?.allowedContext || [];
|
||||
const context = await getContext(allowedContext, contextProviderConfig, workflowContext, Mode.Completion);
|
||||
|
||||
try {
|
||||
return completeExpression(expressionInput, context, [], validatorFunctions).map(item =>
|
||||
mapExpressionCompletionItem(item, currentInput[relCharPos])
|
||||
);
|
||||
} catch (e: any) {
|
||||
error(`Error while completing expression: '${e?.message || "<no details>"}'`);
|
||||
return [];
|
||||
}
|
||||
return getExpressionCompletionItems(token, context, newPos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +200,35 @@ export function getExistingValues(token: TemplateToken | null, parent: TemplateT
|
||||
}
|
||||
}
|
||||
|
||||
function getExpressionCompletionItems(
|
||||
token: TemplateToken,
|
||||
context: DescriptionDictionary,
|
||||
pos: Position
|
||||
): CompletionItem[] {
|
||||
let expressionInput = "";
|
||||
let currentInput = "";
|
||||
let relCharPos: number = 0;
|
||||
|
||||
if (isBasicExpression(token)) {
|
||||
expressionInput = currentInput = token.expression;
|
||||
relCharPos = getRelCharPos(token.range!, expressionInput, pos);
|
||||
} else {
|
||||
const stringToken = token.assertString("Expected string token for expression completion");
|
||||
currentInput = stringToken.source || stringToken.value;
|
||||
relCharPos = getRelCharPos(stringToken.range!, currentInput, pos);
|
||||
expressionInput = (getExpressionInput(currentInput, relCharPos) || "").trim();
|
||||
}
|
||||
|
||||
try {
|
||||
return completeExpression(expressionInput, context, [], validatorFunctions).map(item =>
|
||||
mapExpressionCompletionItem(item, currentInput[relCharPos])
|
||||
);
|
||||
} catch (e: any) {
|
||||
error(`Error while completing expression: '${e?.message || "<no details>"}'`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function filterAndSortCompletionOptions(options: Value[], existingValues?: Set<string>) {
|
||||
options = options.filter(x => !existingValues?.has(x.label));
|
||||
options.sort((a, b) => a.label.localeCompare(b.label));
|
||||
@@ -239,3 +252,23 @@ function mapExpressionCompletionItem(item: ExpressionCompletionItem, charAfterPo
|
||||
kind: item.function ? CompletionItemKind.Function : CompletionItemKind.Variable
|
||||
};
|
||||
}
|
||||
|
||||
function getRelCharPos(tokenRange: TokenRange, currentInput: string, pos: Position): number {
|
||||
// Transform the overall position into a node relative position
|
||||
const range = mapRange(tokenRange);
|
||||
if (range.start.line !== range.end.line) {
|
||||
const lines = currentInput.split("\n");
|
||||
const lineDiff = pos.line - range.start.line - 1;
|
||||
const linesBeforeCusor = lines.slice(0, lineDiff);
|
||||
return linesBeforeCusor.join("\n").length + pos.character + 1;
|
||||
} else {
|
||||
return pos.character - range.start.character;
|
||||
}
|
||||
}
|
||||
|
||||
function isStringExpression(token: TemplateToken): boolean {
|
||||
const isExpression =
|
||||
token.definition?.definitionType === DefinitionType.String && (token.definition as StringDefinition).isExpression;
|
||||
const containsExpression = isString(token) && token.value.indexOf(OPEN_EXPRESSION) >= 0;
|
||||
return isExpression || containsExpression;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import descriptions from "./descriptions.json";
|
||||
import descriptions from "./descriptions.json" assert {type: "json"};
|
||||
|
||||
export const RootContext = "root";
|
||||
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
import check_run from "./check_run.json";
|
||||
import check_suite from "./check_suite.json";
|
||||
import commit_comment from "./commit_comment.json";
|
||||
import content_reference from "./content_reference.json";
|
||||
import create from "./create.json";
|
||||
import deletePayload from "./delete.json";
|
||||
import deploy_key from "./deploy_key.json";
|
||||
import deployment from "./deployment.json";
|
||||
import deployment_status from "./deployment_status.json";
|
||||
import fork from "./fork.json";
|
||||
import github_app_authorization from "./github_app_authorization.json";
|
||||
import gollum from "./gollum.json";
|
||||
import installation from "./installation.json";
|
||||
import installation_repositories from "./installation_repositories.json";
|
||||
import issue_comment from "./issue_comment.json";
|
||||
import issues from "./issues.json";
|
||||
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";
|
||||
import organization from "./organization.json";
|
||||
import packagePayload from "./package_payload.json";
|
||||
import page_build from "./page_build.json";
|
||||
import ping from "./ping.json";
|
||||
import project from "./project.json";
|
||||
import project_card from "./project_card.json";
|
||||
import project_column from "./project_column.json";
|
||||
import publicPayload from "./public.json";
|
||||
import pull_request from "./pull_request.json";
|
||||
import pull_request_review from "./pull_request_review.json";
|
||||
import pull_request_review_comment from "./pull_request_review_comment.json";
|
||||
import push from "./push.json";
|
||||
import release from "./release.json";
|
||||
import repository from "./repository.json";
|
||||
import repository_dispatch from "./repository_dispatch.json";
|
||||
import repository_import from "./repository_import.json";
|
||||
import repository_vulnerability_alert from "./repository_vulnerability_alert.json";
|
||||
import schedule from "./schedule.json";
|
||||
import security_advisory from "./security_advisory.json";
|
||||
import sponsorship from "./sponsorship.json";
|
||||
import star from "./star.json";
|
||||
import status from "./status.json";
|
||||
import team from "./team.json";
|
||||
import team_add from "./team_add.json";
|
||||
import watch from "./watch.json";
|
||||
import workflow_call from "./workflow_call.json";
|
||||
import workflow_dispatch from "./workflow_dispatch.json";
|
||||
import workflow_run from "./workflow_run.json";
|
||||
import check_run from "./check_run.json" assert {type: "json"};
|
||||
import check_suite from "./check_suite.json" assert {type: "json"};
|
||||
import commit_comment from "./commit_comment.json" assert {type: "json"};
|
||||
import content_reference from "./content_reference.json" assert {type: "json"};
|
||||
import create from "./create.json" assert {type: "json"};
|
||||
import deletePayload from "./delete.json" assert {type: "json"};
|
||||
import deploy_key from "./deploy_key.json" assert {type: "json"};
|
||||
import deployment from "./deployment.json" assert {type: "json"};
|
||||
import deployment_status from "./deployment_status.json" assert {type: "json"};
|
||||
import fork from "./fork.json" assert {type: "json"};
|
||||
import github_app_authorization from "./github_app_authorization.json" assert {type: "json"};
|
||||
import gollum from "./gollum.json" assert {type: "json"};
|
||||
import installation from "./installation.json" assert {type: "json"};
|
||||
import installation_repositories from "./installation_repositories.json" assert {type: "json"};
|
||||
import issue_comment from "./issue_comment.json" assert {type: "json"};
|
||||
import issues from "./issues.json" assert {type: "json"};
|
||||
import label from "./label.json" assert {type: "json"};
|
||||
import marketplace_purchase from "./marketplace_purchase.json" assert {type: "json"};
|
||||
import member from "./member.json" assert {type: "json"};
|
||||
import membership from "./membership.json" assert {type: "json"};
|
||||
import merge_group from "./merge_group.json" assert {type: "json"};
|
||||
import meta from "./meta.json" assert {type: "json"};
|
||||
import milestone from "./milestone.json" assert {type: "json"};
|
||||
import org_block from "./org_block.json" assert {type: "json"};
|
||||
import organization from "./organization.json" assert {type: "json"};
|
||||
import packagePayload from "./package_payload.json" assert {type: "json"};
|
||||
import page_build from "./page_build.json" assert {type: "json"};
|
||||
import ping from "./ping.json" assert {type: "json"};
|
||||
import project from "./project.json" assert {type: "json"};
|
||||
import project_card from "./project_card.json" assert {type: "json"};
|
||||
import project_column from "./project_column.json" assert {type: "json"};
|
||||
import publicPayload from "./public.json" assert {type: "json"};
|
||||
import pull_request from "./pull_request.json" assert {type: "json"};
|
||||
import pull_request_review from "./pull_request_review.json" assert {type: "json"};
|
||||
import pull_request_review_comment from "./pull_request_review_comment.json" assert {type: "json"};
|
||||
import push from "./push.json" assert {type: "json"};
|
||||
import release from "./release.json" assert {type: "json"};
|
||||
import repository from "./repository.json" assert {type: "json"};
|
||||
import repository_dispatch from "./repository_dispatch.json" assert {type: "json"};
|
||||
import repository_import from "./repository_import.json" assert {type: "json"};
|
||||
import repository_vulnerability_alert from "./repository_vulnerability_alert.json" assert {type: "json"};
|
||||
import schedule from "./schedule.json" assert {type: "json"};
|
||||
import security_advisory from "./security_advisory.json" assert {type: "json"};
|
||||
import sponsorship from "./sponsorship.json" assert {type: "json"};
|
||||
import star from "./star.json" assert {type: "json"};
|
||||
import status from "./status.json" assert {type: "json"};
|
||||
import team from "./team.json" assert {type: "json"};
|
||||
import team_add from "./team_add.json" assert {type: "json"};
|
||||
import watch from "./watch.json" assert {type: "json"};
|
||||
import workflow_call from "./workflow_call.json" assert {type: "json"};
|
||||
import workflow_dispatch from "./workflow_dispatch.json" assert {type: "json"};
|
||||
import workflow_run from "./workflow_run.json" assert {type: "json"};
|
||||
|
||||
export const eventPayloads: {[key: string]: Object} = {
|
||||
check_run,
|
||||
|
||||
@@ -17,7 +17,7 @@ function testHoverConfig(tokenValue: string, tokenKey: string, description?: str
|
||||
return description;
|
||||
}
|
||||
} satisfies DescriptionProvider
|
||||
} satisfies HoverConfig
|
||||
} satisfies HoverConfig;
|
||||
}
|
||||
|
||||
describe("hover", () => {
|
||||
@@ -146,7 +146,8 @@ jobs:
|
||||
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)"
|
||||
const expected =
|
||||
"**Context:** github, inputs, vars, needs, strategy, matrix, secrets, steps, job, runner, env, hashFiles(1,255)";
|
||||
expect(result?.contents).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -164,11 +165,15 @@ jobs:
|
||||
ref|: main
|
||||
`;
|
||||
|
||||
const result = await hover(...getPositionFromCursor(input), testHoverConfig("ref", "string", "The branch, tag or SHA to checkout."));
|
||||
const result = await hover(
|
||||
...getPositionFromCursor(input),
|
||||
testHoverConfig("ref", "string", "The branch, tag or SHA to checkout.")
|
||||
);
|
||||
expect(result).not.toBeUndefined();
|
||||
|
||||
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)"
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -184,6 +189,8 @@ jobs:
|
||||
|
||||
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.");
|
||||
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."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ export async function hover(document: TextDocument, position: Position, config?:
|
||||
info(`Calculating hover for token with definition ${token.definition.key}`);
|
||||
|
||||
if (tokenResult.parent && isCronMappingValue(tokenResult)) {
|
||||
const tokenValue = (token as StringToken).value
|
||||
const tokenValue = (token as StringToken).value;
|
||||
let description = getCronDescription(tokenValue);
|
||||
if (description) {
|
||||
return {
|
||||
@@ -82,7 +82,9 @@ async function getDescription(
|
||||
}
|
||||
|
||||
function isCronMappingValue(tokenResult: TokenResult): boolean {
|
||||
return tokenResult.parent?.definition?.key === "cron-mapping" &&
|
||||
return (
|
||||
tokenResult.parent?.definition?.key === "cron-mapping" &&
|
||||
isString(tokenResult.token!) &&
|
||||
tokenResult.token.value !== "cron"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -141,13 +141,16 @@ function posInToken(pos: Position, token: TemplateToken): boolean {
|
||||
const tokenChar = pos.character + 1;
|
||||
|
||||
// Check lines
|
||||
if (r.start[0] > tokenLine || tokenLine > r.end[0]) {
|
||||
if (r.start.line > tokenLine || tokenLine > r.end.line) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Position is within the token lines. Check character/column if pos line matches
|
||||
// start or end
|
||||
if ((r.start[0] === tokenLine && tokenChar < r.start[1]) || (r.end[0] === tokenLine && tokenChar > r.end[1])) {
|
||||
if (
|
||||
(r.start.line === tokenLine && tokenChar < r.start.column) ||
|
||||
(r.end.line === tokenLine && tokenChar > r.end.column)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -163,14 +166,14 @@ function onSameLine(pos: Position, key: TemplateToken, value: TemplateToken): bo
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.range.start[0] !== value.range.end[0]) {
|
||||
if (value.range.start.line !== value.range.end.line) {
|
||||
// Token occupies multiple lines, can't be an empty node
|
||||
return false;
|
||||
}
|
||||
|
||||
// TokenRange is one-based, Position is zero-based
|
||||
const posLine = pos.line + 1;
|
||||
if (posLine != value.range.start[0]) {
|
||||
if (posLine != value.range.start.line) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export function mapRange(range: TokenRange | undefined): Range {
|
||||
|
||||
export function mapPosition(position: TokenPosition): Position {
|
||||
return {
|
||||
line: position[0] - 1,
|
||||
character: position[1] - 1
|
||||
line: position.line - 1,
|
||||
character: position.column - 1
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,21 +73,7 @@ jobs:
|
||||
{valueProviderConfig: defaultValueProviders}
|
||||
);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toEqual({
|
||||
message: "Value 'does-not-exist' might not be valid",
|
||||
severity: DiagnosticSeverity.Warning,
|
||||
range: {
|
||||
end: {
|
||||
character: 27,
|
||||
line: 3
|
||||
},
|
||||
start: {
|
||||
character: 13,
|
||||
line: 3
|
||||
}
|
||||
}
|
||||
} as Diagnostic);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
||||
it("value in sequence not returned by value provider", async () => {
|
||||
@@ -106,21 +92,7 @@ jobs:
|
||||
{valueProviderConfig: defaultValueProviders}
|
||||
);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toEqual({
|
||||
message: "Value 'does-not-exist' might not be valid",
|
||||
severity: DiagnosticSeverity.Warning,
|
||||
range: {
|
||||
end: {
|
||||
character: 20,
|
||||
line: 5
|
||||
},
|
||||
start: {
|
||||
character: 6,
|
||||
line: 5
|
||||
}
|
||||
}
|
||||
} as Diagnostic);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
||||
it("single value not returned by allowed value provider", async () => {
|
||||
|
||||
@@ -150,13 +150,7 @@ function invalidValue(diagnostics: Diagnostic[], token: StringToken, kind: Value
|
||||
});
|
||||
break;
|
||||
|
||||
case ValueProviderKind.SuggestedValues:
|
||||
diagnostics.push({
|
||||
message: `Value '${token.value}' might not be valid`,
|
||||
severity: DiagnosticSeverity.Warning,
|
||||
range: mapRange(token.range)
|
||||
});
|
||||
break;
|
||||
// no messages for SuggestedValues
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,8 +162,8 @@ function getProviderContext(
|
||||
): WorkflowContext {
|
||||
const {parent, path} = findToken(
|
||||
{
|
||||
line: token.range!.start[0] - 1,
|
||||
character: token.range!.start[1] - 1
|
||||
line: token.range!.start.line - 1,
|
||||
character: token.range!.start.column - 1
|
||||
},
|
||||
root
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-workflow-parser",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"source": "./src/index.ts",
|
||||
@@ -40,12 +40,12 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "^0.1.100",
|
||||
"@github/actions-expressions": "^0.1.109",
|
||||
"cronstrue": "^2.21.0",
|
||||
"yaml": "^2.0.0-8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
@@ -56,7 +56,7 @@
|
||||
"@typescript-eslint/parser": "^5.40.0",
|
||||
"eslint": "7.32.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
|
||||
@@ -85,15 +85,15 @@ jobs:
|
||||
[
|
||||
"${{ github.event_name }}",
|
||||
{
|
||||
start: [7, 16],
|
||||
end: [7, 40]
|
||||
start: {line: 7, column: 16},
|
||||
end: {line: 7, column: 40}
|
||||
}
|
||||
],
|
||||
[
|
||||
"${{ github.ref }}",
|
||||
{
|
||||
start: [8, 24],
|
||||
end: [8, 41]
|
||||
start: {line: 8, column: 24},
|
||||
end: {line: 8, column: 41}
|
||||
}
|
||||
]
|
||||
]);
|
||||
@@ -160,16 +160,16 @@ jobs:
|
||||
{
|
||||
prefix: "test.yaml (Line: 6, Col: 14)",
|
||||
range: {
|
||||
start: [7, 16],
|
||||
end: [7, 40]
|
||||
start: {line: 7, column: 16},
|
||||
end: {line: 7, column: 40}
|
||||
},
|
||||
rawMessage: "Unrecognized function: 'fromJSON2'"
|
||||
},
|
||||
{
|
||||
prefix: "test.yaml (Line: 6, Col: 14)",
|
||||
range: {
|
||||
start: [8, 24],
|
||||
end: [8, 51]
|
||||
start: {line: 8, column: 24},
|
||||
end: {line: 8, column: 51}
|
||||
},
|
||||
rawMessage: "Unrecognized function: 'toJSON2'"
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ describe("parseWorkflow", () => {
|
||||
|
||||
expect(result.context.errors.getErrors()).toEqual([
|
||||
new TemplateValidationError("Required property is missing: runs-on", "test.yaml (Line: 4, Col: 5)", undefined, {
|
||||
start: [4, 5],
|
||||
end: [5, 24]
|
||||
start: {line: 4, column: 5},
|
||||
end: {line: 5, column: 24}
|
||||
})
|
||||
]);
|
||||
});
|
||||
@@ -62,8 +62,8 @@ jobs:
|
||||
"test.yaml (Line: 6, Col: 13)",
|
||||
undefined,
|
||||
{
|
||||
start: [6, 13],
|
||||
end: [6, 37]
|
||||
start: {line: 6, column: 13},
|
||||
end: {line: 6, column: 37}
|
||||
}
|
||||
)
|
||||
]);
|
||||
|
||||
@@ -455,7 +455,7 @@ class TemplateReader {
|
||||
// Doesn't contain "${{"
|
||||
// Check if value should still be evaluated as an expression
|
||||
if (definitionInfo.definition instanceof StringDefinition && definitionInfo.definition.isExpression) {
|
||||
const expression = this.parseIntoExpressionToken(token.range!, raw, allowedContext, token);
|
||||
const expression = this.parseIntoExpressionToken(token.range!, raw, allowedContext, token, definitionInfo);
|
||||
if (expression) {
|
||||
return expression;
|
||||
}
|
||||
@@ -500,11 +500,11 @@ class TemplateReader {
|
||||
);
|
||||
|
||||
let tr = token.range!;
|
||||
if (tr.start[0] === tr.end[0]) {
|
||||
if (tr.start.line === tr.end.line) {
|
||||
// If it's a single line expression, adjust the range to only cover the sub-expression
|
||||
tr = {
|
||||
start: [tr.start[0], tr.start[1] + startExpression],
|
||||
end: [tr.end[0], tr.start[1] + endExpression + 1]
|
||||
start: {line: tr.start.line, column: tr.start.column + startExpression},
|
||||
end: {line: tr.end.line, column: tr.start.column + endExpression + 1}
|
||||
};
|
||||
} else {
|
||||
// Adjust the range to only cover the expression for multi-line strings
|
||||
@@ -515,12 +515,12 @@ class TemplateReader {
|
||||
const adjustedEnd = endExpression - beginningOfLine + 1;
|
||||
|
||||
tr = {
|
||||
start: [tr.start[0] + adjustedStartLine, adjustedStart],
|
||||
end: [tr.start[0] + adjustedStartLine, adjustedEnd]
|
||||
start: {line: tr.start.line + adjustedStartLine, column: adjustedStart},
|
||||
end: {line: tr.start.line + adjustedStartLine, column: adjustedEnd}
|
||||
};
|
||||
}
|
||||
|
||||
const expression = this.parseIntoExpressionToken(tr, rawExpression, allowedContext, token);
|
||||
const expression = this.parseIntoExpressionToken(tr, rawExpression, allowedContext, token, definitionInfo);
|
||||
|
||||
if (!expression) {
|
||||
// Record that we've hit an error but continue to validate any other expressions
|
||||
@@ -615,9 +615,10 @@ class TemplateReader {
|
||||
tr: TokenRange,
|
||||
rawExpression: string,
|
||||
allowedContext: string[],
|
||||
token: TemplateToken
|
||||
token: TemplateToken,
|
||||
definitionInfo: DefinitionInfo | undefined
|
||||
): ExpressionToken | undefined {
|
||||
const parseExpressionResult = this.parseExpression(tr, rawExpression, allowedContext, token.definitionInfo);
|
||||
const parseExpressionResult = this.parseExpression(tr, rawExpression, allowedContext, definitionInfo);
|
||||
|
||||
// Check for error
|
||||
if (parseExpressionResult.error) {
|
||||
|
||||
@@ -42,11 +42,11 @@ export abstract class TemplateToken {
|
||||
}
|
||||
|
||||
public get line(): number | undefined {
|
||||
return this.range?.start[0];
|
||||
return this.range?.start.line;
|
||||
}
|
||||
|
||||
public get col(): number | undefined {
|
||||
return this.range?.start[1];
|
||||
return this.range?.start.column;
|
||||
}
|
||||
|
||||
public get definition(): Definition | undefined {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
export type Position = [line: number, character: number];
|
||||
/** Represents the position within a template object */
|
||||
export type Position = {
|
||||
/** The one-based line value */
|
||||
line: number;
|
||||
/** The one-based column value */
|
||||
column: number;
|
||||
};
|
||||
|
||||
export type TokenRange = {
|
||||
start: Position;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {JSONObjectReader} from "../templates/json-object-reader";
|
||||
import {TemplateSchema} from "../templates/schema";
|
||||
import WorkflowSchema from "../workflow-v1.0.json";
|
||||
import WorkflowSchema from "../workflow-v1.0.json" assert {type: "json"};
|
||||
|
||||
let schema: TemplateSchema;
|
||||
|
||||
|
||||
@@ -74,8 +74,8 @@ it("YAML errors include range information", () => {
|
||||
|
||||
const error = context.errors.getErrors()[0];
|
||||
expect(error.range).toEqual({
|
||||
start: [7, 38],
|
||||
end: [7, 63]
|
||||
start: {line: 7, column: 38},
|
||||
end: {line: 7, column: 63}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ export class YamlObjectReader implements ObjectReader {
|
||||
const elp = this.lineCounter.linePos(endPos);
|
||||
|
||||
return {
|
||||
start: [slp.line, slp.col],
|
||||
end: [elp.line, elp.col]
|
||||
start: {line: slp.line, column: slp.col},
|
||||
end: {line: elp.line, column: elp.col}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ function rangeFromLinePos(linePos: [LinePos] | [LinePos, LinePos] | undefined):
|
||||
return;
|
||||
}
|
||||
// TokenRange and linePos are both 1-based
|
||||
const start: Position = [linePos[0].line, linePos[0].col];
|
||||
const end: Position = linePos.length == 2 ? [linePos[1].line, linePos[1].col] : start;
|
||||
const start: Position = {line: linePos[0].line, column: linePos[0].col};
|
||||
const end: Position = linePos.length == 2 ? {line: linePos[1].line, column: linePos[1].col} : start;
|
||||
return {start, end};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "browser-playground",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@github/actions-languageserver": "^0.1.100",
|
||||
"@github/actions-languageserver": "^0.1.109",
|
||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
||||
"monaco-editor-workers": "^0.34.2",
|
||||
"monaco-languageclient": "^4.0.3",
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.1.100"
|
||||
"version": "0.1.109"
|
||||
}
|
||||
|
||||
Generated
+119
-63
@@ -18,28 +18,28 @@
|
||||
},
|
||||
"actions-expressions": {
|
||||
"name": "@github/actions-expressions",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
}
|
||||
},
|
||||
"actions-languageserver": {
|
||||
"name": "@github/actions-languageserver",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/actions-languageservice": "^0.1.100",
|
||||
"@github/actions-workflow-parser": "^0.1.100",
|
||||
"@octokit/rest": "^19.0.5",
|
||||
"@github/actions-languageservice": "^0.1.109",
|
||||
"@github/actions-workflow-parser": "^0.1.109",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"vscode-languageserver": "^8.0.2",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"yaml": "^2.1.3"
|
||||
@@ -48,22 +48,22 @@
|
||||
"@types/jest": "^29.0.3",
|
||||
"fetch-mock": "^9.11.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
}
|
||||
},
|
||||
"actions-languageservice": {
|
||||
"name": "@github/actions-languageservice",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "^0.1.100",
|
||||
"@github/actions-workflow-parser": "^0.1.100",
|
||||
"@github/actions-expressions": "^0.1.109",
|
||||
"@github/actions-workflow-parser": "^0.1.109",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"vscode-languageserver-types": "^3.17.2",
|
||||
"yaml": "^2.1.1"
|
||||
@@ -71,21 +71,21 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
}
|
||||
},
|
||||
"actions-workflow-parser": {
|
||||
"name": "@github/actions-workflow-parser",
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "^0.1.100",
|
||||
"@github/actions-expressions": "^0.1.109",
|
||||
"cronstrue": "^2.21.0",
|
||||
"yaml": "^2.0.0-8"
|
||||
},
|
||||
@@ -95,20 +95,20 @@
|
||||
"@typescript-eslint/parser": "^5.40.0",
|
||||
"eslint": "7.32.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 16.15"
|
||||
}
|
||||
},
|
||||
"browser-playground": {
|
||||
"version": "0.1.100",
|
||||
"version": "0.1.109",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/actions-languageserver": "^0.1.100",
|
||||
"@github/actions-languageserver": "^0.1.109",
|
||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
||||
"monaco-editor-workers": "^0.34.2",
|
||||
"monaco-languageclient": "^4.0.3",
|
||||
@@ -2904,11 +2904,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz",
|
||||
"integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz",
|
||||
"integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0"
|
||||
"@octokit/types": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
@@ -2917,6 +2917,19 @@
|
||||
"@octokit/core": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz",
|
||||
"integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz",
|
||||
"integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
@@ -2926,11 +2939,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz",
|
||||
"integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz",
|
||||
"integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"@octokit/types": "^9.0.0",
|
||||
"deprecation": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2940,6 +2953,19 @@
|
||||
"@octokit/core": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz",
|
||||
"integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz",
|
||||
"integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
|
||||
@@ -2970,14 +2996,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "19.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz",
|
||||
"integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==",
|
||||
"version": "19.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz",
|
||||
"integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^4.1.0",
|
||||
"@octokit/plugin-paginate-rest": "^5.0.0",
|
||||
"@octokit/plugin-paginate-rest": "^6.0.0",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^6.7.0"
|
||||
"@octokit/plugin-rest-endpoint-methods": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
@@ -10998,9 +11024,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
|
||||
"integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
@@ -14535,7 +14561,7 @@
|
||||
"requires": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.7.4"
|
||||
@@ -14544,13 +14570,13 @@
|
||||
"@github/actions-languageserver": {
|
||||
"version": "file:actions-languageserver",
|
||||
"requires": {
|
||||
"@github/actions-languageservice": "^0.1.100",
|
||||
"@github/actions-workflow-parser": "^0.1.100",
|
||||
"@octokit/rest": "^19.0.5",
|
||||
"@github/actions-languageservice": "^0.1.109",
|
||||
"@github/actions-workflow-parser": "^0.1.109",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@types/jest": "^29.0.3",
|
||||
"fetch-mock": "^9.11.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4",
|
||||
@@ -14562,11 +14588,11 @@
|
||||
"@github/actions-languageservice": {
|
||||
"version": "file:actions-languageservice",
|
||||
"requires": {
|
||||
"@github/actions-expressions": "^0.1.100",
|
||||
"@github/actions-workflow-parser": "^0.1.100",
|
||||
"@github/actions-expressions": "^0.1.109",
|
||||
"@github/actions-workflow-parser": "^0.1.109",
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4",
|
||||
@@ -14578,14 +14604,14 @@
|
||||
"@github/actions-workflow-parser": {
|
||||
"version": "file:actions-workflow-parser",
|
||||
"requires": {
|
||||
"@github/actions-expressions": "^0.1.100",
|
||||
"@github/actions-expressions": "^0.1.109",
|
||||
"@types/jest": "^29.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
||||
"@typescript-eslint/parser": "^5.40.0",
|
||||
"cronstrue": "^2.21.0",
|
||||
"eslint": "7.32.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4",
|
||||
@@ -16280,11 +16306,26 @@
|
||||
"dev": true
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz",
|
||||
"integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz",
|
||||
"integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0"
|
||||
"@octokit/types": "^9.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz",
|
||||
"integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz",
|
||||
"integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^16.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-request-log": {
|
||||
@@ -16294,12 +16335,27 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz",
|
||||
"integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz",
|
||||
"integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"@octokit/types": "^9.0.0",
|
||||
"deprecation": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz",
|
||||
"integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz",
|
||||
"integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^16.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
@@ -16326,14 +16382,14 @@
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "19.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz",
|
||||
"integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==",
|
||||
"version": "19.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz",
|
||||
"integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==",
|
||||
"requires": {
|
||||
"@octokit/core": "^4.1.0",
|
||||
"@octokit/plugin-paginate-rest": "^5.0.0",
|
||||
"@octokit/plugin-paginate-rest": "^6.0.0",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^6.7.0"
|
||||
"@octokit/plugin-rest-endpoint-methods": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
@@ -17506,7 +17562,7 @@
|
||||
"browser-playground": {
|
||||
"version": "file:browser-playground",
|
||||
"requires": {
|
||||
"@github/actions-languageserver": "^0.1.100",
|
||||
"@github/actions-languageserver": "^0.1.109",
|
||||
"css-loader": "^6.7.2",
|
||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
||||
"monaco-editor-workers": "^0.34.2",
|
||||
@@ -22508,9 +22564,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
|
||||
"integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-format": {
|
||||
|
||||
Reference in New Issue
Block a user