forked from baron/baron-sso
코드체크 결과 README에 뱃지로 추가
This commit is contained in:
@@ -2,7 +2,9 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const repoRoot = process.cwd();
|
||||
const packages = ["adminfront", "devfront", "orgfront"];
|
||||
const defaultPackages = ["adminfront", "devfront", "orgfront"];
|
||||
const packages = process.argv.slice(2);
|
||||
const targetPackages = packages.length > 0 ? packages : defaultPackages;
|
||||
|
||||
function formatPct(value) {
|
||||
return typeof value === "number" ? `${value.toFixed(2)}%` : "n/a";
|
||||
@@ -63,7 +65,7 @@ function renderMarkdown(rows) {
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
for (const packageName of packages) {
|
||||
for (const packageName of targetPackages) {
|
||||
rows.push(await readCoverageSummary(packageName));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
||||
import { mkdir, readdir, readFile, unlink, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const repoRoot = process.cwd();
|
||||
@@ -6,78 +6,124 @@ const badgeDir = path.join(repoRoot, "docs", "badges");
|
||||
const manifestPath = path.join(badgeDir, "badges.json");
|
||||
|
||||
const resultStyles = {
|
||||
success: { message: "passing", color: "#2ea043" },
|
||||
failure: { message: "failing", color: "#cf222e" },
|
||||
cancelled: { message: "cancelled", color: "#bf8700" },
|
||||
skipped: { message: "skipped", color: "#6e7781" },
|
||||
unknown: { message: "unknown", color: "#6e7781" },
|
||||
success: { message: "passing", color: "#2ea043" },
|
||||
failure: { message: "failing", color: "#cf222e" },
|
||||
cancelled: { message: "cancelled", color: "#bf8700" },
|
||||
skipped: { message: "skipped", color: "#6e7781" },
|
||||
unknown: { message: "unknown", color: "#6e7781" },
|
||||
};
|
||||
|
||||
const badgeDefinitions = {
|
||||
"dev-sha": { label: "dev", message: "unknown", color: "#0969da" },
|
||||
"code-check": { label: "code check", message: "unknown", color: "#6e7781" },
|
||||
biome: { label: "biome", message: "unknown", color: "#6e7781" },
|
||||
"userfront-e2e-fast": {
|
||||
label: "userfront e2e fast",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
"userfront-e2e-full": {
|
||||
label: "userfront e2e full",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
"adminfront-coverage": {
|
||||
label: "adminfront coverage",
|
||||
message: "38.89%",
|
||||
color: "#bf8700",
|
||||
},
|
||||
"devfront-coverage": {
|
||||
label: "devfront coverage",
|
||||
message: "8.87%",
|
||||
color: "#cf222e",
|
||||
},
|
||||
"orgfront-coverage": {
|
||||
label: "orgfront coverage",
|
||||
message: "37.50%",
|
||||
color: "#bf8700",
|
||||
},
|
||||
"dev-sha": { label: "dev", message: "unknown", color: "#0969da" },
|
||||
"code-check": { label: "code check", message: "unknown", color: "#6e7781" },
|
||||
biome: { label: "biome", message: "unknown", color: "#6e7781" },
|
||||
"backend-tests": {
|
||||
label: "backend",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
userfront: {
|
||||
label: "userfront",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
adminfront: {
|
||||
label: "adminfront",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
devfront: {
|
||||
label: "devfront",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
orgfront: {
|
||||
label: "orgfront",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
"userfront-chrome": {
|
||||
label: "chrome",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
"userfront-firefox": {
|
||||
label: "firefox",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
"userfront-safari": {
|
||||
label: "safari",
|
||||
message: "unknown",
|
||||
color: "#6e7781",
|
||||
},
|
||||
};
|
||||
|
||||
const deprecatedBadgeKeys = [
|
||||
"userfront-e2e-fast",
|
||||
"userfront-e2e-full",
|
||||
"adminfront-e2e",
|
||||
"devfront-e2e",
|
||||
"orgfront-e2e",
|
||||
"userfront-coverage",
|
||||
"adminfront-coverage",
|
||||
"devfront-coverage",
|
||||
"orgfront-coverage",
|
||||
];
|
||||
|
||||
function normalizeResult(result) {
|
||||
return resultStyles[result] ? result : "unknown";
|
||||
return resultStyles[result] ? result : "unknown";
|
||||
}
|
||||
|
||||
function styleForResult(result) {
|
||||
return resultStyles[normalizeResult(result)];
|
||||
return resultStyles[normalizeResult(result)];
|
||||
}
|
||||
|
||||
function compactResult(result) {
|
||||
const normalized = normalizeResult(result);
|
||||
return {
|
||||
success: "pass",
|
||||
failure: "fail",
|
||||
cancelled: "cancel",
|
||||
skipped: "skip",
|
||||
unknown: "unknown",
|
||||
}[normalized];
|
||||
}
|
||||
|
||||
function colorForParts(parts) {
|
||||
const normalized = parts.map(normalizeResult);
|
||||
if (normalized.includes("failure")) return resultStyles.failure.color;
|
||||
if (normalized.includes("cancelled")) return resultStyles.cancelled.color;
|
||||
if (normalized.every((part) => part === "success")) return resultStyles.success.color;
|
||||
return resultStyles.unknown.color;
|
||||
}
|
||||
|
||||
function colorForCoverage(percent) {
|
||||
if (percent >= 80) return "#2ea043";
|
||||
if (percent >= 35) return "#bf8700";
|
||||
return "#cf222e";
|
||||
if (percent >= 80) return "#2ea043";
|
||||
if (percent >= 35) return "#bf8700";
|
||||
return "#cf222e";
|
||||
}
|
||||
|
||||
function escapeXml(value) {
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
|
||||
function textWidth(text) {
|
||||
return Math.max(38, Math.ceil(String(text).length * 6.8 + 10));
|
||||
return Math.max(38, Math.ceil(String(text).length * 6.8 + 10));
|
||||
}
|
||||
|
||||
function renderBadge({ label, message, color }) {
|
||||
const labelWidth = textWidth(label);
|
||||
const messageWidth = textWidth(message);
|
||||
const width = labelWidth + messageWidth;
|
||||
const labelCenter = labelWidth / 2;
|
||||
const messageCenter = labelWidth + messageWidth / 2;
|
||||
const labelWidth = textWidth(label);
|
||||
const messageWidth = textWidth(message);
|
||||
const width = labelWidth + messageWidth;
|
||||
const labelCenter = labelWidth / 2;
|
||||
const messageCenter = labelWidth + messageWidth / 2;
|
||||
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="20" role="img" aria-label="${escapeXml(label)}: ${escapeXml(message)}">
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="20" role="img" aria-label="${escapeXml(label)}: ${escapeXml(message)}">
|
||||
<title>${escapeXml(label)}: ${escapeXml(message)}</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
@@ -100,151 +146,284 @@ function renderBadge({ label, message, color }) {
|
||||
}
|
||||
|
||||
async function readJsonIfExists(filePath) {
|
||||
try {
|
||||
return JSON.parse(await readFile(filePath, "utf8"));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(await readFile(filePath, "utf8"));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function findCoverageSummary(directory) {
|
||||
const entries = await readdir(directory, { withFileTypes: true }).catch(
|
||||
() => [],
|
||||
);
|
||||
async function findCoverageSummaries(directory) {
|
||||
const entries = await readdir(directory, { withFileTypes: true }).catch(
|
||||
() => [],
|
||||
);
|
||||
const results = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
const entryPath = path.join(directory, entry.name);
|
||||
if (entry.isFile() && entry.name === "vitest-coverage-summary.json") {
|
||||
return entryPath;
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
const found = await findCoverageSummary(entryPath);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const entryPath = path.join(directory, entry.name);
|
||||
if (entry.isFile() && entry.name === "vitest-coverage-summary.json") {
|
||||
results.push(entryPath);
|
||||
continue;
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
results.push(...(await findCoverageSummaries(entryPath)));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return results;
|
||||
}
|
||||
|
||||
function updateResultBadge(manifest, key, result) {
|
||||
const style = styleForResult(result);
|
||||
manifest.badges[key] = {
|
||||
...(manifest.badges[key] ?? badgeDefinitions[key]),
|
||||
message: style.message,
|
||||
color: style.color,
|
||||
};
|
||||
const style = styleForResult(result);
|
||||
manifest.badges[key] = {
|
||||
...(manifest.badges[key] ?? badgeDefinitions[key]),
|
||||
message: style.message,
|
||||
color: style.color,
|
||||
};
|
||||
}
|
||||
|
||||
function updateCoverageBadges(manifest, coverageSummary) {
|
||||
for (const row of coverageSummary.packages ?? []) {
|
||||
const key = `${row.package}-coverage`;
|
||||
if (!badgeDefinitions[key]) continue;
|
||||
const statements = Number(row.statements);
|
||||
manifest.badges[key] = {
|
||||
...(manifest.badges[key] ?? badgeDefinitions[key]),
|
||||
message: `${statements.toFixed(2)}%`,
|
||||
color: colorForCoverage(statements),
|
||||
};
|
||||
}
|
||||
function updateCompactResultBadge(manifest, key, result) {
|
||||
const style = styleForResult(result);
|
||||
manifest.badges[key] = {
|
||||
...(manifest.badges[key] ?? badgeDefinitions[key]),
|
||||
label: badgeDefinitions[key]?.label ?? manifest.badges[key]?.label,
|
||||
message: compactResult(result),
|
||||
color: style.color,
|
||||
};
|
||||
}
|
||||
|
||||
function coveragePart(result, statements) {
|
||||
const normalized = normalizeResult(result);
|
||||
if (normalized !== "success") {
|
||||
return {
|
||||
message: compactResult(normalized),
|
||||
color: styleForResult(normalized).color,
|
||||
result: normalized,
|
||||
};
|
||||
}
|
||||
const value = Number(statements);
|
||||
if (!Number.isFinite(value)) {
|
||||
return {
|
||||
message: "unknown",
|
||||
color: resultStyles.unknown.color,
|
||||
result: "unknown",
|
||||
};
|
||||
}
|
||||
return {
|
||||
message: `${value.toFixed(2)}%`,
|
||||
color: colorForCoverage(value),
|
||||
result: "success",
|
||||
};
|
||||
}
|
||||
|
||||
function updatePackageBadge(manifest, key, testResult, coverageResult, statements) {
|
||||
if (!badgeDefinitions[key]) return;
|
||||
const test = normalizeResult(testResult);
|
||||
const coverage = coveragePart(coverageResult, statements);
|
||||
manifest.badges[key] = {
|
||||
...(manifest.badges[key] ?? badgeDefinitions[key]),
|
||||
label: badgeDefinitions[key].label,
|
||||
message: `${compactResult(test)} | ${coverage.message}`,
|
||||
color: test === "failure" || coverage.result === "failure"
|
||||
? resultStyles.failure.color
|
||||
: test === "cancelled" || coverage.result === "cancelled"
|
||||
? resultStyles.cancelled.color
|
||||
: coverage.result === "success"
|
||||
? coverage.color
|
||||
: colorForParts([test, coverage.result]),
|
||||
};
|
||||
}
|
||||
|
||||
function updateBrowserBadge(manifest, key, desktopResult, mobileResult) {
|
||||
if (!badgeDefinitions[key]) return;
|
||||
const desktop = normalizeResult(desktopResult);
|
||||
const mobile = normalizeResult(mobileResult);
|
||||
manifest.badges[key] = {
|
||||
...(manifest.badges[key] ?? badgeDefinitions[key]),
|
||||
label: badgeDefinitions[key].label,
|
||||
message: `${compactResult(desktop)} | ${compactResult(mobile)}`,
|
||||
color: colorForParts([desktop, mobile]),
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeManifestForComparison(value) {
|
||||
return {
|
||||
...value,
|
||||
updatedAt: null,
|
||||
source: {
|
||||
...(value?.source ?? {}),
|
||||
runId: null,
|
||||
runNumber: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function manifestsMatchIgnoringRunMetadata(left, right) {
|
||||
return (
|
||||
JSON.stringify(normalizeManifestForComparison(left)) ===
|
||||
JSON.stringify(normalizeManifestForComparison(right))
|
||||
);
|
||||
}
|
||||
|
||||
function shortSha(value) {
|
||||
return String(value ?? "").trim().slice(0, 12);
|
||||
return String(value ?? "")
|
||||
.trim()
|
||||
.slice(0, 12);
|
||||
}
|
||||
|
||||
const existingManifest = process.env.RESET_BADGES === "true"
|
||||
? null
|
||||
: await readJsonIfExists(manifestPath);
|
||||
const sourceSha = shortSha(process.env.BADGE_SOURCE_SHA || process.env.GITHUB_SHA);
|
||||
const existingManifest =
|
||||
process.env.RESET_BADGES === "true"
|
||||
? null
|
||||
: await readJsonIfExists(manifestPath);
|
||||
const sourceSha = shortSha(
|
||||
process.env.BADGE_SOURCE_SHA || process.env.GITHUB_SHA,
|
||||
);
|
||||
const manifest = {
|
||||
schemaVersion: 1,
|
||||
generatedBy: "scripts/update_code_check_badges.mjs",
|
||||
updatedAt: new Date().toISOString(),
|
||||
source: {
|
||||
branch: process.env.BADGE_SOURCE_BRANCH || "dev",
|
||||
sha: process.env.BADGE_SOURCE_SHA || process.env.GITHUB_SHA || null,
|
||||
shortSha: sourceSha || null,
|
||||
runId: process.env.GITHUB_RUN_ID || null,
|
||||
runNumber: process.env.GITHUB_RUN_NUMBER || null,
|
||||
},
|
||||
badges: {
|
||||
...badgeDefinitions,
|
||||
...(existingManifest?.badges ?? {}),
|
||||
},
|
||||
schemaVersion: 1,
|
||||
generatedBy: "scripts/update_code_check_badges.mjs",
|
||||
updatedAt: new Date().toISOString(),
|
||||
source: {
|
||||
branch: process.env.BADGE_SOURCE_BRANCH || "dev",
|
||||
sha: process.env.BADGE_SOURCE_SHA || process.env.GITHUB_SHA || null,
|
||||
shortSha: sourceSha || null,
|
||||
runId: process.env.GITHUB_RUN_ID || null,
|
||||
runNumber: process.env.GITHUB_RUN_NUMBER || null,
|
||||
},
|
||||
badges: {
|
||||
...badgeDefinitions,
|
||||
...(existingManifest?.badges ?? {}),
|
||||
},
|
||||
};
|
||||
for (const key of deprecatedBadgeKeys) {
|
||||
delete manifest.badges[key];
|
||||
}
|
||||
|
||||
manifest.badges["dev-sha"] = {
|
||||
...badgeDefinitions["dev-sha"],
|
||||
message: sourceSha || "unknown",
|
||||
...badgeDefinitions["dev-sha"],
|
||||
message: sourceSha || "unknown",
|
||||
};
|
||||
|
||||
const jobResults = {
|
||||
lint: process.env.LINT_RESULT,
|
||||
biome: process.env.BIOME_RESULT,
|
||||
backend: process.env.BACKEND_RESULT,
|
||||
userfront: process.env.USERFRONT_RESULT,
|
||||
userfrontE2e: process.env.USERFRONT_E2E_RESULT,
|
||||
coverage: process.env.COVERAGE_RESULT,
|
||||
adminfront: process.env.ADMINFRONT_RESULT,
|
||||
devfront: process.env.DEVFRONT_RESULT,
|
||||
orgfront: process.env.ORGFRONT_RESULT,
|
||||
lint: process.env.LINT_RESULT,
|
||||
biome: process.env.BIOME_RESULT,
|
||||
backend: process.env.BACKEND_RESULT,
|
||||
userfront: process.env.USERFRONT_RESULT,
|
||||
userfrontE2e: process.env.USERFRONT_E2E_RESULT,
|
||||
adminfront: process.env.ADMINFRONT_RESULT,
|
||||
devfront: process.env.DEVFRONT_RESULT,
|
||||
orgfront: process.env.ORGFRONT_RESULT,
|
||||
};
|
||||
const e2eWasFull = process.env.USERFRONT_E2E_FULL === "true";
|
||||
const userfrontFastResult = e2eWasFull ? undefined : jobResults.userfrontE2e;
|
||||
const browserResults = {
|
||||
chrome: {
|
||||
desktop: process.env.USERFRONT_E2E_CHROMIUM_DESKTOP_RESULT,
|
||||
mobile: process.env.USERFRONT_E2E_CHROMIUM_MOBILE_RESULT,
|
||||
},
|
||||
firefox: {
|
||||
desktop: process.env.USERFRONT_E2E_FIREFOX_DESKTOP_RESULT,
|
||||
mobile: process.env.USERFRONT_E2E_FIREFOX_MOBILE_RESULT,
|
||||
},
|
||||
safari: {
|
||||
desktop: process.env.USERFRONT_E2E_WEBKIT_DESKTOP_RESULT,
|
||||
mobile: process.env.USERFRONT_E2E_WEBKIT_MOBILE_RESULT,
|
||||
},
|
||||
};
|
||||
|
||||
const overallResults = Object.values(jobResults).filter(Boolean);
|
||||
const legacyCoverageResult = process.env.COVERAGE_RESULT;
|
||||
const coverageJobResults = {
|
||||
userfront: process.env.USERFRONT_COVERAGE_RESULT,
|
||||
adminfront: process.env.ADMINFRONT_COVERAGE_RESULT || legacyCoverageResult,
|
||||
devfront: process.env.DEVFRONT_COVERAGE_RESULT || legacyCoverageResult,
|
||||
orgfront: process.env.ORGFRONT_COVERAGE_RESULT || legacyCoverageResult,
|
||||
};
|
||||
|
||||
const overallResults = [
|
||||
...Object.values(jobResults),
|
||||
...Object.values(coverageJobResults),
|
||||
...Object.values(browserResults).flatMap((result) => [
|
||||
result.desktop,
|
||||
result.mobile,
|
||||
]),
|
||||
].filter(Boolean);
|
||||
const hasFailure = overallResults.some((result) =>
|
||||
["failure", "cancelled"].includes(result),
|
||||
["failure", "cancelled"].includes(result),
|
||||
);
|
||||
const allSkipped = overallResults.length > 0 &&
|
||||
overallResults.every((result) => result === "skipped");
|
||||
const allSkipped =
|
||||
overallResults.length > 0 &&
|
||||
overallResults.every((result) => result === "skipped");
|
||||
if (process.env.BADGE_UPDATE_CODE_CHECK !== "false") {
|
||||
updateResultBadge(
|
||||
manifest,
|
||||
"code-check",
|
||||
overallResults.length === 0
|
||||
? "unknown"
|
||||
: hasFailure
|
||||
? "failure"
|
||||
: allSkipped
|
||||
? "skipped"
|
||||
: "success",
|
||||
);
|
||||
updateResultBadge(
|
||||
manifest,
|
||||
"code-check",
|
||||
overallResults.length === 0
|
||||
? "unknown"
|
||||
: hasFailure
|
||||
? "failure"
|
||||
: allSkipped
|
||||
? "skipped"
|
||||
: "success",
|
||||
);
|
||||
}
|
||||
|
||||
updateResultBadge(manifest, "biome", jobResults.biome);
|
||||
updateCompactResultBadge(manifest, "backend-tests", jobResults.backend);
|
||||
|
||||
const e2eWasFull = process.env.USERFRONT_E2E_FULL === "true";
|
||||
if (jobResults.userfrontE2e && jobResults.userfrontE2e !== "skipped") {
|
||||
updateResultBadge(
|
||||
manifest,
|
||||
e2eWasFull ? "userfront-e2e-full" : "userfront-e2e-fast",
|
||||
jobResults.userfrontE2e,
|
||||
);
|
||||
const coverageSummaries = process.env.COVERAGE_SUMMARY_PATH
|
||||
? [process.env.COVERAGE_SUMMARY_PATH]
|
||||
: await findCoverageSummaries(path.join(repoRoot, "badge-artifacts"));
|
||||
const coverageByPackage = new Map();
|
||||
for (const summaryPath of coverageSummaries) {
|
||||
const coverageSummary = await readJsonIfExists(summaryPath);
|
||||
for (const row of coverageSummary?.packages ?? []) {
|
||||
coverageByPackage.set(row.package, row.statements);
|
||||
}
|
||||
}
|
||||
|
||||
if (jobResults.coverage === "failure" || jobResults.coverage === "cancelled") {
|
||||
for (const key of [
|
||||
"adminfront-coverage",
|
||||
"devfront-coverage",
|
||||
"orgfront-coverage",
|
||||
]) {
|
||||
updateResultBadge(manifest, key, "failure");
|
||||
}
|
||||
} else {
|
||||
const coverageSummaryPath = process.env.COVERAGE_SUMMARY_PATH ||
|
||||
(await findCoverageSummary(path.join(repoRoot, "badge-artifacts")));
|
||||
const coverageSummary = coverageSummaryPath
|
||||
? await readJsonIfExists(coverageSummaryPath)
|
||||
: null;
|
||||
if (coverageSummary) {
|
||||
updateCoverageBadges(manifest, coverageSummary);
|
||||
}
|
||||
for (const [key, testResult, coverageResult] of [
|
||||
["userfront", userfrontFastResult, coverageJobResults.userfront],
|
||||
["adminfront", jobResults.adminfront, coverageJobResults.adminfront],
|
||||
["devfront", jobResults.devfront, coverageJobResults.devfront],
|
||||
["orgfront", jobResults.orgfront, coverageJobResults.orgfront],
|
||||
]) {
|
||||
if (testResult || coverageResult) {
|
||||
updatePackageBadge(
|
||||
manifest,
|
||||
key,
|
||||
testResult,
|
||||
coverageResult,
|
||||
coverageByPackage.get(key),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [browser, result] of Object.entries(browserResults)) {
|
||||
if (result.desktop || result.mobile) {
|
||||
updateBrowserBadge(
|
||||
manifest,
|
||||
`userfront-${browser}`,
|
||||
result.desktop,
|
||||
result.mobile,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
existingManifest &&
|
||||
manifestsMatchIgnoringRunMetadata(manifest, existingManifest)
|
||||
) {
|
||||
manifest.updatedAt = existingManifest.updatedAt;
|
||||
manifest.source = existingManifest.source ?? manifest.source;
|
||||
}
|
||||
|
||||
await mkdir(badgeDir, { recursive: true });
|
||||
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
|
||||
for (const [key, badge] of Object.entries(manifest.badges)) {
|
||||
await writeFile(path.join(badgeDir, `${key}.svg`), renderBadge(badge));
|
||||
await writeFile(path.join(badgeDir, `${key}.svg`), renderBadge(badge));
|
||||
}
|
||||
for (const key of deprecatedBadgeKeys) {
|
||||
await unlink(path.join(badgeDir, `${key}.svg`)).catch(() => {});
|
||||
}
|
||||
|
||||
console.log(`Updated ${Object.keys(manifest.badges).length} badge files.`);
|
||||
|
||||
Reference in New Issue
Block a user