Repository navigation
Use node:26-alpine for docker images - #3055
Conversation
node:lts-alpine now points to Node 26, which no longer ships yarn, so the runtime stage failed at yarn install --production. The published images run Node 24.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Update Docker stages and changelogs packages/node/Dockerfile, packages/query/Dockerfile, packages/node/CHANGELOG.md, packages/query/CHANGELOG.md |
Both Dockerfiles use node:26-alpine in their builder and production stages. Each production stage installs yarn@latest globally with --force. Both changelogs record the changes. |
Priority:
Estimated code review effort: 2 (Simple) | ~5 minutes
Change: Bug fix
Merge Risk: 
Minimal · up to d74d8
-
The images use Node 26 rather than the described Node 24 pin. Yarn installation is provided in both stages, and no actionable merge-blocking defect was identified; normal build and compatibility checks remain necessary.
Pre-merge checks: 
4
-
Full details: Title check
-
Explanation
The title names the main change, which moves the node and query Docker images from node:lts-alpine to node:26-alpine. The PR objectives describe PR
#3055as pinning the images to node:24-alpine, which conflicts with the title and the file summaries. The changeset as summarized uses node:26-alpine and adds a global yarn install, so the title matches the changes, but the stated objective does not.
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
The Node 26 image no longer ships yarn. Pin the base image to an explicit major version instead of lts-alpine, so a future LTS change can't break the images.
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟢 | Statements | 87.01% (+16.9% 🔼) |
70758/81320 |
| 🟢 | Branches | 80.75% (+2.45% 🔼) |
3338/4134 |
| 🟡 | Functions | 65.24% (+2.74% 🔼) |
1250/1916 |
| 🟢 | Lines | 87.01% (+16.9% 🔼) |
70758/81320 |
⚠️ Details were not displayed: the report size has exceeded the limit.
Test suite run failed
Failed tests: 28/739. Failed suites: 8/116.
● Dictionary V1 › coreDictionary › set startHeight of this dictionary
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › coreDictionary › validateChainMeta and useDictionary
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › coreDictionary › validate dictionary with a height
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › coreDictionary › able to build queryEntryMap
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › coreDictionary › can use scoped dictionary query
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › coreDictionary › able to getDicitonaryQueryEntries
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › get metadata
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › init metadata and get metadata
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › return dictionary query result
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › should return undefined startblock height greater than dictionary last processed height
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Dictionary V1 › should use metadata last process height at end of query height
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"2db0b0156ff6311611089e2cda73fe48"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:58:18)
● Individual dictionary V1 test › return undefined when dictionary api failed
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"4423c35113f7674937b0c56a20e7ab69"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:186:18)
● Individual dictionary V1 test › limits the dictionary query to that block range
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"0471af6538ec0037aa64704724e2da4c"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:186:18)
● Individual dictionary V1 test › test query the correct range
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"359ec474e993d80f91238b3e624e750a"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:186:18)
● Individual dictionary V1 test › use minimum value of event/extrinsic returned block as batch end block
DictionaryQueryError: Dictionary returned HTTP 503 without data: {
"message":"failure to get a peer from the ring-balancer",
"request_id":"fa27bf18d456fe7988f92c643e4b826a"
}
94 | const data = body?.data;
95 | if (!response.ok || typeof data !== 'object' || data === null || Array.isArray(data)) {
> 96 | throw new DictionaryQueryError(
| ^
97 | `Dictionary returned HTTP ${response.status} without data: ${text.slice(0, 500)}`,
98 | response.status,
99 | [],
at TestDictionaryV1.query (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:96:13)
at TestDictionaryV1.init (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.ts:110:20)
at prepareDictionary (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:49:3)
at Object.<anonymous> (packages/node-core/src/indexer/dictionary/v1/dictionaryV1.spec.ts:186:18)
● Load chain type hasher › should use new hasher function, types hasher string should be replaced with function
thrown: "Exceeded timeout of 90000 ms for a test.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."
509 | };
510 |
> 511 | it('should use new hasher function, types hasher string should be replaced with function', async () => {
| ^
512 | const apiService = await prepareApiService();
513 | const api = apiService.api;
514 | expect(typeof (api as any)._options.typesBundle.spec.gargantua.hasher).toBe(
at packages/node/src/indexer/api.service.test.ts:511:3
at Object.<anonymous> (packages/node/src/indexer/api.service.test.ts:447:1)
● Substrate DictionaryService › should return all specVersion
expect(received).toBeGreaterThan(expected)
Matcher error: received value must be a number or bigint
Received has value: undefined
63 | const specVersions = await dictionaryService.getSpecVersions();
64 |
> 65 | expect(specVersions?.length).toBeGreaterThan(0);
| ^
66 | dictionaryService.onApplicationShutdown();
67 | }, 50000);
68 | });
at Object.<anonymous> (packages/node/src/indexer/dictionary/v1/substrateDictionaryV1.spec.ts:65:34)
● AutoQueue › resumes after flushing
expect(received).toEqual(expected) // deep equality
- Expected - 0
+ Received + 2
@@ -1,8 +1,10 @@
Array [
1,
2,
+ 3,
+ 4,
11,
12,
13,
14,
15,
192 | );
193 |
> 194 | expect(results).toEqual([1, 2, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
| ^
195 | });
196 |
197 | it('resolves the isIdle promise when the queue becomes idle', async () => {
at Object.<anonymous> (packages/node-core/src/utils/queues/autoQueue.spec.ts:194:21)
● substrate utils › return undefined if no timestamp set extrinsic
RpcError: 4003: Client error: Api called for an unknown Block: State already discarded for 0xf1cf9022c7ebb34b162d5b5e34e705a5a740b2d0ecc1009fb89023e62a488108
150 | formatted_error = new LargeResponseError(e);
151 | } else {
> 152 | formatted_error = new ApiConnectionError(
| ^
153 | e.name,
154 | e.message,
155 | ApiErrorType.Default,
at ApiPromiseConnection.handleError (packages/node/src/indexer/apiPromise.connection.ts:152:25)
at packages/node/src/utils/substrate.ts:312:32
at getBlockByHeight (packages/node/src/utils/substrate.ts:308:17)
at Object.<anonymous> (packages/node/src/utils/substrate.test.ts:102:20)
● substrate utils › return defined if no timestamp set extrinsic
RpcError: 4003: Client error: Api called for an unknown Block: State already discarded for 0x96ee06f85333baba93e16da4384978e2c1ac4bfed789446b975ffda894da90be
150 | formatted_error = new LargeResponseError(e);
151 | } else {
> 152 | formatted_error = new ApiConnectionError(
| ^
153 | e.name,
154 | e.message,
155 | ApiErrorType.Default,
at ApiPromiseConnection.handleError (packages/node/src/indexer/apiPromise.connection.ts:152:25)
at packages/node/src/utils/substrate.ts:312:32
at getBlockByHeight (packages/node/src/utils/substrate.ts:308:17)
at Object.<anonymous> (packages/node/src/utils/substrate.test.ts:110:20)
● etherscan api › Deployment information › can get the deploy height of a contract
Etherscan API error: Free API access is not supported for this chain. Please upgrade your api plan for full chain coverage. https://etherscan.io/apis
24 | return undefined;
25 | }
> 26 | throw new Error(`Etherscan API error: ${data.result}`);
| ^
27 | }
28 |
29 | return data.result;
at runRequest (packages/cli/src/utils/etherscan.ts:26:11)
at fetchContractDeployHeight (packages/cli/src/utils/etherscan.ts:69:18)
at Object.<anonymous> (packages/cli/src/utils/etherscan.spec.ts:41:22)
● Integration test - Publish › overwrites any existing CID files
Failed to generate manifest from typescript /tmp/JNtD5x/mocked_starter/project.ts, Failed to build /tmp/JNtD5x/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Object.<anonymous> (packages/cli/src/commands/publish.test.ts:17:22)
● Integration test - Publish › create ipfsCID file stored in local with dictiory path
Failed to generate manifest from typescript /tmp/JNtD5x/mocked_starter/project.ts, Failed to build /tmp/JNtD5x/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Object.<anonymous> (packages/cli/src/commands/publish.test.ts:17:22)
● Integration test - Publish › file name consistent with manifest file name, if -f <manifest path> is used
Failed to generate manifest from typescript /tmp/JNtD5x/mocked_starter/project.ts, Failed to build /tmp/JNtD5x/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Object.<anonymous> (packages/cli/src/commands/publish.test.ts:17:22)
● Cli publish › should upload appropriate project to IPFS
Failed to generate manifest from typescript /tmp/zDQYID/mocked_starter/project.ts, Failed to build /tmp/zDQYID/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Promise.all (index 0)
at async Object.<anonymous> (packages/cli/src/controller/publish-controller.spec.ts:18:21)
● Cli publish › convert to deployment and removed descriptive field
Failed to generate manifest from typescript /tmp/zDQYID/mocked_starter/project.ts, Failed to build /tmp/zDQYID/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Promise.all (index 0)
at async Object.<anonymous> (packages/cli/src/controller/publish-controller.spec.ts:18:21)
● Cli publish › convert js object to JSON object
Failed to generate manifest from typescript /tmp/zDQYID/mocked_starter/project.ts, Failed to build /tmp/zDQYID/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Promise.all (index 0)
at async Object.<anonymous> (packages/cli/src/controller/publish-controller.spec.ts:18:21)
● Cli publish › Get directory CID from multi-chain project
Failed to generate manifest from typescript /tmp/zDQYID/mocked_starter/project.ts, Failed to build /tmp/zDQYID/mocked_starter/project.ts: TypeError: Cannot read properties of undefined (reading 'fileExists'), undefined
55 | await codegen(root, manifests);
56 | }
> 57 |
| ^
58 | export default class Codegen extends Command {
59 | static description = 'Generate entity types from the GraphQL schema and contract interfaces';
60 | static args = zodToArgs(codegenInputs);
at Object.error (node_modules/@oclif/core/lib/errors/error.js:44:15)
at Codegen.error (node_modules/@oclif/core/lib/command.js:216:23)
at Codegen.run (packages/cli/src/commands/codegen/index.ts:57:18)
at async Codegen._run (node_modules/@oclif/core/lib/command.js:182:22)
at async installAndBuild (packages/cli/src/createProject.fixtures.ts:75:5)
at async createTestProject (packages/cli/src/createProject.fixtures.ts:84:5)
at async Promise.all (index 0)
at async Object.<anonymous> (packages/cli/src/controller/publish-controller.spec.ts:18:21)
Report generated by 🧪jest coverage report action from d74d818
* ci: replace the revoked REPO_TOKEN with a short-lived GitHub App token REPO_TOKEN was revoked after it leaked, so Prerelease Publish fails at checkout. This ports subquery#3053. - Read-only checkouts (node-docker, benchmark) use the default token. - Pushing the prerelease commit to main and creating GitHub releases use a token minted from the subql-release-bot GitHub App. The token is created after install, build and publish, and is passed only to the push and release steps, so third-party install and build scripts never see a write credential. Releases made with it still trigger the Docker and Discord workflows, unlike ones made with GITHUB_TOKEN. - Prerelease checkout no longer persists credentials, and the commit and push are explicit git commands instead of EndBug/add-and-commit. - pre-ci passes the head commit message through env instead of interpolating it into the script, which allowed shell injection in a job with id-token: write. * Use node:26-alpine for the docker image node:lts-alpine moved to Node 26 on 2026-10-28. Pin the major version so the next LTS change can't silently change the base image, as subquery#3055 did. * ci: check the release app before publishing, and push in a separate step - The prerelease job publishes to npm before it pushes the version bump. If the app couldn't get a token, the prerelease would be on npm while main kept the old version, and the next prerelease would fail on the same version. A separate job now creates a token first, and the prerelease job waits for it. - git commit runs the husky pre-commit hook (lint-staged), so the commit step no longer has the token. The token is created after the commit, and only the push step gets it.
Problem
The Node-to-docker run for
node/6.5.0failed in both jobs (https://github.com/subquery/subql/actions/runs/40824622723):node:lts-alpinemoved to Node 26 on 2026-10-28 (it now has the same digest asnode:26-alpine), and the Node 26 image doesn't include yarn. The builder stage still works becausescripts/build.shinstalls yarn with npm, but the runtime stage used the yarn that came with the image.Change
node:26-alpineinstead ofnode:lts-alpine, so the next LTS change can't break the images without a code change.npm install -g --force yarn@latest, the same wayscripts/build.shdoes in the builder stage.onfinality/subql-node:v6.4.6has v24.11.1,onfinality/subql-query:latesthas v24.22.1).Testing
Both images were built locally (linux/arm64) from this branch:
@subql/node6.5.0 with@subql/node-core19.4.0.blockEntitiesand_metadatareturned the indexed blocks (indexerNodeVersion6.5.0,queryNodeVersion2.25.0).Release
npm 6.5.0 and the GitHub release are already published. Only the docker images are missing. Re-running the failed run won't help, because it checks out the
node/6.5.0tag, which has the old Dockerfile. So the images are built from this branch with a Node-to-dockerworkflow_dispatch(isLatest=true) before merging. After the merge, the prerelease bumpspackages/nodeto6.5.1-0, so a dispatch frommainwould tag the image with that version.Summary by CodeRabbit