feat(WP7-07): 增加最终发布冻结与泄漏扫描
Dada P0-A isolated Windows CI / validate-and-package (push) Canceled after 0s

This commit is contained in:
suyx
2026-08-04 23:03:11 +08:00
parent 08e9c39e49
commit ad86b4ddcc
5 changed files with 334 additions and 14 deletions
+31 -13
View File
@@ -208,7 +208,7 @@ async function waitForHealth(child) {
throw new Error("Packaged API did not become healthy on fixed port 43121.", { cause: lastError });
}
async function verifyExtractedPackage(zipPath, packageName) {
async function verifyExtractedPackage(zipPath, packageName, expectedSupport) {
const extractRoot = mkdtempSync(join(tmpdir(), "dada-wp0-09-"));
try {
const escapedZip = zipPath.replaceAll("'", "''");
@@ -237,19 +237,21 @@ async function verifyExtractedPackage(zipPath, packageName) {
const health = await waitForHealth(api);
const releaseGate = await fetch(`http://127.0.0.1:${fixedPort}/api/v1/support/check`, {
body: JSON.stringify({
brands: [{ brand: "Google Chrome", version: "150" }],
full_version_list: [{ brand: "Google Chrome", version: "150.0.0.0" }],
brands: [{ brand: expectedSupport.brand, version: String(expectedSupport.major) }],
full_version_list: [{ brand: expectedSupport.brand, version: expectedSupport.fullVersion }],
platform: "Windows",
}),
headers: {
"content-type": "application/json",
"sec-ch-ua": '"Google Chrome";v="150"',
"sec-ch-ua-full-version-list": '"Google Chrome";v="150.0.0.0"',
"sec-ch-ua": `"${expectedSupport.brand}";v="${expectedSupport.major}"`,
"sec-ch-ua-full-version-list": `"${expectedSupport.brand}";v="${expectedSupport.fullVersion}"`,
"sec-ch-ua-platform": '"Windows"',
},
method: "POST",
});
if (releaseGate.status !== 426) throw new Error(`Candidate RELEASE.json unexpectedly passed with ${releaseGate.status}.`);
if (releaseGate.status !== expectedSupport.statusCode) {
throw new Error(`Packaged RELEASE.json support gate returned ${releaseGate.status}; expected ${expectedSupport.statusCode}.`);
}
return {
api: { executable: "runtime/node.exe", health, pid: api.pid, release_gate: { status_code: releaseGate.status }, status: "passed" },
native,
@@ -291,7 +293,7 @@ function scanPackage(packageDirectory) {
return { disallowed_matches: disallowedMatches, reparse_points: reparsePoints, scanned_files: files.length, status: disallowedMatches.length === 0 && reparsePoints.length === 0 ? "passed" : "failed" };
}
export async function buildAndValidatePortablePackage({ evidenceDirectory, outputRoot }) {
export async function buildAndValidatePortablePackage({ evidenceDirectory, outputRoot, releaseRecord }) {
if (process.platform !== frozenRuntime.os || process.arch !== frozenRuntime.arch || process.version.slice(1) !== frozenRuntime.node) {
throw new Error("Portable package build requires frozen Node 24.13.0 on win-x64.");
}
@@ -351,7 +353,8 @@ export async function buildAndValidatePortablePackage({ evidenceDirectory, outpu
writeJson(join(packageDirectory, "LICENSES", "third-party.json"), { api: apiDependencies, runtime: { node: frozenRuntime.node }, schema_version: "1.0", worker: workerDependencies });
const commit = run("git", ["rev-parse", "HEAD"]);
writeJson(join(packageDirectory, "RELEASE.json"), {
const finalRelease = releaseRecord !== undefined;
writeJson(join(packageDirectory, "RELEASE.json"), releaseRecord ?? {
app_version: appVersion,
browsers: [],
build_commit: commit,
@@ -360,16 +363,20 @@ export async function buildAndValidatePortablePackage({ evidenceDirectory, outpu
windows_build: null,
});
writeFileSync(join(packageDirectory, "START-HERE.txt"), [
"Dada P0-A candidate package",
finalRelease ? "Dada P0-A first-version portable package" : "Dada P0-A candidate package",
"",
"This candidate is unsigned and is not a final P0-A release.",
finalRelease
? "This unsigned first-version package passed the local P0-A release gates recorded in RELEASE.json."
: "This candidate is unsigned and is not a final P0-A release.",
"Verify the adjacent SHA-256 file before first launch.",
"Windows SmartScreen may warn on first launch because the executable is unsigned.",
"For an antivirus alert, compare the package hash with the Gitea build record.",
"Do not disable antivirus protection, add broad exclusions, or skip hash verification.",
"To update, exit Dada from the tray and replace the complete program directory.",
"Dada uses 127.0.0.1:43121 and does not support LAN or remote access.",
"A final RELEASE.json is created only after WP-7 acceptance.",
finalRelease
? "Resend and Amap real-provider validation remain explicitly deferred and are not recorded as passed."
: "A final RELEASE.json is created only after WP-7 acceptance.",
"",
].join("\r\n"));
@@ -381,7 +388,18 @@ export async function buildAndValidatePortablePackage({ evidenceDirectory, outpu
const zipSha256 = fileSha256(zipPath);
const shaPath = `${zipPath}.sha256`;
writeFileSync(shaPath, `${zipSha256} ${basename(zipPath)}\n`);
const processTree = await verifyExtractedPackage(zipPath, packageName);
const supportBrowser = finalRelease ? releaseRecord.browsers[0] : undefined;
const processTree = await verifyExtractedPackage(zipPath, packageName, finalRelease ? {
brand: supportBrowser.brand,
fullVersion: supportBrowser.fullVersion,
major: Number.parseInt(supportBrowser.fullVersion.split(".")[0], 10),
statusCode: 200,
} : {
brand: "Google Chrome",
fullVersion: "150.0.0.0",
major: 150,
statusCode: 426,
});
const fileEntries = listFiles(packageDirectory).files.map((path) => ({
path: relative(packageDirectory, path).replaceAll("\\", "/"),
sha256: fileSha256(path),
@@ -392,7 +410,7 @@ export async function buildAndValidatePortablePackage({ evidenceDirectory, outpu
files: fileEntries,
fixed_port: fixedPort,
package_name: packageName,
release_status: "candidate_unvalidated",
release_status: finalRelease ? releaseRecord.releaseStatus : "candidate_unvalidated",
schema_version: "1.0",
zip_sha256: zipSha256,
};