Merge pull request #100 from github/thyeggman/cronstrue-hover
Produce hover sentence for cron expressions
This commit is contained in:
@@ -99,7 +99,6 @@ function getEventContext(workflowContext: WorkflowContext): ExpressionData {
|
||||
function merge(d: data.Dictionary, toAdd: Object): data.Dictionary {
|
||||
for (const [key, value] of Object.entries(toAdd)) {
|
||||
if (value && typeof value === "object" && !d.get(key)) {
|
||||
|
||||
if (!Array.isArray(value) && Object.entries(value).length === 0) {
|
||||
// Allow an empty object to be any value
|
||||
d.add(key, new data.Null());
|
||||
|
||||
@@ -96,6 +96,39 @@ jobs:
|
||||
expect(result?.contents).toEqual("Runs your workflow when you push a commit or tag.");
|
||||
});
|
||||
|
||||
it("on a cron schedule", async () => {
|
||||
const input = `on:
|
||||
schedule:
|
||||
- cron: '0,30 0|,12 * * *'
|
||||
`;
|
||||
const result = await hover(...getPositionFromCursor(input));
|
||||
expect(result).not.toBeUndefined();
|
||||
expect(result?.contents).toEqual(
|
||||
"Runs at 0 and 30 minutes past the hour, at 00:00 and 12:00\n\n" +
|
||||
"Actions schedules run at most every 5 minutes. " +
|
||||
"[Learn more](https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#onschedule)"
|
||||
);
|
||||
});
|
||||
|
||||
it("on a cron mapping key", async () => {
|
||||
const input = `on:
|
||||
schedule:
|
||||
- c|ron: '0 0 * * *'
|
||||
`;
|
||||
const result = await hover(...getPositionFromCursor(input));
|
||||
expect(result).not.toBeUndefined();
|
||||
expect(result?.contents).toEqual("");
|
||||
});
|
||||
|
||||
it("on an invalid cron schedule", async () => {
|
||||
const input = `on:
|
||||
schedule:
|
||||
- cron: '0 0 |* * * * *'
|
||||
`;
|
||||
const result = await hover(...getPositionFromCursor(input));
|
||||
expect(result).not.toBeUndefined();
|
||||
expect(result?.contents).toEqual("");
|
||||
});
|
||||
|
||||
it("shows context inherited from parent nodes", async () => {
|
||||
const input = `
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import {convertWorkflowTemplate, parseWorkflow, ParseWorkflowResult} from "@github/actions-workflow-parser";
|
||||
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
|
||||
import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token";
|
||||
import {TokenResult} from "./utils/find-token";
|
||||
import {File} from "@github/actions-workflow-parser/workflows/file";
|
||||
import {isString} from "@github/actions-workflow-parser/templates/tokens/type-guards";
|
||||
import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token";
|
||||
import {Position, TextDocument} from "vscode-languageserver-textdocument";
|
||||
import {Hover} from "vscode-languageserver-types";
|
||||
import {getWorkflowContext, WorkflowContext} from "./context/workflow-context";
|
||||
@@ -9,6 +12,7 @@ import {info} from "./log";
|
||||
import {nullTrace} from "./nulltrace";
|
||||
import {findToken} from "./utils/find-token";
|
||||
import {mapRange} from "./utils/range";
|
||||
import {getCronDescription} from "@github/actions-workflow-parser/model/converter/cron";
|
||||
|
||||
export type DescriptionProvider = {
|
||||
getDescription(context: WorkflowContext, token: TemplateToken, path: TemplateToken[]): Promise<string | undefined>;
|
||||
@@ -26,14 +30,26 @@ export async function hover(document: TextDocument, position: Position, config?:
|
||||
};
|
||||
const result = parseWorkflow(file.name, [file], nullTrace);
|
||||
|
||||
const {token, path} = findToken(position, result.value);
|
||||
const tokenResult = findToken(position, result.value);
|
||||
const token = tokenResult.token;
|
||||
if (!token?.definition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
info(`Calculating hover for token with definition ${token.definition.key}`);
|
||||
|
||||
let description = await getDescription(document, config, result, token, path);
|
||||
if (tokenResult.parent && isCronMappingValue(tokenResult)) {
|
||||
const tokenValue = (token as StringToken).value
|
||||
let description = getCronDescription(tokenValue);
|
||||
if (description) {
|
||||
return {
|
||||
contents: description,
|
||||
range: mapRange(token.range)
|
||||
} as Hover;
|
||||
}
|
||||
}
|
||||
|
||||
let description = await getDescription(document, config, result, token, tokenResult.path);
|
||||
|
||||
const allowedContext = token.definitionInfo?.allowedContext;
|
||||
if (allowedContext && allowedContext?.length > 0) {
|
||||
@@ -64,3 +80,9 @@ async function getDescription(
|
||||
const description = await config.descriptionProvider.getDescription(workflowContext, token, path);
|
||||
return description || defaultDescription;
|
||||
}
|
||||
|
||||
function isCronMappingValue(tokenResult: TokenResult): boolean {
|
||||
return tokenResult.parent?.definition?.key === "cron-mapping" &&
|
||||
isString(tokenResult.token!) &&
|
||||
tokenResult.token.value !== "cron"
|
||||
}
|
||||
|
||||
@@ -1248,7 +1248,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo \${{ github.event.client_payload.anything }}
|
||||
- run: echo \${{ github.event.client_payload.branch }}`
|
||||
- run: echo \${{ github.event.client_payload.branch }}`;
|
||||
|
||||
const result = await validate(createDocument("wf.yaml", input));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user