Skip to content

Commit 59e3d03

Browse files
committed
Validate expression block scalar chomping
1 parent 7f8bba4 commit 59e3d03

15 files changed

+2911
-14
lines changed

languageservice/src/context-providers/matrix.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,17 @@ function stringToToken(value: string) {
4646
}
4747

4848
function expressionToToken(expr: string) {
49-
return new BasicExpressionToken(undefined, undefined, expr, undefined, undefined, undefined);
49+
return new BasicExpressionToken(
50+
undefined,
51+
undefined,
52+
expr,
53+
undefined,
54+
undefined,
55+
undefined,
56+
undefined,
57+
undefined,
58+
undefined
59+
);
5060
}
5161

5262
function contextFromStrategy(strategy?: TemplateToken) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {registerLogger} from "./log";
2+
import {createDocument} from "./test-utils/document";
3+
import {TestLogger} from "./test-utils/logger";
4+
import {clearCache} from "./utils/workflow-cache";
5+
import {validate} from "./validate";
6+
7+
registerLogger(new TestLogger());
8+
9+
beforeEach(() => {
10+
clearCache();
11+
});
12+
13+
describe("block scalar chomping - allowed cases", () => {
14+
it("does NOT warn for step.run with clip chomping (exception)", async () => {
15+
const input = `
16+
on: push
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- run: |
22+
echo \${{ github.event_name }}
23+
`;
24+
const result = await validate(createDocument("wf.yaml", input));
25+
26+
expect(result.filter(d => d.code === "expression-block-scalar-chomping")).toEqual([]);
27+
});
28+
29+
it("does not warn for inline expression", async () => {
30+
const input = `
31+
on: push
32+
jobs:
33+
build:
34+
if: \${{ github.event_name == 'push' }}
35+
runs-on: ubuntu-latest
36+
steps:
37+
- run: echo hi
38+
`;
39+
const result = await validate(createDocument("wf.yaml", input));
40+
41+
expect(result.filter(d => d.code === "expression-block-scalar-chomping")).toEqual([]);
42+
});
43+
44+
it("does not warn for quoted string", async () => {
45+
const input = `
46+
on: push
47+
jobs:
48+
build:
49+
if: "\${{ github.event_name == 'push' }}"
50+
runs-on: ubuntu-latest
51+
steps:
52+
- run: echo hi
53+
`;
54+
const result = await validate(createDocument("wf.yaml", input));
55+
56+
expect(result.filter(d => d.code === "expression-block-scalar-chomping")).toEqual([]);
57+
});
58+
});
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import {DiagnosticSeverity} from "vscode-languageserver-types";
2+
import {registerLogger} from "./log";
3+
import {createDocument} from "./test-utils/document";
4+
import {TestLogger} from "./test-utils/logger";
5+
import {clearCache} from "./utils/workflow-cache";
6+
import {validate} from "./validate";
7+
8+
registerLogger(new TestLogger());
9+
10+
beforeEach(() => {
11+
clearCache();
12+
});
13+
14+
describe("block scalar chomping - boolean fields", () => {
15+
describe("job continue-on-error", () => {
16+
it("errors with clip chomping", async () => {
17+
const input = `
18+
on: push
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
continue-on-error: |
23+
\${{ matrix.experimental }}
24+
steps:
25+
- run: echo hi
26+
`;
27+
const result = await validate(createDocument("wf.yaml", input));
28+
29+
expect(result).toContainEqual(
30+
expect.objectContaining({
31+
message:
32+
"Block scalar adds trailing newline which breaks boolean evaluation. Use '|-' to strip trailing newlines.",
33+
code: "expression-block-scalar-chomping",
34+
severity: DiagnosticSeverity.Error
35+
})
36+
);
37+
});
38+
39+
it("errors with keep chomping", async () => {
40+
const input = `
41+
on: push
42+
jobs:
43+
build:
44+
runs-on: ubuntu-latest
45+
continue-on-error: |+
46+
\${{ matrix.experimental }}
47+
steps:
48+
- run: echo hi
49+
`;
50+
const result = await validate(createDocument("wf.yaml", input));
51+
52+
expect(result).toContainEqual(
53+
expect.objectContaining({
54+
message:
55+
"Block scalar adds trailing newline which breaks boolean evaluation. Use '|-' to strip trailing newlines.",
56+
code: "expression-block-scalar-chomping",
57+
severity: DiagnosticSeverity.Error
58+
})
59+
);
60+
});
61+
62+
it("does not error with strip chomping", async () => {
63+
const input = `
64+
on: push
65+
jobs:
66+
build:
67+
runs-on: ubuntu-latest
68+
continue-on-error: |-
69+
\${{ matrix.experimental }}
70+
steps:
71+
- run: echo hi
72+
`;
73+
const result = await validate(createDocument("wf.yaml", input));
74+
75+
expect(result.filter(d => d.code === "expression-block-scalar-chomping")).toEqual([]);
76+
});
77+
});
78+
79+
describe("step continue-on-error", () => {
80+
it("errors with clip chomping", async () => {
81+
const input = `
82+
on: push
83+
jobs:
84+
build:
85+
runs-on: ubuntu-latest
86+
steps:
87+
- run: echo hi
88+
continue-on-error: |
89+
\${{ matrix.experimental }}
90+
`;
91+
const result = await validate(createDocument("wf.yaml", input));
92+
93+
expect(result).toContainEqual(
94+
expect.objectContaining({
95+
message:
96+
"Block scalar adds trailing newline which breaks boolean evaluation. Use '|-' to strip trailing newlines.",
97+
code: "expression-block-scalar-chomping",
98+
severity: DiagnosticSeverity.Error
99+
})
100+
);
101+
});
102+
103+
it("errors with keep chomping", async () => {
104+
const input = `
105+
on: push
106+
jobs:
107+
build:
108+
runs-on: ubuntu-latest
109+
steps:
110+
- run: echo hi
111+
continue-on-error: |+
112+
\${{ matrix.experimental }}
113+
`;
114+
const result = await validate(createDocument("wf.yaml", input));
115+
116+
expect(result).toContainEqual(
117+
expect.objectContaining({
118+
message:
119+
"Block scalar adds trailing newline which breaks boolean evaluation. Use '|-' to strip trailing newlines.",
120+
code: "expression-block-scalar-chomping",
121+
severity: DiagnosticSeverity.Error
122+
})
123+
);
124+
});
125+
126+
it("does not error with strip chomping", async () => {
127+
const input = `
128+
on: push
129+
jobs:
130+
build:
131+
runs-on: ubuntu-latest
132+
steps:
133+
- run: echo hi
134+
continue-on-error: |-
135+
\${{ matrix.experimental }}
136+
`;
137+
const result = await validate(createDocument("wf.yaml", input));
138+
139+
expect(result.filter(d => d.code === "expression-block-scalar-chomping")).toEqual([]);
140+
});
141+
});
142+
});

0 commit comments

Comments
 (0)