Files
languageservices/actions-languageservice/src/validate.expressions.test.ts
T

659 lines
14 KiB
TypeScript
Raw Normal View History

2022-11-21 17:55:24 -08:00
import {DiagnosticSeverity} from "vscode-languageserver-types";
2022-12-08 10:17:29 -08:00
import {registerLogger} from "./log";
2022-11-21 17:55:24 -08:00
import {createDocument} from "./test-utils/document";
2022-12-08 10:17:29 -08:00
import {TestLogger} from "./test-utils/logger";
2022-11-21 17:55:24 -08:00
import {validate} from "./validate";
2022-12-08 10:17:29 -08:00
registerLogger(new TestLogger());
2022-11-21 17:55:24 -08:00
describe("expression validation", () => {
it("access invalid context field", async () => {
const result = await validate(
createDocument(
"wf.yaml",
2022-12-02 10:48:49 -08:00
`on: push
run-name: name-\${{ github.does-not-exist }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo`
2022-11-21 17:55:24 -08:00
)
);
expect(result).toEqual([
{
2022-11-22 10:59:55 -08:00
message: "Context access might be invalid: does-not-exist",
2022-11-21 17:55:24 -08:00
range: {
end: {
character: 43,
line: 1
},
start: {
2022-11-22 10:59:55 -08:00
character: 15,
2022-11-21 17:55:24 -08:00
line: 1
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
it("access invalid nested context field", async () => {
const result = await validate(
createDocument(
"wf.yaml",
"on: push\nrun-name: name-${{ github.does-not-exist.again }}\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - run: echo"
)
);
expect(result).toEqual([
{
2022-11-22 10:59:55 -08:00
message: "Context access might be invalid: does-not-exist",
2022-11-21 17:55:24 -08:00
range: {
end: {
character: 49,
line: 1
},
start: {
2022-11-22 10:59:55 -08:00
character: 15,
2022-11-21 17:55:24 -08:00
line: 1
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
2022-12-01 15:10:18 -05:00
it("needs.<job_id>", async () => {
const input = `
on: push
jobs:
a:
runs-on: ubuntu-latest
steps:
- run: echo hello a
b:
needs: [a]
runs-on: ubuntu-latest
steps:
- run: echo "hello \${{ needs.a }}"
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
2022-12-02 10:48:49 -08:00
describe("expressions without markers", () => {
it("access invalid context field", async () => {
const result = await validate(
createDocument(
"wf.yaml",
`on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo
if: github.does-not-exist`
)
);
expect(result).toEqual([
{
message: "Context access might be invalid: does-not-exist",
range: {
start: {
character: 12,
line: 6
},
end: {
character: 33,
line: 6
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
});
describe("steps context", () => {
it("steps.<step_id>", async () => {
const input = `
on: push
jobs:
a:
runs-on: ubuntu-latest
steps:
- id: a
run: echo hello a
- id: b
run: echo \${{ steps.a }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("steps.<step_id>.outputs.<output_id>", async () => {
const input = `
on: push
jobs:
a:
runs-on: ubuntu-latest
steps:
- id: a
run: echo hello a
- id: b
run: echo \${{ steps.a.outputs.anything }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("invalid reference of later step", async () => {
const input = `
on: push
jobs:
a:
runs-on: ubuntu-latest
steps:
- id: a
run: echo hello a
- id: b
run: echo \${{ steps.c }}
- id: c
run: echo hello c
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: c",
range: {
end: {
character: 36,
line: 9
},
start: {
character: 22,
line: 9
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
it("invalid reference of generated step name", async () => {
const input = `
on: push
jobs:
a:
runs-on: ubuntu-latest
steps:
- id: a
run: echo hello a
- id: b
run: echo \${{ steps.__run }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: __run",
range: {
end: {
character: 40,
line: 9
},
start: {
character: 22,
line: 9
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
});
2022-12-06 18:02:54 -05:00
describe("strategy context", () => {
it("reference within a matrix job", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
test-group: [1, 2]
node: [14, 16]
steps:
- uses: actions/checkout@v3
- run: echo \${{ strategy.fail-fast }}
- run: echo \${{ strategy.job-index }}
- run: echo \${{ strategy.job-total }}
- run: echo \${{ strategy.max-parallel }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("reference outside of a matrix job", async () => {
2022-12-06 18:02:54 -05:00
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: echo \${{ strategy.fail-fast }}
- run: echo \${{ strategy.job-index }}
- run: echo \${{ strategy.job-total }}
- run: echo \${{ strategy.max-parallel }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).not.toEqual([]);
});
it("invalid strategy property", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
test-group: [1, 2]
node: [14, 16]
steps:
- uses: actions/checkout@v3
- run: echo \${{ strategy.fail-faster-than-fast }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: fail-faster-than-fast",
range: {
end: {
character: 55,
line: 12
},
start: {
character: 18,
line: 12
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
});
2022-12-08 13:55:58 -05:00
describe("matrix context", () => {
it("reference within a matrix job", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [14, 16]
steps:
- uses: actions/checkout@v3
- run: echo \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("reference outside of a matrix job", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: echo \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: matrix",
range: {
end: {
character: 36,
line: 8
},
start: {
character: 18,
line: 8
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
it("basic matrix", async () => {
const input = `
on: push
jobs:
test:
runs-on: \${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [14, 16]
steps:
- uses: actions/checkout@v3
- run: echo \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("invalid property reference", async () => {
const input = `
on: push
jobs:
test:
runs-on: \${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [14, 16]
include:
- os: macos-latest
node: 14
exclude:
- os: windows-latest
node: 14
steps:
- uses: actions/checkout@v3
- run: echo \${{ matrix.goversion }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: goversion",
range: {
end: {
character: 41,
line: 18
},
start: {
character: 18,
line: 18
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
it("matrix with include", async () => {
const input = `
on: push
jobs:
test:
runs-on: \${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [14, 16]
include:
- os: macos-latest
node: 14
steps:
- uses: actions/checkout@v3
- run: echo \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("matrix with only include", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- os: windows-latest
node: 14
steps:
- uses: actions/checkout@v3
- run: echo \${{ matrix.os }}
- run: echo \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("matrix with exclude", async () => {
const input = `
on: push
jobs:
test:
runs-on: \${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [14, 16]
include:
- os: macos-latest
node: 14
exclude:
- os: windows-latest
node: 14
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("matrix with only exclude", async () => {
const input = `
on: push
jobs:
test:
runs-on: \${{ matrix.os }}
strategy:
matrix:
exclude:
- os: windows-latest
node: 14
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: \${{ matrix.node }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: os",
range: {
end: {
character: 29,
line: 5
},
start: {
character: 13,
line: 5
}
},
severity: DiagnosticSeverity.Warning
},
{
message: "Context access might be invalid: node",
range: {
end: {
character: 42,
line: 15
},
start: {
character: 24,
line: 15
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
it("matrix from expression", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix: \${{ fromJSON('{"color":["green","blue"]}') }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: \${{ matrix.ANYVALUE }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("matrix with include expression", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
fruit: [apple, pear]
animal: [cat, dog]
include: \${{ fromJSON('{"color":"green"}') }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: \${{ matrix.ANYVALUE }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("matrix with property expression", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
color: \${{ fromJSON('["green","blue"]') }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: \${{ matrix.color }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([]);
});
it("matrix with property expression and invalid property reference", async () => {
const input = `
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
color: \${{ fromJSON('["green","blue"]') }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: \${{ matrix.shape }}
`;
const result = await validate(createDocument("wf.yaml", input));
expect(result).toEqual([
{
message: "Context access might be invalid: shape",
range: {
end: {
character: 43,
line: 13
},
start: {
character: 24,
line: 13
}
},
severity: DiagnosticSeverity.Warning
}
]);
});
});
2022-11-21 17:55:24 -08:00
});