mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-02 18:00:05 -05:00
100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
// Compares blocks-ci fixture screenshots from a rendered manifest against the committed markdown.
|
|
// Usage: node build/lib/screenshotBlocksCi.ts <manifest-path> <markdown-path> <service-url> [--json]
|
|
//
|
|
// Exit codes:
|
|
// 0 — all screenshots match (or no blocks-ci fixtures)
|
|
// 1 — mismatches found
|
|
//
|
|
// Without --json: prints the full updated markdown to stdout.
|
|
// With --json: prints a JSON object with { startLine, endLine, replacement } for a GitHub suggestion.
|
|
|
|
import * as fs from 'fs';
|
|
|
|
const HEADER = '<!-- auto-generated by CI — do not edit manually -->';
|
|
|
|
interface ManifestFixture {
|
|
readonly fixtureId: string;
|
|
readonly imageHash: string;
|
|
readonly labels?: readonly string[];
|
|
}
|
|
|
|
interface Manifest {
|
|
readonly fixtures: readonly ManifestFixture[];
|
|
}
|
|
|
|
function generateMarkdown(fixtures: readonly ManifestFixture[], serviceUrl: string): string {
|
|
const lines: string[] = [HEADER, ''];
|
|
const seen = new Set<string>();
|
|
const sorted = [...fixtures].sort((a, b) => a.fixtureId.localeCompare(b.fixtureId));
|
|
for (const f of sorted) {
|
|
if (f.labels?.includes('blocks-ci') && !seen.has(f.fixtureId)) {
|
|
seen.add(f.fixtureId);
|
|
lines.push(`#### ${f.fixtureId}`);
|
|
lines.push(``);
|
|
lines.push('');
|
|
}
|
|
}
|
|
return lines.join('\n');
|
|
}
|
|
|
|
function computeDiff(committedLines: string[], updatedLines: string[]): { startLine: number; endLine: number; replacement: string } {
|
|
let firstDiff = 0;
|
|
while (firstDiff < committedLines.length && firstDiff < updatedLines.length && committedLines[firstDiff] === updatedLines[firstDiff]) {
|
|
firstDiff++;
|
|
}
|
|
|
|
let committedEnd = committedLines.length - 1;
|
|
let updatedEnd = updatedLines.length - 1;
|
|
while (committedEnd > firstDiff && updatedEnd > firstDiff && committedLines[committedEnd] === updatedLines[updatedEnd]) {
|
|
committedEnd--;
|
|
updatedEnd--;
|
|
}
|
|
|
|
return {
|
|
startLine: firstDiff + 1, // 1-indexed
|
|
endLine: committedEnd + 1, // 1-indexed
|
|
replacement: updatedLines.slice(firstDiff, updatedEnd + 1).join('\n'),
|
|
};
|
|
}
|
|
|
|
function main(): void {
|
|
const args = process.argv.slice(2);
|
|
const jsonMode = args.includes('--json');
|
|
const positional = args.filter(a => a !== '--json');
|
|
const [manifestPath, markdownPath, serviceUrl] = positional;
|
|
|
|
if (!manifestPath || !markdownPath || !serviceUrl) {
|
|
console.error('Usage: node build/lib/screenshotBlocksCi.ts <manifest-path> <markdown-path> <service-url> [--json]');
|
|
process.exit(1);
|
|
}
|
|
|
|
const manifest: Manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
const actual = generateMarkdown(manifest.fixtures, serviceUrl);
|
|
|
|
let committed = '';
|
|
if (fs.existsSync(markdownPath)) {
|
|
committed = fs.readFileSync(markdownPath, 'utf8');
|
|
}
|
|
|
|
if (actual === committed) {
|
|
process.exit(0);
|
|
}
|
|
|
|
console.error('blocks-ci screenshots have changed.');
|
|
|
|
if (jsonMode) {
|
|
const diff = computeDiff(committed.split('\n'), actual.split('\n'));
|
|
process.stdout.write(JSON.stringify(diff) + '\n');
|
|
} else {
|
|
process.stdout.write(actual);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
main();
|