@mertushka/webrtc-node 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const root = path.resolve(__dirname, "..");
7
+ const args = process.argv.slice(2);
8
+ const outputIndex = args.indexOf("--output");
9
+ const resultsIndex = args.indexOf("--results");
10
+ const outputPath =
11
+ outputIndex === -1
12
+ ? path.join(root, "ci-evidence.json")
13
+ : path.resolve(root, args[outputIndex + 1] || "");
14
+ const resultsPath =
15
+ resultsIndex === -1
16
+ ? process.env.WPT_RESULTS || path.join(root, "wpt-results.json")
17
+ : path.resolve(root, args[resultsIndex + 1] || "");
18
+ const manifestPath = path.join(root, "wpt-manifest.json");
19
+
20
+ function fail(message) {
21
+ console.error(`CI evidence failed: ${message}`);
22
+ process.exit(1);
23
+ }
24
+
25
+ function readJson(file) {
26
+ try {
27
+ return JSON.parse(fs.readFileSync(file, "utf8"));
28
+ } catch (error) {
29
+ fail(`could not read ${file}: ${error.message}`);
30
+ }
31
+ }
32
+
33
+ if (outputIndex !== -1 && !args[outputIndex + 1]) fail("--output requires a path");
34
+ if (resultsIndex !== -1 && !args[resultsIndex + 1]) fail("--results requires a path");
35
+ if (!fs.existsSync(resultsPath)) fail(`${resultsPath} does not exist`);
36
+ if (!fs.existsSync(manifestPath)) fail(`${manifestPath} does not exist`);
37
+
38
+ const manifest = readJson(manifestPath);
39
+ const results = readJson(resultsPath);
40
+
41
+ if (!Array.isArray(results.results)) fail(`${resultsPath} is not a WPT result artifact`);
42
+ if (results.results.length !== results.total) {
43
+ fail(`result length ${results.results.length} does not match total ${results.total}`);
44
+ }
45
+
46
+ const pass = results.results.filter((result) => result.status === "PASS").length;
47
+ const failCount = results.results.filter((result) => result.status === "FAIL").length;
48
+ const retries = results.results.filter((result) => Number(result.retries) > 0).length;
49
+
50
+ if (pass !== results.pass) fail(`PASS count ${pass} does not match summary ${results.pass}`);
51
+ if (failCount !== results.fail)
52
+ fail(`FAIL count ${failCount} does not match summary ${results.fail}`);
53
+ if (manifest.expectedSelectedSubtests && results.total !== manifest.expectedSelectedSubtests) {
54
+ fail(
55
+ `result total ${results.total} does not match manifest ${manifest.expectedSelectedSubtests}`,
56
+ );
57
+ }
58
+ if (results.fail !== 0 || retries !== 0 || pass !== results.total) {
59
+ fail(
60
+ `strict WPT evidence requires all pass and no retries; pass=${pass} total=${results.total} retries=${retries}`,
61
+ );
62
+ }
63
+
64
+ const evidence = {
65
+ generatedAt: new Date().toISOString(),
66
+ source: "write-ci-evidence.js",
67
+ github: {
68
+ actions: process.env.GITHUB_ACTIONS === "true",
69
+ workflow: process.env.GITHUB_WORKFLOW || null,
70
+ job: process.env.GITHUB_JOB || null,
71
+ runId: process.env.GITHUB_RUN_ID || null,
72
+ runAttempt: process.env.GITHUB_RUN_ATTEMPT || null,
73
+ repository: process.env.GITHUB_REPOSITORY || null,
74
+ ref: process.env.GITHUB_REF || null,
75
+ sha: process.env.GITHUB_SHA || null,
76
+ },
77
+ runner: {
78
+ os: process.env.RUNNER_OS || process.platform,
79
+ arch: process.env.RUNNER_ARCH || process.arch,
80
+ imageOS: process.env.ImageOS || null,
81
+ imageVersion: process.env.ImageVersion || null,
82
+ },
83
+ node: {
84
+ version: process.version,
85
+ napi: process.versions.napi || null,
86
+ modules: process.versions.modules || null,
87
+ platform: process.platform,
88
+ arch: process.arch,
89
+ },
90
+ pins: {
91
+ libdatachannel: manifest.libdatachannelCommit || null,
92
+ wpt: manifest.wptCommit || null,
93
+ },
94
+ wpt: {
95
+ expectedSelectedSubtests: manifest.expectedSelectedSubtests ?? null,
96
+ total: results.total,
97
+ pass,
98
+ fail: failCount,
99
+ retries,
100
+ resultFiles: new Set(results.results.map((result) => result.file)).size,
101
+ },
102
+ gates: [
103
+ "npm ci",
104
+ "npm run native:check",
105
+ "npm run build",
106
+ "npm test",
107
+ "npm run api:check",
108
+ "npm run types:check",
109
+ "npm run wpt:ensure",
110
+ "npm run wpt:selection:check",
111
+ "npm run wpt:test",
112
+ "npm run wpt:check:strict",
113
+ "npm run wpt:report",
114
+ ],
115
+ };
116
+
117
+ fs.writeFileSync(outputPath, `${JSON.stringify(evidence, null, 2)}\n`);
118
+ console.log(`CI evidence written to ${path.relative(root, outputPath) || outputPath}`);
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const root = path.resolve(__dirname, "..");
7
+ const args = process.argv.slice(2);
8
+ const outputIndex = args.indexOf("--output");
9
+ const resultsIndex = args.indexOf("--results");
10
+ const expectedTotalIndex = args.indexOf("--expected-total");
11
+ const outputPath =
12
+ outputIndex === -1
13
+ ? path.join(root, "wpt-report.md")
14
+ : path.resolve(root, args[outputIndex + 1] || "");
15
+ const resultsPath =
16
+ resultsIndex === -1
17
+ ? process.env.WPT_RESULTS || path.join(root, "wpt-results.json")
18
+ : path.resolve(root, args[resultsIndex + 1] || "");
19
+ const manifestPath = path.join(root, "wpt-manifest.json");
20
+
21
+ function fail(message) {
22
+ console.error(`WPT report failed: ${message}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ if (outputIndex !== -1 && !args[outputIndex + 1]) fail("--output requires a path");
27
+ if (resultsIndex !== -1 && !args[resultsIndex + 1]) fail("--results requires a path");
28
+ if (expectedTotalIndex !== -1 && !args[expectedTotalIndex + 1]) {
29
+ fail("--expected-total requires a positive integer");
30
+ }
31
+ if (!fs.existsSync(resultsPath)) fail(`${resultsPath} does not exist`);
32
+ if (!fs.existsSync(manifestPath)) fail(`${manifestPath} does not exist`);
33
+
34
+ const results = JSON.parse(fs.readFileSync(resultsPath, "utf8"));
35
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
36
+ const expectedTotal = process.env.WPT_EXPECTED_TOTAL
37
+ ? Number(process.env.WPT_EXPECTED_TOTAL)
38
+ : expectedTotalIndex === -1
39
+ ? (manifest.expectedSelectedSubtests ?? null)
40
+ : Number(args[expectedTotalIndex + 1]);
41
+
42
+ if (!Array.isArray(results.results)) fail(`${resultsPath} is not a WPT result artifact`);
43
+ if (!Number.isInteger(results.total)) fail("WPT result total is missing");
44
+ if (results.results.length !== results.total) {
45
+ fail(`result length ${results.results.length} does not match total ${results.total}`);
46
+ }
47
+ if (expectedTotal !== null) {
48
+ if (!Number.isInteger(expectedTotal) || expectedTotal < 1) {
49
+ fail("expected total must be a positive integer");
50
+ }
51
+ if (results.total !== expectedTotal) {
52
+ fail(`result total ${results.total} does not match expected total ${expectedTotal}`);
53
+ }
54
+ }
55
+
56
+ const pass = results.results.filter((result) => result.status === "PASS").length;
57
+ const failCount = results.results.filter((result) => result.status === "FAIL").length;
58
+ const retried = results.results.filter((result) => Number(result.retries) > 0);
59
+ const files = new Set(results.results.map((result) => result.file));
60
+ const generatedAt = new Date().toISOString();
61
+
62
+ if (pass !== results.pass) fail(`PASS count ${pass} does not match summary ${results.pass}`);
63
+ if (failCount !== results.fail)
64
+ fail(`FAIL count ${failCount} does not match summary ${results.fail}`);
65
+
66
+ const lines = [];
67
+ lines.push("# WPT Conformance Report");
68
+ lines.push("");
69
+ lines.push(`Generated: ${generatedAt}`);
70
+ lines.push("");
71
+ lines.push("## Summary");
72
+ lines.push("");
73
+ lines.push("| Metric | Value |");
74
+ lines.push("| --- | ---: |");
75
+ lines.push(`| Selected subtests | ${results.total} |`);
76
+ lines.push(`| Passing subtests | ${pass} |`);
77
+ lines.push(`| Failing subtests | ${failCount} |`);
78
+ lines.push(`| Retried subtests | ${retried.length} |`);
79
+ lines.push(`| Result files | ${files.size} |`);
80
+ lines.push(`| Expected subtests | ${expectedTotal ?? "n/a"} |`);
81
+ lines.push("");
82
+ lines.push("## Pins");
83
+ lines.push("");
84
+ lines.push("| Dependency | Commit |");
85
+ lines.push("| --- | --- |");
86
+ lines.push(`| libdatachannel | \`${manifest.libdatachannelCommit || "n/a"}\` |`);
87
+ lines.push(`| web-platform-tests | \`${manifest.wptCommit || "n/a"}\` |`);
88
+ lines.push("");
89
+ lines.push("## Manifest Groups");
90
+ lines.push("");
91
+ lines.push("| Group | Entries |");
92
+ lines.push("| --- | ---: |");
93
+ for (const [group, entries] of Object.entries(manifest)) {
94
+ if (Array.isArray(entries)) lines.push(`| ${group} | ${entries.length} |`);
95
+ }
96
+ lines.push("");
97
+
98
+ if (failCount > 0) {
99
+ lines.push("## Failures");
100
+ lines.push("");
101
+ for (const result of results.results.filter((entry) => entry.status === "FAIL")) {
102
+ lines.push(`- ${result.file} :: ${result.name}${result.message ? ` - ${result.message}` : ""}`);
103
+ }
104
+ lines.push("");
105
+ }
106
+
107
+ if (retried.length > 0) {
108
+ lines.push("## Retries");
109
+ lines.push("");
110
+ for (const result of retried) {
111
+ lines.push(`- ${result.file} :: ${result.name} (${result.retries})`);
112
+ if (Array.isArray(result.retryAttempts)) {
113
+ for (const [index, attempt] of result.retryAttempts.entries()) {
114
+ const reason =
115
+ attempt.output ||
116
+ attempt.error ||
117
+ attempt.failures
118
+ ?.map((failure) => failure.message)
119
+ .filter(Boolean)
120
+ .join("; ") ||
121
+ `exitCode=${attempt.exitCode ?? "null"} signal=${attempt.signal ?? "null"}`;
122
+ lines.push(` - attempt ${index + 1}: ${String(reason).split(/\r?\n/)[0]}`);
123
+ }
124
+ }
125
+ }
126
+ lines.push("");
127
+ }
128
+
129
+ lines.push("## Expected-Pass Selection");
130
+ lines.push("");
131
+ for (const entry of manifest.expectedPass || []) {
132
+ lines.push(`- ${entry}`);
133
+ }
134
+ lines.push("");
135
+
136
+ const report = `${lines.join("\n")}\n`;
137
+ fs.writeFileSync(outputPath, report);
138
+
139
+ if (process.env.GITHUB_STEP_SUMMARY && process.env.WPT_REPORT_STEP_SUMMARY !== "0") {
140
+ fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, report);
141
+ }
142
+
143
+ console.log(`WPT report written to ${path.relative(root, outputPath) || outputPath}`);