Skip to content

Commit c43b4fa

Browse files
authored
Merge pull request #1 from vltpkg/fix/show-failed-output
fix: show query output when expect-results fails
2 parents c5aa835 + aef1940 commit c43b4fa

5 files changed

Lines changed: 225 additions & 37 deletions

File tree

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ inputs:
3232
working-directory:
3333
description: 'Working directory for running vlt query (defaults to repository root)'
3434
required: false
35+
show-results:
36+
description: 'Show query output in logs and summary when queries fail. Set to "always" to show for all queries, "never" to hide, or "failed" (default) to show only for failed queries.'
37+
required: false
38+
default: 'failed'
3539

3640
outputs:
3741
results:

dist/index.js

Lines changed: 32 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ async function run(): Promise<void> {
1717
const scope = core.getInput('scope');
1818
const target = core.getInput('target');
1919
const workingDirectory = core.getInput('working-directory');
20+
const showResults = core.getInput('show-results') || 'failed';
2021

2122
// Validate inputs
2223
if (!query && !queries) {
@@ -55,10 +56,10 @@ async function run(): Promise<void> {
5556
core.info(`Executing ${parsedQueries.length} vlt queries...`);
5657

5758
// Execute queries
58-
const results = await executeQueries(parsedQueries, workingDirectory);
59+
const results = await executeQueries(parsedQueries, workingDirectory, showResults);
5960

6061
// Generate summary
61-
const summary = generateSummaryTable(results);
62+
const summary = generateSummaryTable(results, showResults);
6263
await core.summary.addRaw(summary).write();
6364

6465
// Set outputs

src/query.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,23 @@ export async function executeQuery(
8484
return queryResult;
8585
}
8686

87+
/**
88+
* Check whether output should be shown based on the show-results setting
89+
*/
90+
function shouldShowOutput(passed: boolean, showResults: string): boolean {
91+
if (showResults === 'always') return true;
92+
if (showResults === 'never') return false;
93+
// 'failed' (default) — show only for failed queries
94+
return !passed;
95+
}
96+
8797
/**
8898
* Execute multiple queries
8999
*/
90100
export async function executeQueries(
91101
queries: ParsedQuery[],
92-
workingDirectory?: string
102+
workingDirectory?: string,
103+
showResults: string = 'failed'
93104
): Promise<QueryResult[]> {
94105
const results: QueryResult[] = [];
95106

@@ -100,8 +111,21 @@ export async function executeQueries(
100111
// Log result
101112
if (result.passed) {
102113
core.info(`✅ ${result.query}`);
114+
if (shouldShowOutput(true, showResults) && result.output && result.output.trim()) {
115+
core.info(`Query output:\n${result.output}`);
116+
}
103117
} else {
104118
core.error(`❌ ${result.query}: ${result.error}`);
119+
if (shouldShowOutput(false, showResults)) {
120+
// Show stdout so users can see what matched (e.g. expect-results failures)
121+
if (result.output && result.output.trim()) {
122+
core.info(`Query output:\n${result.output}`);
123+
}
124+
// Show stderr so users can see CLI errors (e.g. unsupported selector)
125+
if (result.stderr && result.stderr.trim()) {
126+
core.info(`Query stderr:\n${result.stderr}`);
127+
}
128+
}
105129
}
106130
}
107131

@@ -111,7 +135,7 @@ export async function executeQueries(
111135
/**
112136
* Generate summary table for GitHub Actions step summary
113137
*/
114-
export function generateSummaryTable(results: QueryResult[]): string {
138+
export function generateSummaryTable(results: QueryResult[], showResults: string = 'failed'): string {
115139
const lines: string[] = [];
116140

117141
lines.push('## Query Deps Results');
@@ -147,12 +171,19 @@ export function generateSummaryTable(results: QueryResult[]): string {
147171
if (result.stderr) {
148172
lines.push(`- stderr: \`${escapeMarkdown(result.stderr)}\``);
149173
}
174+
if (shouldShowOutput(false, showResults) && result.output && result.output.trim()) {
175+
lines.push('');
176+
lines.push('Output:');
177+
lines.push('```');
178+
lines.push(result.output);
179+
lines.push('```');
180+
}
150181
lines.push('');
151182
}
152183
}
153184

154185
// Add output for successful queries with actual output
155-
const successfulWithOutput = results.filter(r => r.passed && r.output.trim());
186+
const successfulWithOutput = results.filter(r => r.passed && r.output.trim() && shouldShowOutput(true, showResults));
156187
if (successfulWithOutput.length > 0) {
157188
lines.push('### Query Outputs');
158189
lines.push('');

tests/query.test.ts

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,111 @@ describe('generateSummaryTable', () => {
8080
expect(summary).toContain('Expected 0 results, but got 1');
8181
});
8282

83-
it('should include query outputs for successful queries', () => {
83+
it('should include query output in failed queries section (default show-results=failed)', () => {
84+
const results: QueryResult[] = [
85+
{
86+
query: '*:license(copyleft) --expect-results=0',
87+
selector: '*:license(copyleft)',
88+
flags: ['--expect-results=0'],
89+
output: 'gpl-pkg@1.0.0\nlgpl-lib@2.3.4\nagpl-service@0.1.0',
90+
stderr: '',
91+
exitCode: 0,
92+
success: true,
93+
passed: false,
94+
error: 'Expected 0 results, but got 3',
95+
expectedResults: '0',
96+
actualResultCount: 3,
97+
duration: 120,
98+
},
99+
];
100+
101+
const summary = generateSummaryTable(results);
102+
103+
expect(summary).toContain('### Failed Queries');
104+
expect(summary).toContain('Expected 0 results, but got 3');
105+
// The actual matched packages should be shown
106+
expect(summary).toContain('Output:');
107+
expect(summary).toContain('gpl-pkg@1.0.0');
108+
expect(summary).toContain('lgpl-lib@2.3.4');
109+
expect(summary).toContain('agpl-service@0.1.0');
110+
});
111+
112+
it('should show stderr in failed queries section for CLI errors', () => {
113+
const results: QueryResult[] = [
114+
{
115+
query: ':diff() --expect-results=0',
116+
selector: ':diff()',
117+
flags: ['--expect-results=0'],
118+
output: '',
119+
stderr: 'Error: unsupported selector :diff()',
120+
exitCode: 1,
121+
success: false,
122+
passed: false,
123+
error: 'Error: unsupported selector :diff()',
124+
duration: 50,
125+
},
126+
];
127+
128+
const summary = generateSummaryTable(results);
129+
130+
expect(summary).toContain('### Failed Queries');
131+
expect(summary).toContain('unsupported selector');
132+
expect(summary).toContain('stderr');
133+
});
134+
135+
it('should show both stdout and stderr for CLI errors with partial output', () => {
136+
const results: QueryResult[] = [
137+
{
138+
query: ':some-selector',
139+
selector: ':some-selector',
140+
flags: [],
141+
output: 'partial-result@1.0.0',
142+
stderr: 'Warning: query terminated early\nError: connection reset',
143+
exitCode: 1,
144+
success: false,
145+
passed: false,
146+
error: 'Warning: query terminated early\nError: connection reset',
147+
duration: 300,
148+
},
149+
];
150+
151+
const summary = generateSummaryTable(results);
152+
153+
expect(summary).toContain('### Failed Queries');
154+
expect(summary).toContain('connection reset');
155+
// stdout should also be shown
156+
expect(summary).toContain('Output:');
157+
expect(summary).toContain('partial-result@1.0.0');
158+
});
159+
160+
it('should not show output for failed queries when show-results=never', () => {
161+
const results: QueryResult[] = [
162+
{
163+
query: '*:license(copyleft) --expect-results=0',
164+
selector: '*:license(copyleft)',
165+
flags: ['--expect-results=0'],
166+
output: 'gpl-pkg@1.0.0\nlgpl-lib@2.3.4',
167+
stderr: '',
168+
exitCode: 0,
169+
success: true,
170+
passed: false,
171+
error: 'Expected 0 results, but got 2',
172+
expectedResults: '0',
173+
actualResultCount: 2,
174+
duration: 120,
175+
},
176+
];
177+
178+
const summary = generateSummaryTable(results, 'never');
179+
180+
expect(summary).toContain('### Failed Queries');
181+
expect(summary).toContain('Expected 0 results, but got 2');
182+
// Output should NOT be shown
183+
expect(summary).not.toContain('gpl-pkg@1.0.0');
184+
expect(summary).not.toContain('Output:');
185+
});
186+
187+
it('should show output for successful queries when show-results=always', () => {
84188
const results: QueryResult[] = [
85189
{
86190
query: ':outdated --view=json',
@@ -95,7 +199,52 @@ describe('generateSummaryTable', () => {
95199
},
96200
];
97201

98-
const summary = generateSummaryTable(results);
202+
const summary = generateSummaryTable(results, 'always');
203+
204+
expect(summary).toContain('### Query Outputs');
205+
expect(summary).toContain('```');
206+
expect(summary).toContain('"name": "lodash"');
207+
});
208+
209+
it('should not show successful query outputs with default show-results=failed', () => {
210+
const results: QueryResult[] = [
211+
{
212+
query: ':outdated --view=json',
213+
selector: ':outdated',
214+
flags: ['--view=json'],
215+
output: '[\n {\n "name": "lodash",\n "current": "4.17.20",\n "wanted": "4.17.21"\n }\n]',
216+
stderr: '',
217+
exitCode: 0,
218+
success: true,
219+
passed: true,
220+
duration: 200,
221+
},
222+
];
223+
224+
const summary = generateSummaryTable(results, 'failed');
225+
226+
// With 'failed' mode, successful query output should NOT be shown
227+
expect(summary).not.toContain('### Query Outputs');
228+
expect(summary).not.toContain('"name": "lodash"');
229+
});
230+
231+
it('should include query outputs for successful queries (legacy default behavior)', () => {
232+
// When show-results is 'always', successful query outputs are shown
233+
const results: QueryResult[] = [
234+
{
235+
query: ':outdated --view=json',
236+
selector: ':outdated',
237+
flags: ['--view=json'],
238+
output: '[\n {\n "name": "lodash",\n "current": "4.17.20",\n "wanted": "4.17.21"\n }\n]',
239+
stderr: '',
240+
exitCode: 0,
241+
success: true,
242+
passed: true,
243+
duration: 200,
244+
},
245+
];
246+
247+
const summary = generateSummaryTable(results, 'always');
99248

100249
expect(summary).toContain('### Query Outputs');
101250
expect(summary).toContain('```');
@@ -159,4 +308,4 @@ describe('setOutputs', () => {
159308

160309
expect(mockSetOutput).toHaveBeenCalledWith('passed', 'false');
161310
});
162-
});
311+
});

0 commit comments

Comments
 (0)