Skip to content

Commit c39cd36

Browse files
DanWahlinCopilot
andcommitted
Fix Co-op Translator workflow: filter false-positive review errors
co-op-review flags `.github/**` source files as "Missing translated file" even though `translate` intentionally excludes them, failing the job. Add .github/scripts/filter-co-op-review.js to ignore findings under the intentionally-untranslated paths (.github/**, samples/skills/**) and fail only on genuine errors. Also bump deprecated actions off Node 20. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 1cee145 commit c39cd36

2 files changed

Lines changed: 106 additions & 5 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env node
2+
3+
// Runs `co-op-review` and post-filters its findings so the workflow only fails
4+
// on genuine errors.
5+
//
6+
// Why this exists: the `translate` command and the `co-op-review` command ship
7+
// with *different* exclusion lists. `translate` skips `.github/**` (it is in
8+
// Co-op Translator's EXCLUDED_DIRS), so those files are never translated. But
9+
// `co-op-review` does NOT exclude `.github/**`, so it reports every one of those
10+
// untranslated source files as a "Missing translated file" error and fails the
11+
// build. Those errors are false positives for paths this repo intentionally
12+
// leaves untranslated. The review CLI exposes no way to extend its exclusions,
13+
// so we drop findings under the excluded paths here and fail only on the rest.
14+
15+
const { spawnSync } = require("child_process");
16+
17+
// Source paths that are intentionally excluded from translation. Keep this in
18+
// sync with the excludes in .github/workflows/co-op-translator.yml and the
19+
// guidance in .github/workflows/translation-polisher.md.
20+
const EXCLUDED_PREFIXES = [".github/", "samples/skills/"];
21+
22+
const languages = process.argv
23+
.slice(2)
24+
.flatMap((value) => value.split(/\s+/))
25+
.map((value) => value.trim())
26+
.filter(Boolean);
27+
28+
if (languages.length === 0) {
29+
console.error("Usage: node .github/scripts/filter-co-op-review.js <language-codes>");
30+
process.exit(1);
31+
}
32+
33+
const result = spawnSync(
34+
"co-op-review",
35+
["-l", languages.join(" "), "--format", "github"],
36+
{ encoding: "utf8" }
37+
);
38+
39+
if (result.error && result.error.code === "ENOENT") {
40+
console.log("co-op-review is not available in the installed Co-op Translator package; skipping.");
41+
process.exit(0);
42+
}
43+
44+
const report = result.stdout || "";
45+
const stderr = result.stderr || "";
46+
47+
// Always surface the full report in the job log (and summary when available).
48+
if (report.trim()) {
49+
console.log(report.trimEnd());
50+
}
51+
if (process.env.GITHUB_STEP_SUMMARY && report.trim()) {
52+
try {
53+
require("fs").appendFileSync(process.env.GITHUB_STEP_SUMMARY, `${report.trimEnd()}\n`);
54+
} catch (err) {
55+
console.error(`Could not write review report to step summary: ${err.message}`);
56+
}
57+
}
58+
59+
const isExcluded = (filePath) =>
60+
EXCLUDED_PREFIXES.some((prefix) => filePath.startsWith(prefix));
61+
62+
const genuineErrors = [];
63+
const ignoredErrors = [];
64+
65+
for (const line of report.split("\n")) {
66+
if (!line.trimStart().startsWith("|")) {
67+
continue;
68+
}
69+
const cells = line.split("|").map((cell) => cell.trim());
70+
// cells[0] is the empty string before the leading pipe.
71+
const severity = (cells[1] || "").toLowerCase();
72+
if (severity !== "error" && severity !== "warning") {
73+
continue; // Skip the metrics table, header, and separator rows.
74+
}
75+
if (severity !== "error") {
76+
continue; // Only errors fail the build; warnings are informational.
77+
}
78+
const filePath = (cells[4] || "").replace(/`/g, "").trim();
79+
if (isExcluded(filePath)) {
80+
ignoredErrors.push(filePath);
81+
} else {
82+
genuineErrors.push({ filePath, message: cells[5] || "" });
83+
}
84+
}
85+
86+
if (ignoredErrors.length > 0) {
87+
console.log(
88+
`\nIgnored ${ignoredErrors.length} expected finding(s) for intentionally untranslated paths ` +
89+
`(${EXCLUDED_PREFIXES.join(", ")}).`
90+
);
91+
}
92+
93+
if (genuineErrors.length > 0) {
94+
console.error(`\nco-op-review found ${genuineErrors.length} genuine error(s):`);
95+
for (const { filePath, message } of genuineErrors) {
96+
console.error(` - ${filePath}: ${message}`);
97+
}
98+
if (stderr.trim()) {
99+
console.error(stderr.trimEnd());
100+
}
101+
process.exit(1);
102+
}
103+
104+
console.log("\nco-op-review passed (no genuine errors).");
105+
process.exit(0);

.github/workflows/co-op-translator.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ jobs:
8787
run: |
8888
migrate-links -l "$TRANSLATION_LANGUAGES" -y
8989
node .github/scripts/fix-translated-markdown.js "$TRANSLATION_LANGUAGES"
90-
if command -v co-op-review >/dev/null 2>&1; then
91-
co-op-review -l "$TRANSLATION_LANGUAGES" --format github
92-
else
93-
echo "co-op-review is not available in the installed Co-op Translator package; skipping."
94-
fi
90+
node .github/scripts/filter-co-op-review.js "$TRANSLATION_LANGUAGES"
9591
9692
- name: Remove excluded translations
9793
run: |

0 commit comments

Comments
 (0)