@aspruyt/xfg 3.9.11 → 3.9.12

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.
@@ -54,6 +54,13 @@ export declare class GraphQLCommitStrategy implements ICommitStrategy {
54
54
  * For direct mode (force=false): just ensure branch exists.
55
55
  */
56
56
  private ensureBranchExistsOnRemote;
57
+ /**
58
+ * Sanitize command execution errors to remove the GraphQL payload.
59
+ * Node.js execSync errors include "Command failed: <full command>\n<stderr>".
60
+ * The command contains the entire GraphQL mutation payload (potentially megabytes
61
+ * of base64-encoded file contents). This extracts just the meaningful stderr.
62
+ */
63
+ private sanitizeCommandError;
57
64
  /**
58
65
  * Check if an error is due to expectedHeadOid mismatch (optimistic locking failure).
59
66
  * This happens when the branch was updated between getting HEAD and making the commit.
@@ -173,12 +173,18 @@ export class GraphQLCommitStrategy {
173
173
  // GH_TOKEN env var must be set for the gh command (after the pipe), not echo
174
174
  const tokenPrefix = token ? `GH_TOKEN=${token} ` : "";
175
175
  const command = `echo ${escapeShellArg(requestBody)} | ${tokenPrefix}gh api graphql ${hostnameArg} --input -`;
176
- const response = await withRetry(() => this.executor.exec(command, workDir), {
177
- permanentErrorPatterns: [
178
- ...DEFAULT_PERMANENT_ERROR_PATTERNS,
179
- ...OID_MISMATCH_PATTERNS,
180
- ],
181
- });
176
+ let response;
177
+ try {
178
+ response = await withRetry(() => this.executor.exec(command, workDir), {
179
+ permanentErrorPatterns: [
180
+ ...DEFAULT_PERMANENT_ERROR_PATTERNS,
181
+ ...OID_MISMATCH_PATTERNS,
182
+ ],
183
+ });
184
+ }
185
+ catch (error) {
186
+ throw this.sanitizeCommandError(error, repositoryNameWithOwner);
187
+ }
182
188
  // Parse the response
183
189
  const parsed = JSON.parse(response);
184
190
  if (parsed.errors) {
@@ -240,6 +246,32 @@ export class GraphQLCommitStrategy {
240
246
  }
241
247
  }
242
248
  }
249
+ /**
250
+ * Sanitize command execution errors to remove the GraphQL payload.
251
+ * Node.js execSync errors include "Command failed: <full command>\n<stderr>".
252
+ * The command contains the entire GraphQL mutation payload (potentially megabytes
253
+ * of base64-encoded file contents). This extracts just the meaningful stderr.
254
+ */
255
+ sanitizeCommandError(error, repo) {
256
+ const originalMessage = error instanceof Error ? error.message : String(error);
257
+ let cleanMessage;
258
+ if (originalMessage.startsWith("Command failed:")) {
259
+ // Extract stderr: everything after the first newline
260
+ const newlineIndex = originalMessage.indexOf("\n");
261
+ cleanMessage =
262
+ newlineIndex >= 0
263
+ ? originalMessage.substring(newlineIndex + 1).trim()
264
+ : "unknown error";
265
+ }
266
+ else {
267
+ cleanMessage = originalMessage;
268
+ }
269
+ // Safety truncation for any remaining oversized messages
270
+ if (cleanMessage.length > 2000) {
271
+ cleanMessage = cleanMessage.substring(0, 2000) + "... (truncated)";
272
+ }
273
+ return new Error(`GraphQL commit failed for ${repo}: ${cleanMessage}`);
274
+ }
243
275
  /**
244
276
  * Check if an error is due to expectedHeadOid mismatch (optimistic locking failure).
245
277
  * This happens when the branch was updated between getting HEAD and making the commit.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspruyt/xfg",
3
- "version": "3.9.11",
3
+ "version": "3.9.12",
4
4
  "description": "Manage files, settings, and repositories across GitHub, Azure DevOps, and GitLab — declaratively, from a single YAML config",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",