@lodestar/spec-test-util 1.49.0-dev.4d35c8b82e → 1.49.0-dev.535f5dd45f

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.
@@ -1 +1 @@
1
- {"version":3,"file":"downloadNightlyTests.d.ts","sourceRoot":"","sources":["../src/downloadNightlyTests.ts"],"names":[],"mappings":"AA0CA,wBAAsB,oBAAoB,CACxC,IAAI,EAAE;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,EAC/F,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
1
+ {"version":3,"file":"downloadNightlyTests.d.ts","sourceRoot":"","sources":["../src/downloadNightlyTests.ts"],"names":[],"mappings":"AA+EA,wBAAsB,oBAAoB,CACxC,IAAI,EAAE;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,EAC/F,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAgDf"}
@@ -1,4 +1,4 @@
1
- import { fetch } from "@lodestar/utils";
1
+ import { LodestarError, fetch, retry } from "@lodestar/utils";
2
2
  import { downloadGenericSpecTests } from "./downloadTests.js";
3
3
  async function ghApiFetch(endpoint, token) {
4
4
  const res = await fetch(`https://api.github.com${endpoint}`, {
@@ -10,35 +10,57 @@ async function ghApiFetch(endpoint, token) {
10
10
  }
11
11
  return res.json();
12
12
  }
13
- async function resolveNightlyRunId(repo, token, date, branch) {
13
+ async function resolveNightlyRun(repo, token, log, date, branch) {
14
14
  const params = new URLSearchParams({ status: "success", per_page: "1" });
15
15
  if (branch)
16
16
  params.append("branch", branch);
17
17
  // If neither branch nor date narrow the query, restrict to scheduled runs so
18
18
  // a PR's successful run on consensus-specs can't outrank the latest master
19
19
  // nightly. When a date is given, allow manual re-runs on that day too.
20
- else if (!date)
20
+ else if (date === "latest")
21
21
  params.append("event", "schedule");
22
- if (date)
23
- params.append("created", date);
24
- const { workflow_runs } = await ghApiFetch(`/repos/${repo}/actions/workflows/tests.yml/runs?${params}`, token);
25
- const runId = workflow_runs[0]?.id;
26
- if (!runId) {
27
- throw new Error(`No successful run found${date ? ` on ${date}` : ""} for ${repo}${branch ? ` (${branch})` : ""}`);
28
- }
29
- return runId;
22
+ // Require today's UTC run so upstream delays or failures surface in our nightly.
23
+ const createdFilter = (date === "latest" ? new Date() : date).toISOString().slice(0, 10);
24
+ const minCreatedAt = Date.parse(createdFilter);
25
+ const maxCreatedAt = minCreatedAt + 24 * 60 * 60 * 1000;
26
+ params.append("created", createdFilter);
27
+ return retry(async () => {
28
+ const { workflow_runs } = await ghApiFetch(`/repos/${repo}/actions/workflows/tests.yml/runs?${params}`, token);
29
+ const run = workflow_runs[0];
30
+ if (!run) {
31
+ throw new LodestarError({ code: "NIGHTLY_RUN_NOT_FOUND", repo, branch: branch ?? null, createdFilter }, `No successful run found for ${repo}${branch ? ` (${branch})` : ""} with created=${createdFilter}`);
32
+ }
33
+ // GitHub's run listing can return weeks-old results, so validate even with a date filter.
34
+ const createdAt = Date.parse(run.created_at);
35
+ if (!(createdAt >= minCreatedAt && createdAt < maxCreatedAt)) {
36
+ throw new LodestarError({
37
+ code: "NIGHTLY_RUN_OUTSIDE_DATE_RANGE",
38
+ runId: run.id,
39
+ createdAt: run.created_at ?? null,
40
+ createdFilter,
41
+ }, `Refusing nightly run ${run.id} created at ${run.created_at}: expected created=${createdFilter}`);
42
+ }
43
+ return run;
44
+ }, {
45
+ retries: 2,
46
+ retryDelay: 1000,
47
+ shouldRetry: (error) => error instanceof LodestarError,
48
+ onRetry: (error, attempt) => log(`Nightly lookup attempt ${attempt}: ${error.message}`),
49
+ });
30
50
  }
31
51
  export async function downloadNightlyTests(opts, log, date) {
32
52
  const token = process.env.GITHUB_TOKEN;
33
53
  if (!token)
34
54
  throw new Error("GITHUB_TOKEN is required for nightly downloads");
35
- const resolvedDate = date === "latest" || !date ? undefined : date;
36
- if (resolvedDate && !/^\d{4}-\d{2}-\d{2}$/.test(resolvedDate)) {
55
+ const resolvedDate = date === "latest" || !date ? "latest" : new Date(date);
56
+ if (resolvedDate !== "latest" &&
57
+ (!Number.isFinite(resolvedDate.getTime()) || resolvedDate.toISOString().slice(0, 10) !== date)) {
37
58
  throw new Error(`Invalid date: "${date}". Expected "latest" or YYYY-MM-DD`);
38
59
  }
39
60
  const repo = new URL(opts.specTestsRepoUrl).pathname.slice(1).replace(/\/$/, "");
40
- const runId = await resolveNightlyRunId(repo, token, resolvedDate, opts.branch);
41
- log(`Resolved nightly${resolvedDate ? ` ${resolvedDate}` : ""} to run ${runId}`);
61
+ const run = await resolveNightlyRun(repo, token, log, resolvedDate, opts.branch);
62
+ const runId = run.id;
63
+ log(`Resolved nightly${resolvedDate === "latest" ? "" : ` ${date}`} to run ${runId} (created_at=${run.created_at}, head_sha=${run.head_sha})`);
42
64
  const { artifacts } = await ghApiFetch(`/repos/${repo}/actions/runs/${runId}/artifacts`, token);
43
65
  const urlByTest = {};
44
66
  const available = [];
@@ -1 +1 @@
1
- {"version":3,"file":"downloadNightlyTests.js","sourceRoot":"","sources":["../src/downloadNightlyTests.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"downloadNightlyTests.js","sourceRoot":"","sources":["../src/downloadNightlyTests.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodestar/spec-test-util",
3
- "version": "1.49.0-dev.4d35c8b82e",
3
+ "version": "1.49.0-dev.535f5dd45f",
4
4
  "description": "Spec test suite generator from yaml test files",
5
5
  "author": "ChainSafe Systems",
6
6
  "license": "Apache-2.0",
@@ -60,14 +60,14 @@
60
60
  ],
61
61
  "dependencies": {
62
62
  "@chainsafe/snappy-wasm": "^0.5.2",
63
- "@lodestar/utils": "^1.49.0-dev.4d35c8b82e",
63
+ "@lodestar/utils": "^1.49.0-dev.535f5dd45f",
64
64
  "rimraf": "^4.4.1",
65
65
  "vitest": "catalog:"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@chainsafe/ssz": "^1.8.0",
69
- "@lodestar/types": "^1.49.0-dev.4d35c8b82e",
69
+ "@lodestar/types": "^1.49.0-dev.535f5dd45f",
70
70
  "vitest": "catalog:"
71
71
  },
72
- "gitHead": "3a39fb7af997b424bed33a63c8b2e79d1dc12f78"
72
+ "gitHead": "7348f6fa176a07c18d3462b474c091ee055fd0ba"
73
73
  }
@@ -1,7 +1,8 @@
1
- import {fetch} from "@lodestar/utils";
1
+ import {LodestarError, fetch, retry} from "@lodestar/utils";
2
2
  import {downloadGenericSpecTests} from "./downloadTests.js";
3
3
 
4
- type WorkflowRunsResponse = {workflow_runs: {id: number}[]};
4
+ type WorkflowRun = {id: number; created_at: string; head_sha: string};
5
+ type WorkflowRunsResponse = {workflow_runs: WorkflowRun[]};
5
6
  type ArtifactsListResponse = {artifacts: {archive_download_url: string; expired: boolean; name: string}[]};
6
7
 
7
8
  async function ghApiFetch<T>(endpoint: string, token: string): Promise<T> {
@@ -19,25 +20,61 @@ async function ghApiFetch<T>(endpoint: string, token: string): Promise<T> {
19
20
  return res.json() as Promise<T>;
20
21
  }
21
22
 
22
- async function resolveNightlyRunId(repo: string, token: string, date?: string, branch?: string): Promise<number> {
23
+ async function resolveNightlyRun(
24
+ repo: string,
25
+ token: string,
26
+ log: (msg: string) => void,
27
+ date: Date | "latest",
28
+ branch?: string
29
+ ): Promise<WorkflowRun> {
23
30
  const params = new URLSearchParams({status: "success", per_page: "1"});
24
31
  if (branch) params.append("branch", branch);
25
32
  // If neither branch nor date narrow the query, restrict to scheduled runs so
26
33
  // a PR's successful run on consensus-specs can't outrank the latest master
27
34
  // nightly. When a date is given, allow manual re-runs on that day too.
28
- else if (!date) params.append("event", "schedule");
29
- if (date) params.append("created", date);
35
+ else if (date === "latest") params.append("event", "schedule");
36
+ // Require today's UTC run so upstream delays or failures surface in our nightly.
37
+ const createdFilter = (date === "latest" ? new Date() : date).toISOString().slice(0, 10);
38
+ const minCreatedAt = Date.parse(createdFilter);
39
+ const maxCreatedAt = minCreatedAt + 24 * 60 * 60 * 1000;
40
+ params.append("created", createdFilter);
30
41
 
31
- const {workflow_runs} = await ghApiFetch<WorkflowRunsResponse>(
32
- `/repos/${repo}/actions/workflows/tests.yml/runs?${params}`,
33
- token
34
- );
42
+ return retry(
43
+ async () => {
44
+ const {workflow_runs} = await ghApiFetch<WorkflowRunsResponse>(
45
+ `/repos/${repo}/actions/workflows/tests.yml/runs?${params}`,
46
+ token
47
+ );
48
+ const run = workflow_runs[0];
49
+ if (!run) {
50
+ throw new LodestarError(
51
+ {code: "NIGHTLY_RUN_NOT_FOUND", repo, branch: branch ?? null, createdFilter},
52
+ `No successful run found for ${repo}${branch ? ` (${branch})` : ""} with created=${createdFilter}`
53
+ );
54
+ }
35
55
 
36
- const runId = workflow_runs[0]?.id;
37
- if (!runId) {
38
- throw new Error(`No successful run found${date ? ` on ${date}` : ""} for ${repo}${branch ? ` (${branch})` : ""}`);
39
- }
40
- return runId;
56
+ // GitHub's run listing can return weeks-old results, so validate even with a date filter.
57
+ const createdAt = Date.parse(run.created_at);
58
+ if (!(createdAt >= minCreatedAt && createdAt < maxCreatedAt)) {
59
+ throw new LodestarError(
60
+ {
61
+ code: "NIGHTLY_RUN_OUTSIDE_DATE_RANGE",
62
+ runId: run.id,
63
+ createdAt: run.created_at ?? null,
64
+ createdFilter,
65
+ },
66
+ `Refusing nightly run ${run.id} created at ${run.created_at}: expected created=${createdFilter}`
67
+ );
68
+ }
69
+ return run;
70
+ },
71
+ {
72
+ retries: 2,
73
+ retryDelay: 1000,
74
+ shouldRetry: (error) => error instanceof LodestarError,
75
+ onRetry: (error, attempt) => log(`Nightly lookup attempt ${attempt}: ${error.message}`),
76
+ }
77
+ );
41
78
  }
42
79
 
43
80
  export async function downloadNightlyTests(
@@ -48,14 +85,20 @@ export async function downloadNightlyTests(
48
85
  const token = process.env.GITHUB_TOKEN;
49
86
  if (!token) throw new Error("GITHUB_TOKEN is required for nightly downloads");
50
87
 
51
- const resolvedDate = date === "latest" || !date ? undefined : date;
52
- if (resolvedDate && !/^\d{4}-\d{2}-\d{2}$/.test(resolvedDate)) {
88
+ const resolvedDate = date === "latest" || !date ? "latest" : new Date(date);
89
+ if (
90
+ resolvedDate !== "latest" &&
91
+ (!Number.isFinite(resolvedDate.getTime()) || resolvedDate.toISOString().slice(0, 10) !== date)
92
+ ) {
53
93
  throw new Error(`Invalid date: "${date}". Expected "latest" or YYYY-MM-DD`);
54
94
  }
55
95
 
56
96
  const repo = new URL(opts.specTestsRepoUrl).pathname.slice(1).replace(/\/$/, "");
57
- const runId = await resolveNightlyRunId(repo, token, resolvedDate, opts.branch);
58
- log(`Resolved nightly${resolvedDate ? ` ${resolvedDate}` : ""} to run ${runId}`);
97
+ const run = await resolveNightlyRun(repo, token, log, resolvedDate, opts.branch);
98
+ const runId = run.id;
99
+ log(
100
+ `Resolved nightly${resolvedDate === "latest" ? "" : ` ${date}`} to run ${runId} (created_at=${run.created_at}, head_sha=${run.head_sha})`
101
+ );
59
102
 
60
103
  const {artifacts} = await ghApiFetch<ArtifactsListResponse>(`/repos/${repo}/actions/runs/${runId}/artifacts`, token);
61
104