From 0ea849047391328edeee42b399345d292dfb559d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Sat, 28 Feb 2026 17:55:41 +0000 Subject: [PATCH] Switch from `js-yaml` to `yaml` for better output formatting --- pr-checks/package-lock.json | 43 ++++++++++++++----------------------- pr-checks/package.json | 7 +++--- pr-checks/sync.ts | 37 ++++++++++++++++++------------- 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/pr-checks/package-lock.json b/pr-checks/package-lock.json index 9988fd2d2..2facb7322 100644 --- a/pr-checks/package-lock.json +++ b/pr-checks/package-lock.json @@ -5,10 +5,9 @@ "packages": { "": { "dependencies": { - "js-yaml": "^4.1.1" + "yaml": "^2.8.2" }, "devDependencies": { - "@types/js-yaml": "^4.0.9", "@types/node": "^20.19.9", "tsx": "^4.21.0", "typescript": "^5.9.3" @@ -456,13 +455,6 @@ "node": ">=18" } }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "20.19.35", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.35.tgz", @@ -473,12 +465,6 @@ "undici-types": "~6.21.0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, "node_modules/esbuild": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", @@ -549,18 +535,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -611,6 +585,21 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } } } } diff --git a/pr-checks/package.json b/pr-checks/package.json index c21fc557f..b323b98b8 100644 --- a/pr-checks/package.json +++ b/pr-checks/package.json @@ -2,12 +2,11 @@ "private": true, "description": "Dependencies for the sync.ts", "dependencies": { - "js-yaml": "^4.1.1" + "yaml": "^2.8.2" }, "devDependencies": { - "tsx": "^4.21.0", - "typescript": "^5.9.3", "@types/node": "^20.19.9", - "@types/js-yaml": "^4.0.9" + "tsx": "^4.21.0", + "typescript": "^5.9.3" } } diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 5630e5216..35fdc5a16 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import * as path from "path"; -import * as yaml from "js-yaml"; +import * as yaml from "yaml"; /** * Represents workflow input definitions. @@ -84,30 +84,31 @@ const CHECKS_DIR = path.join(THIS_DIR, "checks"); const OUTPUT_DIR = path.join(THIS_DIR, "new-output"); /** - * Loads and parses a YAML file as a `Specification`. + * Loads and parses a YAML file. */ -function loadYaml(filePath: string): Specification { +function loadYaml(filePath: string): yaml.Document { const content = fs.readFileSync(filePath, "utf8"); - return yaml.load(content) as Specification; + return yaml.parseDocument(content); } /** * Serialize a value to YAML and write it to a file, prepended with the * standard header comment. */ -function writeYaml(filePath: string, data: any): void { +function writeYaml(filePath: string, workflow: any): void { const header = `# Warning: This file is generated automatically, and should not be modified. # Instead, please modify the template in the pr-checks directory and run: # pr-checks/sync.sh # to regenerate this file. `; - const yamlStr = yaml.dump(data, { - indent: 2, - lineWidth: -1, // Don't wrap long lines - noRefs: true, // Don't use YAML anchors/aliases - quotingType: "'", // Use single quotes where quoting is needed - forceQuotes: false, + const workflowDoc = new yaml.Document(workflow, { + aliasDuplicateObjects: false, + }); + const yamlStr = yaml.stringify(workflowDoc, { + aliasDuplicateObjects: false, + singleQuote: true, + lineWidth: 0, }); fs.writeFileSync(filePath, stripTrailingWhitespace(header + yamlStr), "utf8"); } @@ -156,7 +157,8 @@ function main(): void { for (const file of checkFiles) { const checkName = path.basename(file, ".yml"); - const checkSpecification = loadYaml(file); + const specDocument = loadYaml(file); + const checkSpecification = specDocument.toJS() as Specification; console.log(`Processing: ${checkName} — "${checkSpecification.name}"`); @@ -361,7 +363,9 @@ function main(): void { }); } - steps.push(...checkSpecification.steps); + // Extract the sequence of steps from the YAML document to persist as much formatting as possible. + const specSteps = specDocument.get("steps") as yaml.YAMLSeq; + specSteps.items.unshift(...steps); const checkJob: Record = { strategy: { @@ -378,7 +382,7 @@ function main(): void { }, "timeout-minutes": 45, "runs-on": "${{ matrix.os }}", - steps, + steps: specSteps, }; if (checkSpecification.permissions) { @@ -414,6 +418,9 @@ function main(): void { extraGroupName += "-${{inputs." + inputName + "}}"; } + const cron = new yaml.Scalar("0 5 * * *"); + cron.type = yaml.Scalar.QUOTE_SINGLE; + const workflow = { name: `PR Check - ${checkSpecification.name}`, env: { @@ -430,7 +437,7 @@ function main(): void { merge_group: { types: ["checks_requested"], }, - schedule: [{ cron: "0 5 * * *" }], + schedule: [{ cron }], workflow_dispatch: { inputs: workflowInputs, },