Skip to content

Commit 4685618

Browse files
stephentoubCopilot
andauthored
Fix codegen schema resolution for new @github/copilot package layout (#1738)
* 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> * 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> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9b97c2e commit 4685618

2 files changed

Lines changed: 94 additions & 33 deletions

File tree

java/scripts/codegen/java.ts

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -148,36 +148,61 @@ function toEnumConstant(value: string): string {
148148

149149
// ── Schema path resolution ───────────────────────────────────────────────────
150150

151-
async function getSessionEventsSchemaPath(): Promise<string> {
152-
const candidates = [
153-
path.join(REPO_ROOT, "scripts/codegen/node_modules/@github/copilot/schemas/session-events.schema.json"),
154-
path.join(REPO_ROOT, "nodejs/node_modules/@github/copilot/schemas/session-events.schema.json"),
151+
/**
152+
* Resolve a JSON schema shipped by the `@github/copilot` CLI package.
153+
*
154+
* The CLI package layout changed in 1.0.64-1: the umbrella `@github/copilot`
155+
* package became a thin loader and its bundled assets (including the JSON
156+
* schemas) moved into the platform-specific packages installed as optional
157+
* dependencies, e.g. `@github/copilot-linux-x64` or `@github/copilot-win32-x64`.
158+
*
159+
* We search both the Java codegen install (`scripts/codegen/node_modules`) and
160+
* the Node SDK install (`nodejs/node_modules`), checking the umbrella package
161+
* first (older versions) and then whichever platform package is present.
162+
*/
163+
async function resolveCopilotSchemaPath(fileName: string): Promise<string> {
164+
const nodeModulesDirs = [
165+
path.join(REPO_ROOT, "scripts/codegen/node_modules"),
166+
path.join(REPO_ROOT, "nodejs/node_modules"),
155167
];
156-
for (const p of candidates) {
168+
169+
const candidates: string[] = [];
170+
for (const nodeModulesDir of nodeModulesDirs) {
171+
candidates.push(path.join(nodeModulesDir, "@github/copilot/schemas", fileName));
172+
const githubScopeDir = path.join(nodeModulesDir, "@github");
157173
try {
158-
await fs.access(p);
159-
return p;
160-
} catch {
161-
// try next
174+
for (const entry of await fs.readdir(githubScopeDir)) {
175+
if (entry.startsWith("copilot-")) {
176+
candidates.push(path.join(githubScopeDir, entry, "schemas", fileName));
177+
}
178+
}
179+
} catch (err) {
180+
const code = (err as NodeJS.ErrnoException).code;
181+
if (code !== "ENOENT" && code !== "ENOTDIR") {
182+
throw err;
183+
}
184+
// @github scope directory may not exist; try the next location.
162185
}
163186
}
164-
throw new Error("session-events.schema.json not found. Run 'npm ci' in scripts/codegen first.");
165-
}
166187

167-
async function getApiSchemaPath(): Promise<string> {
168-
const candidates = [
169-
path.join(REPO_ROOT, "scripts/codegen/node_modules/@github/copilot/schemas/api.schema.json"),
170-
path.join(REPO_ROOT, "nodejs/node_modules/@github/copilot/schemas/api.schema.json"),
171-
];
172-
for (const p of candidates) {
188+
for (const candidate of candidates) {
173189
try {
174-
await fs.access(p);
175-
return p;
190+
await fs.access(candidate);
191+
return candidate;
176192
} catch {
177-
// try next
193+
// Try the next candidate.
178194
}
179195
}
180-
throw new Error("api.schema.json not found. Run 'npm ci' in scripts/codegen first.");
196+
197+
throw new Error(`${fileName} not found. Run 'npm ci' in java/scripts/codegen or java/nodejs first.`);
198+
}
199+
200+
async function getSessionEventsSchemaPath(): Promise<string> {
201+
return resolveCopilotSchemaPath("session-events.schema.json");
202+
}
203+
204+
async function getApiSchemaPath(): Promise<string> {
205+
return resolveCopilotSchemaPath("api.schema.json");
181206
}
182207

183208
// ── File writing ─────────────────────────────────────────────────────────────

scripts/codegen/utils.ts

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,59 @@ export type SchemaWithSharedDefinitions<T extends JSONSchema7 = JSONSchema7> = T
4545
};
4646
// ── Schema paths ────────────────────────────────────────────────────────────
4747

48-
export async function getSessionEventsSchemaPath(): Promise<string> {
49-
const schemaPath = path.join(
50-
REPO_ROOT,
51-
"nodejs/node_modules/@github/copilot/schemas/session-events.schema.json"
48+
const SDK_NODE_MODULES = path.join(REPO_ROOT, "nodejs/node_modules");
49+
50+
/**
51+
* Resolve a JSON schema shipped by the `@github/copilot` CLI package.
52+
*
53+
* The CLI package layout changed in 1.0.64-1: the umbrella `@github/copilot`
54+
* package became a thin loader and its bundled assets (including the JSON
55+
* schemas) moved into the platform-specific packages installed as optional
56+
* dependencies, e.g. `@github/copilot-linux-x64` or `@github/copilot-win32-x64`.
57+
*
58+
* To support both layouts we look in the umbrella package first (older
59+
* versions) and then in whichever platform package was installed for the
60+
* current host.
61+
*/
62+
async function resolveCopilotSchemaPath(nodeModulesDir: string, fileName: string): Promise<string> {
63+
const candidates = [path.join(nodeModulesDir, "@github/copilot/schemas", fileName)];
64+
65+
const githubScopeDir = path.join(nodeModulesDir, "@github");
66+
try {
67+
for (const entry of await fs.readdir(githubScopeDir)) {
68+
if (entry.startsWith("copilot-")) {
69+
candidates.push(path.join(githubScopeDir, entry, "schemas", fileName));
70+
}
71+
}
72+
} catch (err) {
73+
const code = (err as NodeJS.ErrnoException).code;
74+
if (code !== "ENOENT" && code !== "ENOTDIR") {
75+
throw err;
76+
}
77+
// @github scope directory may not exist yet; fall through to the error below.
78+
}
79+
80+
for (const candidate of candidates) {
81+
try {
82+
await fs.access(candidate);
83+
return candidate;
84+
} catch {
85+
// Try the next candidate.
86+
}
87+
}
88+
89+
throw new Error(
90+
`${fileName} not found under ${githubScopeDir}. Run 'npm ci' in nodejs/ first.`
5291
);
53-
await fs.access(schemaPath);
54-
return schemaPath;
92+
}
93+
94+
export async function getSessionEventsSchemaPath(): Promise<string> {
95+
return resolveCopilotSchemaPath(SDK_NODE_MODULES, "session-events.schema.json");
5596
}
5697

5798
export async function getApiSchemaPath(cliArg?: string): Promise<string> {
5899
if (cliArg) return cliArg;
59-
const schemaPath = path.join(
60-
REPO_ROOT,
61-
"nodejs/node_modules/@github/copilot/schemas/api.schema.json"
62-
);
63-
await fs.access(schemaPath);
64-
return schemaPath;
100+
return resolveCopilotSchemaPath(SDK_NODE_MODULES, "api.schema.json");
65101
}
66102

67103
// ── Brand casing normalization ──────────────────────────────────────────────

0 commit comments

Comments
 (0)