From 3722cdfb3781a2366f91a1189433a6b3bcb738ed Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 19 Jun 2026 22:02:59 -0400 Subject: [PATCH 1/2] Fix codegen schema resolution for new @github/copilot package layout The @github/copilot CLI package became a thin loader in 1.0.64-1 and moved its bundled JSON schemas into platform-specific packages (e.g. @github/copilot-win32-x64). The codegen scripts hardcoded the umbrella package's schemas/ path, which no longer exists, breaking the Update @github/copilot Dependency workflow. Resolve schemas by checking the umbrella package first (older versions), then falling back to whichever @github/copilot-* platform package is installed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- java/scripts/codegen/java.ts | 61 ++++++++++++++++++++++++------------ scripts/codegen/utils.ts | 56 ++++++++++++++++++++++++++------- 2 files changed, 85 insertions(+), 32 deletions(-) diff --git a/java/scripts/codegen/java.ts b/java/scripts/codegen/java.ts index 89fea8930..54f32f773 100644 --- a/java/scripts/codegen/java.ts +++ b/java/scripts/codegen/java.ts @@ -148,36 +148,57 @@ function toEnumConstant(value: string): string { // ── Schema path resolution ─────────────────────────────────────────────────── -async function getSessionEventsSchemaPath(): Promise { - const candidates = [ - path.join(REPO_ROOT, "scripts/codegen/node_modules/@github/copilot/schemas/session-events.schema.json"), - path.join(REPO_ROOT, "nodejs/node_modules/@github/copilot/schemas/session-events.schema.json"), +/** + * Resolve a JSON schema shipped by the `@github/copilot` CLI package. + * + * The CLI package layout changed in 1.0.64-1: the umbrella `@github/copilot` + * package became a thin loader and its bundled assets (including the JSON + * schemas) moved into the platform-specific packages installed as optional + * dependencies, e.g. `@github/copilot-linux-x64` or `@github/copilot-win32-x64`. + * + * We search both the Java codegen install (`scripts/codegen/node_modules`) and + * the Node SDK install (`nodejs/node_modules`), checking the umbrella package + * first (older versions) and then whichever platform package is present. + */ +async function resolveCopilotSchemaPath(fileName: string): Promise { + const nodeModulesDirs = [ + path.join(REPO_ROOT, "scripts/codegen/node_modules"), + path.join(REPO_ROOT, "nodejs/node_modules"), ]; - for (const p of candidates) { + + const candidates: string[] = []; + for (const nodeModulesDir of nodeModulesDirs) { + candidates.push(path.join(nodeModulesDir, "@github/copilot/schemas", fileName)); + const githubScopeDir = path.join(nodeModulesDir, "@github"); try { - await fs.access(p); - return p; + for (const entry of await fs.readdir(githubScopeDir)) { + if (entry.startsWith("copilot-")) { + candidates.push(path.join(githubScopeDir, entry, "schemas", fileName)); + } + } } catch { - // try next + // @github scope directory may not exist; try the next location. } } - throw new Error("session-events.schema.json not found. Run 'npm ci' in scripts/codegen first."); -} -async function getApiSchemaPath(): Promise { - const candidates = [ - path.join(REPO_ROOT, "scripts/codegen/node_modules/@github/copilot/schemas/api.schema.json"), - path.join(REPO_ROOT, "nodejs/node_modules/@github/copilot/schemas/api.schema.json"), - ]; - for (const p of candidates) { + for (const candidate of candidates) { try { - await fs.access(p); - return p; + await fs.access(candidate); + return candidate; } catch { - // try next + // Try the next candidate. } } - throw new Error("api.schema.json not found. Run 'npm ci' in scripts/codegen first."); + + throw new Error(`${fileName} not found. Run 'npm ci' in scripts/codegen first.`); +} + +async function getSessionEventsSchemaPath(): Promise { + return resolveCopilotSchemaPath("session-events.schema.json"); +} + +async function getApiSchemaPath(): Promise { + return resolveCopilotSchemaPath("api.schema.json"); } // ── File writing ───────────────────────────────────────────────────────────── diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts index 3917dad44..d39be20cb 100644 --- a/scripts/codegen/utils.ts +++ b/scripts/codegen/utils.ts @@ -45,23 +45,55 @@ export type SchemaWithSharedDefinitions = T }; // ── Schema paths ──────────────────────────────────────────────────────────── -export async function getSessionEventsSchemaPath(): Promise { - const schemaPath = path.join( - REPO_ROOT, - "nodejs/node_modules/@github/copilot/schemas/session-events.schema.json" +const SDK_NODE_MODULES = path.join(REPO_ROOT, "nodejs/node_modules"); + +/** + * Resolve a JSON schema shipped by the `@github/copilot` CLI package. + * + * The CLI package layout changed in 1.0.64-1: the umbrella `@github/copilot` + * package became a thin loader and its bundled assets (including the JSON + * schemas) moved into the platform-specific packages installed as optional + * dependencies, e.g. `@github/copilot-linux-x64` or `@github/copilot-win32-x64`. + * + * To support both layouts we look in the umbrella package first (older + * versions) and then in whichever platform package was installed for the + * current host. + */ +async function resolveCopilotSchemaPath(nodeModulesDir: string, fileName: string): Promise { + const candidates = [path.join(nodeModulesDir, "@github/copilot/schemas", fileName)]; + + const githubScopeDir = path.join(nodeModulesDir, "@github"); + try { + for (const entry of await fs.readdir(githubScopeDir)) { + if (entry.startsWith("copilot-")) { + candidates.push(path.join(githubScopeDir, entry, "schemas", fileName)); + } + } + } catch { + // @github scope directory may not exist yet; fall through to the error below. + } + + for (const candidate of candidates) { + try { + await fs.access(candidate); + return candidate; + } catch { + // Try the next candidate. + } + } + + throw new Error( + `${fileName} not found under ${githubScopeDir}. Run 'npm ci' in nodejs/ first.` ); - await fs.access(schemaPath); - return schemaPath; +} + +export async function getSessionEventsSchemaPath(): Promise { + return resolveCopilotSchemaPath(SDK_NODE_MODULES, "session-events.schema.json"); } export async function getApiSchemaPath(cliArg?: string): Promise { if (cliArg) return cliArg; - const schemaPath = path.join( - REPO_ROOT, - "nodejs/node_modules/@github/copilot/schemas/api.schema.json" - ); - await fs.access(schemaPath); - return schemaPath; + return resolveCopilotSchemaPath(SDK_NODE_MODULES, "api.schema.json"); } // ── Brand casing normalization ────────────────────────────────────────────── From a52fa6ced39e187ed6ddfc8067580483160dca4c Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 19 Jun 2026 22:28:54 -0400 Subject: [PATCH 2/2] Surface real readdir errors and fix schema-not-found guidance in codegen resolvers Only swallow ENOENT/ENOTDIR when probing the @github scope directory so permission/I/O failures are no longer misreported as 'schema not found'. Also correct the java codegen not-found message to name both install locations the resolver searches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- java/scripts/codegen/java.ts | 8 ++++++-- scripts/codegen/utils.ts | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java/scripts/codegen/java.ts b/java/scripts/codegen/java.ts index 54f32f773..ba0ed3df1 100644 --- a/java/scripts/codegen/java.ts +++ b/java/scripts/codegen/java.ts @@ -176,7 +176,11 @@ async function resolveCopilotSchemaPath(fileName: string): Promise { candidates.push(path.join(githubScopeDir, entry, "schemas", fileName)); } } - } catch { + } catch (err) { + const code = (err as NodeJS.ErrnoException).code; + if (code !== "ENOENT" && code !== "ENOTDIR") { + throw err; + } // @github scope directory may not exist; try the next location. } } @@ -190,7 +194,7 @@ async function resolveCopilotSchemaPath(fileName: string): Promise { } } - throw new Error(`${fileName} not found. Run 'npm ci' in scripts/codegen first.`); + throw new Error(`${fileName} not found. Run 'npm ci' in java/scripts/codegen or java/nodejs first.`); } async function getSessionEventsSchemaPath(): Promise { diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts index d39be20cb..b9bfb9730 100644 --- a/scripts/codegen/utils.ts +++ b/scripts/codegen/utils.ts @@ -69,7 +69,11 @@ async function resolveCopilotSchemaPath(nodeModulesDir: string, fileName: string candidates.push(path.join(githubScopeDir, entry, "schemas", fileName)); } } - } catch { + } catch (err) { + const code = (err as NodeJS.ErrnoException).code; + if (code !== "ENOENT" && code !== "ENOTDIR") { + throw err; + } // @github scope directory may not exist yet; fall through to the error below. }