Merge pull request #91 from github/cschleiden/improve-expression-validation

Validate expressions even when calling `fromJson`
This commit is contained in:
Christopher Schleiden
2023-01-19 10:08:43 -08:00
committed by GitHub
8 changed files with 118 additions and 36 deletions
@@ -359,7 +359,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: step a
env:
env:
step_env: job_a_env
run: echo "hello \${{ env.step_env }}
`;
@@ -376,7 +376,7 @@ env:
jobs:
a:
runs-on: ubuntu-latest
env:
env:
envjoba: job_a_env
steps:
- name: step a
@@ -395,7 +395,7 @@ env:
jobs:
a:
runs-on: ubuntu-latest
env:
env:
envjoba: job_a_env
steps:
- name: step a
@@ -1185,6 +1185,9 @@ jobs:
- run: echo "hello \${{ github.event.inputs.name }}"
- run: echo "hello \${{ github.event.inputs.third-name }}"
- run: echo "hello \${{ github.event.inputs.random }}"
- run: echo \${{ fromJSON(inputs.random2) }}
- run: echo "hello \${{ inputs.random }}"
name: "\${{ fromJSON('test') == inputs.name }}"
`;
const result = await validate(createDocument("wf.yaml", input));
@@ -1202,6 +1205,34 @@ jobs:
}
},
severity: DiagnosticSeverity.Warning
},
{
message: "Context access might be invalid: random2",
range: {
end: {
character: 47,
line: 20
},
start: {
character: 16,
line: 20
}
},
severity: 2
},
{
message: "Context access might be invalid: random",
range: {
end: {
character: 43,
line: 21
},
start: {
character: 23,
line: 21
}
},
severity: 2
}
]);
});
+27 -2
View File
@@ -1,4 +1,11 @@
import {Evaluator, Lexer, Parser} from "@github/actions-expressions";
import {
data,
Evaluator,
ExpressionEvaluationError,
Lexer,
Parser,
wellKnownFunctions
} from "@github/actions-expressions";
import {Expr} from "@github/actions-expressions/ast";
import {
convertWorkflowTemplate,
@@ -202,7 +209,7 @@ async function validateExpression(
try {
const context = await getContext(namedContexts, contextProviderConfig, workflowContext, Mode.Validation);
const e = new Evaluator(expr, wrapDictionary(context));
const e = new Evaluator(expr, wrapDictionary(context), validatorFunctions);
e.evaluate();
// Any invalid context access would've thrown an error via the `ErrorDictionary`, for now we don't have to check the actual
@@ -214,7 +221,25 @@ async function validateExpression(
severity: DiagnosticSeverity.Warning,
range: mapRange(expression.range)
});
} else if (e instanceof ExpressionEvaluationError) {
diagnostics.push({
message: `Expression might be invalid: ${e.message}`,
severity: DiagnosticSeverity.Error,
range: mapRange(expression.range)
});
}
}
}
}
// Custom implementations for standard actions-expression functions used during validation. For example,
// for fromJson we'll most likely not have a valid input. In order to not throw, we'll always return an
// empty dictionary.
const validatorFunctions = new Map(
Object.entries({
fromjson: {
...wellKnownFunctions.fromjson,
call: () => new data.Dictionary()
}
})
);