Merge branch 'main' into joshmgross/schema-function-descriptions
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a bug or unexpected behavior while using Actions Language Services
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. With this workflow '...'
|
||||
2. Do this '...'
|
||||
3. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Package/Area**
|
||||
- [ ] Expressions
|
||||
- [ ] Workflow Parser
|
||||
- [ ] Language Service
|
||||
- [ ] Language Server
|
||||
|
||||
**Package Version**
|
||||
`v1.x.y`
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Ask a question or provide feedback about the Actions Language Services
|
||||
about: For general Q&A and feedback, see the Discussions tab.
|
||||
url: https://github.com/actions/languageservices/discussions
|
||||
- name: Ask a question or provide feedback about GitHub Actions
|
||||
about: Please check out the GitHub community forum for discussions about GitHub Actions
|
||||
url: https://github.com/orgs/community/discussions/categories/actions
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for Actions Language Services
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -23,4 +23,5 @@ jobs:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: npm run format-check -ws
|
||||
- run: npm run build -ws
|
||||
- run: npm run lint -ws
|
||||
- run: npm test -ws
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "browser-playground",
|
||||
"version": "0.1.177",
|
||||
"version": "0.1.179",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@github/actions-languageserver": "^0.1.177",
|
||||
"@github/actions-languageserver": "^0.1.179",
|
||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
||||
"monaco-editor-workers": "^0.34.2",
|
||||
"monaco-languageclient": "^4.0.3",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
import * as monaco from "monaco-editor";
|
||||
|
||||
import {CloseAction, ErrorAction, MessageTransports, MonacoLanguageClient, MonacoServices} from "monaco-languageclient";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-expressions",
|
||||
"version": "0.1.177",
|
||||
"version": "0.1.179",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"source": "./src/index.ts",
|
||||
@@ -46,6 +46,11 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-languageserver",
|
||||
"version": "0.1.177",
|
||||
"version": "0.1.179",
|
||||
"description": "Language server for GitHub Actions",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
@@ -40,8 +40,8 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-languageservice": "^0.1.177",
|
||||
"@github/actions-workflow-parser": "^0.1.177",
|
||||
"@github/actions-languageservice": "^0.1.179",
|
||||
"@github/actions-workflow-parser": "^0.1.179",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@octokit/types": "^9.0.0",
|
||||
"vscode-languageserver": "^8.0.2",
|
||||
@@ -56,6 +56,11 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"fetch-mock": "^9.11.0",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.8.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-languageservice",
|
||||
"version": "0.1.177",
|
||||
"version": "0.1.179",
|
||||
"description": "Language service for GitHub Actions",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
@@ -41,8 +41,8 @@
|
||||
"watch": "tsc --build tsconfig.build.json --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "^0.1.177",
|
||||
"@github/actions-workflow-parser": "^0.1.177",
|
||||
"@github/actions-expressions": "^0.1.179",
|
||||
"@github/actions-workflow-parser": "^0.1.179",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"vscode-languageserver-types": "^3.17.2",
|
||||
"vscode-uri": "^3.0.7",
|
||||
@@ -57,6 +57,11 @@
|
||||
"types": "./dist/index.d.ts",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.8.3",
|
||||
"rest-api-description": "github:github/rest-api-description",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import {data, DescriptionDictionary} from "@github/actions-expressions";
|
||||
import {CompletionItem, CompletionItemKind} from "vscode-languageserver-types";
|
||||
import {complete, getExpressionInput} from "./complete";
|
||||
@@ -9,17 +10,19 @@ import {testFileProvider} from "./test-utils/test-file-provider";
|
||||
import {clearCache} from "./utils/workflow-cache";
|
||||
|
||||
const contextProviderConfig: ContextProviderConfig = {
|
||||
getContext: async (context: string) => {
|
||||
getContext: (context: string) => {
|
||||
switch (context) {
|
||||
case "github":
|
||||
return new DescriptionDictionary({
|
||||
key: "event",
|
||||
value: new data.StringData("push"),
|
||||
description: "The event that triggered the workflow"
|
||||
});
|
||||
return Promise.resolve(
|
||||
new DescriptionDictionary({
|
||||
key: "event",
|
||||
value: new data.StringData("push"),
|
||||
description: "The event that triggered the workflow"
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -225,6 +225,10 @@ function getExpressionCompletionItems(
|
||||
context: DescriptionDictionary,
|
||||
pos: Position
|
||||
): CompletionItem[] {
|
||||
if (!token.range) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let currentInput = "";
|
||||
|
||||
if (isBasicExpression(token)) {
|
||||
@@ -234,15 +238,15 @@ function getExpressionCompletionItems(
|
||||
currentInput = stringToken.source || stringToken.value;
|
||||
}
|
||||
|
||||
const relCharOffset = getRelCharOffset(token.range!, currentInput, pos);
|
||||
const relCharOffset = getRelCharOffset(token.range, currentInput, pos);
|
||||
const expressionInput = (getExpressionInput(currentInput, relCharOffset) || "").trim();
|
||||
|
||||
try {
|
||||
return completeExpression(expressionInput, context, [], validatorFunctions).map(item =>
|
||||
mapExpressionCompletionItem(item, currentInput[relCharOffset])
|
||||
);
|
||||
} catch (e: any) {
|
||||
error(`Error while completing expression: '${e?.message || "<no details>"}'`);
|
||||
} catch (e) {
|
||||
error(`Error while completing expression: '${(e as Error)?.message || "<no details>"}'`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +73,10 @@ type DeduplicatedWebhooks = {
|
||||
};
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */
|
||||
const dedupedWebhookPayloads: DeduplicatedWebhooks = webhooks as any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const objects: Param[] = webhookObjects as any;
|
||||
/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */
|
||||
|
||||
// Hydrated webhook payloads
|
||||
const webhookPayloads: Webhooks = {};
|
||||
|
||||
@@ -9,28 +9,30 @@ import {TestLogger} from "./test-utils/logger";
|
||||
import {clearCache} from "./utils/workflow-cache";
|
||||
|
||||
const contextProviderConfig: ContextProviderConfig = {
|
||||
getContext: async (context: string) => {
|
||||
getContext: (context: string) => {
|
||||
switch (context) {
|
||||
case "github":
|
||||
return new DescriptionDictionary(
|
||||
{
|
||||
key: "event",
|
||||
value: new data.StringData("push"),
|
||||
description: "The event that triggered the workflow"
|
||||
},
|
||||
{
|
||||
key: "test",
|
||||
value: new DescriptionDictionary({
|
||||
key: "name",
|
||||
return Promise.resolve(
|
||||
new DescriptionDictionary(
|
||||
{
|
||||
key: "event",
|
||||
value: new data.StringData("push"),
|
||||
description: "Name for the test"
|
||||
}),
|
||||
description: "Test dictionary"
|
||||
}
|
||||
description: "The event that triggered the workflow"
|
||||
},
|
||||
{
|
||||
key: "test",
|
||||
value: new DescriptionDictionary({
|
||||
key: "name",
|
||||
value: new data.StringData("push"),
|
||||
description: "Name for the test"
|
||||
}),
|
||||
description: "Test dictionary"
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
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";
|
||||
import {testFileProvider} from "./test-utils/test-file-provider";
|
||||
@@ -8,15 +7,16 @@ import {clearCache} from "./utils/workflow-cache";
|
||||
export function testHoverConfig(tokenValue: string, tokenKey: string, description?: string) {
|
||||
return {
|
||||
descriptionProvider: {
|
||||
getDescription: async (_, token, __) => {
|
||||
getDescription: (_, token) => {
|
||||
if (!isString(token)) {
|
||||
throw new Error("Test provider only supports string tokens");
|
||||
}
|
||||
|
||||
expect(token.value).toEqual(tokenValue);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
expect(token.definition!.key).toEqual(tokenKey);
|
||||
|
||||
return description;
|
||||
return Promise.resolve(description);
|
||||
}
|
||||
} satisfies DescriptionProvider,
|
||||
fileProvider: testFileProvider
|
||||
|
||||
@@ -160,7 +160,8 @@ async function getDescription(
|
||||
function isCronMappingValue(tokenResult: TokenResult): boolean {
|
||||
return (
|
||||
tokenResult.parent?.definition?.key === "cron-mapping" &&
|
||||
isString(tokenResult.token!) &&
|
||||
!!tokenResult.token &&
|
||||
isString(tokenResult.token) &&
|
||||
tokenResult.token.value !== "cron"
|
||||
);
|
||||
}
|
||||
@@ -211,7 +212,7 @@ function expressionHover(
|
||||
};
|
||||
} catch (e) {
|
||||
// Hovering over an invalid expression should not cause an error here
|
||||
info(`Encountered error trying to calculate expression hover: ${e}`);
|
||||
info(`Encountered error trying to calculate expression hover: ${(e as Error).message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import {TraceWriter} from "@github/actions-workflow-parser/templates/trace-writer";
|
||||
import {NoOperationTraceWriter} from "@github/actions-workflow-parser/templates/trace-writer";
|
||||
|
||||
export const nullTrace: TraceWriter = {
|
||||
info: x => {},
|
||||
verbose: x => {},
|
||||
error: x => {}
|
||||
};
|
||||
export const nullTrace = new NoOperationTraceWriter();
|
||||
|
||||
@@ -14,7 +14,7 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
const validationConfig: ValidationConfig = {
|
||||
fetchActionMetadata: async (ref: ActionReference) => {
|
||||
fetchActionMetadata: (ref: ActionReference) => {
|
||||
let metadata: ActionMetadata | undefined = undefined;
|
||||
switch (ref.owner + "/" + ref.name + "@" + ref.ref) {
|
||||
case "actions/checkout@v3":
|
||||
@@ -82,7 +82,7 @@ const validationConfig: ValidationConfig = {
|
||||
description: "An action with no inputs"
|
||||
};
|
||||
}
|
||||
return metadata;
|
||||
return Promise.resolve(metadata);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -326,8 +326,8 @@ jobs:
|
||||
config.valueProviderConfig = {
|
||||
"step-with": {
|
||||
kind: ValueProviderKind.AllowedValues,
|
||||
get: async () => {
|
||||
return [{label: "repository", description: "Repository name with owner."}];
|
||||
get: () => {
|
||||
return Promise.resolve([{label: "repository", description: "Repository name with owner."}]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {data, DescriptionDictionary} from "@github/actions-expressions/.";
|
||||
import {DescriptionDictionary} from "@github/actions-expressions/.";
|
||||
import {DiagnosticSeverity} from "vscode-languageserver-types";
|
||||
import {ContextProviderConfig} from "./context-providers/config";
|
||||
import {registerLogger} from "./log";
|
||||
@@ -48,15 +48,16 @@ jobs:
|
||||
|
||||
it("partial skip access invalid context on incomplete", async () => {
|
||||
const contextProviderConfig: ContextProviderConfig = {
|
||||
getContext: async (context: string) => {
|
||||
getContext: (context: string) => {
|
||||
switch (context) {
|
||||
case "secrets":
|
||||
case "secrets": {
|
||||
const dict = new DescriptionDictionary();
|
||||
dict.complete = false;
|
||||
return dict;
|
||||
return Promise.resolve(dict);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import {createDocument} from "./test-utils/document";
|
||||
import {validate} from "./validate";
|
||||
import {defaultValueProviders} from "./value-providers/default";
|
||||
import {clearCache} from "./utils/workflow-cache";
|
||||
import {ValueProvider, ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
||||
import {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
||||
|
||||
beforeEach(() => {
|
||||
clearCache();
|
||||
@@ -249,7 +249,7 @@ jobs:
|
||||
const valueProviderConfig: ValueProviderConfig = {
|
||||
"job-environment": {
|
||||
kind: ValueProviderKind.AllowedValues,
|
||||
get: async () => [{label: "test"}],
|
||||
get: () => Promise.resolve([{label: "test"}]),
|
||||
caseInsensitive: false
|
||||
}
|
||||
};
|
||||
@@ -286,7 +286,7 @@ jobs:
|
||||
const valueProviderConfig: ValueProviderConfig = {
|
||||
"job-environment": {
|
||||
kind: ValueProviderKind.AllowedValues,
|
||||
get: async () => [{label: "test"}],
|
||||
get: () => Promise.resolve([{label: "test"}]),
|
||||
caseInsensitive: true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ import {validateAction} from "./validate-action";
|
||||
import {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
||||
import {defaultValueProviders} from "./value-providers/default";
|
||||
import {fetchOrParseWorkflow, fetchOrConvertWorkflowTemplate} from "./utils/workflow-cache";
|
||||
import {TokenRange} from "@github/actions-workflow-parser/templates/tokens/token-range";
|
||||
|
||||
export type ValidationConfig = {
|
||||
valueProviderConfig?: ValueProviderConfig;
|
||||
@@ -72,7 +73,7 @@ export async function validate(textDocument: TextDocument, config?: ValidationCo
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
error(`Unhandled error while validating: ${e}`);
|
||||
error(`Unhandled error while validating: ${(e as Error).message}`);
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
@@ -92,18 +93,18 @@ async function additionalValidations(
|
||||
const validationDefinition = validationToken.definition;
|
||||
|
||||
// If this is an expression, validate it
|
||||
if (isBasicExpression(token)) {
|
||||
if (isBasicExpression(token) && token.range) {
|
||||
await validateExpression(
|
||||
diagnostics,
|
||||
token,
|
||||
validationToken.definitionInfo?.allowedContext || [],
|
||||
config?.contextProviderConfig,
|
||||
getProviderContext(documentUri, template, root, token)
|
||||
getProviderContext(documentUri, template, root, token.range)
|
||||
);
|
||||
}
|
||||
|
||||
if (token.definition?.key === "regular-step") {
|
||||
const context = getProviderContext(documentUri, template, root, token);
|
||||
if (token.definition?.key === "regular-step" && token.range) {
|
||||
const context = getProviderContext(documentUri, template, root, token.range);
|
||||
await validateAction(diagnostics, token, context.step, config);
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ async function additionalValidations(
|
||||
}
|
||||
|
||||
if (valueProvider) {
|
||||
const customValues = await valueProvider.get(getProviderContext(documentUri, template, root, token));
|
||||
const customValues = await valueProvider.get(getProviderContext(documentUri, template, root, token.range));
|
||||
const caseInsensitive = valueProvider.caseInsensitive ?? false;
|
||||
const customValuesMap = new Set(customValues.map(x => (caseInsensitive ? x.label.toLowerCase() : x.label)));
|
||||
|
||||
@@ -161,12 +162,12 @@ function getProviderContext(
|
||||
documentUri: URI,
|
||||
template: WorkflowTemplate,
|
||||
root: TemplateToken,
|
||||
token: TemplateToken
|
||||
tokenRange: TokenRange
|
||||
): WorkflowContext {
|
||||
const {parent, path} = findToken(
|
||||
const {path} = findToken(
|
||||
{
|
||||
line: token.range!.start.line - 1,
|
||||
character: token.range!.start.column - 1
|
||||
line: tokenRange.start.line - 1,
|
||||
character: tokenRange.start.column - 1
|
||||
},
|
||||
root
|
||||
);
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.1.177"
|
||||
"version": "0.1.179"
|
||||
}
|
||||
|
||||
Generated
+1578
-157
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@github/actions-workflow-parser",
|
||||
"version": "0.1.177",
|
||||
"version": "0.1.179",
|
||||
"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.177",
|
||||
"@github/actions-expressions": "^0.1.179",
|
||||
"cronstrue": "^2.21.0",
|
||||
"yaml": "^2.0.0-8"
|
||||
},
|
||||
@@ -52,9 +52,11 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
||||
"@typescript-eslint/parser": "^5.40.0",
|
||||
"eslint": "7.32.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^29.0.3",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^3.0.2",
|
||||
|
||||
Reference in New Issue
Block a user