Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion actions/setup/js/check_membership.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

const { parseRequiredPermissions, parseAllowedBots, checkRepositoryPermission, checkBotStatus, isAllowedBot, isConfusedDeputyAttack } = require("./check_permissions_utils.cjs");
const { writeDenialSummary } = require("./pre_activation_summary.cjs");
const { getErrorMessage } = require("./error_helpers.cjs");

/**
* Attempt to authorize the actor via the bots allowlist.
Expand Down Expand Up @@ -147,7 +148,7 @@ async function main() {
return;
}
} catch (error) {
const errorMessage = `Repository permission check failed: Unable to verify pull request provenance (${error?.message ?? String(error)}).`;
const errorMessage = `Repository permission check failed: Unable to verify pull request provenance (${getErrorMessage(error)}).`;
core.warning(errorMessage);
core.setOutput("is_team_member", "false");
core.setOutput("result", "api_error");
Expand Down
2 changes: 1 addition & 1 deletion actions/setup/js/check_permissions_utils.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function readAllowBotAuthoredTriggerComment(payload) {
} catch (err) {
// Malformed aw_context is treated as absent — default to safe behaviour (flag is false).
// Log at debug level so workflow authors can diagnose issues with aw_context format.
core.debug?.(`readAllowBotAuthoredTriggerComment: failed to parse aw_context: ${err?.message ?? String(err)}`);
core.debug?.(`readAllowBotAuthoredTriggerComment: failed to parse aw_context: ${getErrorMessage(err)}`);
return false;
}
}
Expand Down
3 changes: 2 additions & 1 deletion actions/setup/js/check_team_member.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* @returns {Promise<void>}
*/
const { ERR_PERMISSION } = require("./error_codes.cjs");
const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
const actor = context.actor;
const { owner, repo } = context.repo;
Expand All @@ -29,7 +30,7 @@ async function main() {
return;
}
} catch (repoError) {
const errorMessage = repoError instanceof Error ? repoError.message : String(repoError);
const errorMessage = getErrorMessage(repoError);
core.warning(`Repository permission check failed: ${errorMessage}`);
}

Expand Down
3 changes: 2 additions & 1 deletion actions/setup/js/check_version_updates.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

const { withRetry, isTransientError } = require("./error_recovery.cjs");
const { getErrorMessage } = require("./error_helpers.cjs");

const CONFIG_URL = "https://raw.githubusercontent.com/github/gh-aw-actions/main/.github/aw/compat.json";

Expand Down Expand Up @@ -108,7 +109,7 @@ async function main() {
"fetch update configuration"
);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
const message = getErrorMessage(err);
core.info(`Could not fetch update configuration (${message}). Skipping version check.`);
return;
}
Expand Down
6 changes: 4 additions & 2 deletions actions/setup/js/checkout_pr_branch.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,14 @@ async function assertTrustedCheckoutRuntime() {
// A 404 here is ambiguous: it can indicate either a non-user app/bot actor
// or a real user that is not a collaborator. Disambiguate via users API.
// Real users resolve via users.getByUsername; app/bot actors return 404.
if (err.status === 404) {
const errAny = /** @type {any} */ err;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] The /** @type {any} */ err cast lacks the parentheses required for a JSDoc type assertion in @ts-check files — the correct form is /** @type {any} */ (err). Without parens, the type annotation is a JSDoc comment on the const declaration itself, not a cast expression; TypeScript will still treat errAny as unknown and the .status access will fail type-checking.

💡 Suggested fix
// Before (missing parens)
const errAny = /** `@type` {any} */ err;

// After (correct JSDoc cast)
const errAny = /** `@type` {any} */ (err);

Note: error_helpers.cjs uses the correct form at line 28: const errorAsAny = /** @type {any} */ (error);.

This pattern is introduced in multiple files in this PR (checkout_pr_branch.cjs, load_experiment_state_from_repo.cjs, run_operation_update_upgrade.cjs). All need the parentheses.

@copilot please address this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSDoc type cast is missing required parentheses: /** @type {any} */ err does not apply the cast — TypeScript JSDoc assertions require the target expression to be parenthesized.

💡 Detail and fix

The TypeScript JSDoc type-assertion syntax requires wrapping the expression in parentheses:

// WRONG — cast is ignored; err is still typed as unknown
const errAny = /** `@type` {any} */ err;

// CORRECT
const errAny = /** `@type` {any} */ (err);

Without the parens, tsc --checkJs (and checkers like Pyright) still see errAny as the original type of err. In a catch block with useUnknownInCatchVariables: true, err is unknown, so errAny.status remains a type error. Even if your tsconfig has useUnknownInCatchVariables: false today, the pattern is incorrect and will break if strict checking is tightened.

The same issue appears at line 166 with userErrAny. Both casts need parens.

const errAny = /** `@type` {any} */ (err);
if (errAny.status === 404) {
  const userErrAny = /** `@type` {any} */ (userErr);
  if (userErrAny.status === 404) {

if (errAny.status === 404) {
try {
await github.rest.users.getByUsername({ username: actor });
throw new Error(`Refusing PR checkout: actor '${actor}' is not a collaborator (requires write or higher)`);
} catch (userErr) {
if (userErr.status === 404) {
const userErrAny = /** @type {any} */ userErr;
if (userErrAny.status === 404) {
core.info(`Runtime safety check passed for app actor '${actor}' (not a regular user)`);
return;
}
Expand Down
3 changes: 2 additions & 1 deletion actions/setup/js/claude_harness.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

"use strict";

const { getErrorMessage } = require("./error_helpers.cjs");
const fs = require("fs");
const { runProcess, formatDuration, sleep } = require("./process_runner.cjs");
const { resolveRetryConfig: resolveSharedRetryConfig } = require("./harness_retry_config.cjs");
Expand Down Expand Up @@ -555,7 +556,7 @@ if (typeof module !== "undefined" && module.exports) {

if (require.main === module) {
main().catch(err => {
log(`unexpected error: ${err.message}`);
log(`unexpected error: ${getErrorMessage(err)}`);
process.exit(1);
});
}
3 changes: 2 additions & 1 deletion actions/setup/js/codex_harness.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

"use strict";

const { getErrorMessage } = require("./error_helpers.cjs");
const fs = require("fs");
const { runProcess, formatDuration, sleep } = require("./process_runner.cjs");
const {
Expand Down Expand Up @@ -602,7 +603,7 @@ if (typeof module !== "undefined" && module.exports) {

if (require.main === module) {
main().catch(err => {
log(`unexpected error: ${err.message}`);
log(`unexpected error: ${getErrorMessage(err)}`);
process.exit(1);
});
}
4 changes: 2 additions & 2 deletions actions/setup/js/collect_ndjson_output.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ async function main() {
return sanitizePrototypePollution(parsed);
} catch (repairError) {
core.info(`invalid input json: ${jsonStr}`);
const originalMsg = originalError instanceof Error ? originalError.message : String(originalError);
const repairMsg = repairError instanceof Error ? repairError.message : String(repairError);
const originalMsg = getErrorMessage(originalError);
const repairMsg = getErrorMessage(repairError);
throw new Error(`${ERR_PARSE}: JSON parsing failed. Original: ${originalMsg}. After attempted repair: ${repairMsg}`);
}
}
Expand Down
3 changes: 2 additions & 1 deletion actions/setup/js/collect_skill_install_failures.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/// <reference types="@actions/github-script" />

const fs = require("fs");
const { getErrorMessage } = require("./error_helpers.cjs");

/** Path written by install_frontmatter_skills.cjs during the activation job. */
const SKILL_FAILURES_FILE = "/tmp/gh-aw/skill_install_failures.json";
Expand All @@ -24,7 +25,7 @@ function readSkillInstallFailures() {
return parsed.filter(entry => entry && typeof entry.skill === "string" && typeof entry.error === "string");
} catch (readErr) {
// Warn so "no failures" vs "couldn't read failures file" is distinguishable in logs
core.warning(`Could not read skill install failures file: ${readErr instanceof Error ? readErr.message : String(readErr)}`);
core.warning(`Could not read skill install failures file: ${getErrorMessage(readErr)}`);
return [];
}
}
Expand Down
3 changes: 2 additions & 1 deletion actions/setup/js/convert_gateway_config_copilot.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ require("./shim.cjs");

const path = require("path");
const { rewriteUrl, normalizeGatewayEntry, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs");
const { getErrorMessage } = require("./error_helpers.cjs");

/**
* Resolves the Copilot CLI MCP config output path from the runtime $HOME.
Expand Down Expand Up @@ -67,7 +68,7 @@ function main() {
try {
outputPath = resolveCopilotConfigOutputPath();
} catch (err) {
core.error(`ERROR: ${err.message}`);
core.error(`ERROR: ${getErrorMessage(err)}`);
process.exit(1);
}

Expand Down
3 changes: 2 additions & 1 deletion actions/setup/js/copilot_harness.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

require("./shim.cjs");

const { getErrorMessage } = require("./error_helpers.cjs");
const fs = require("fs");
const crypto = require("crypto");
const { getPromptPath, renderTemplateFromFile } = require("./messages_core.cjs");
Expand Down Expand Up @@ -1223,7 +1224,7 @@ if (typeof module !== "undefined" && module.exports) {

if (require.main === module) {
main().catch(err => {
log(`unexpected error: ${err.message}`);
log(`unexpected error: ${getErrorMessage(err)}`);
process.exit(1);
});
}
3 changes: 2 additions & 1 deletion actions/setup/js/copilot_sdk_session.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

"use strict";

const { getErrorMessage } = require("./error_helpers.cjs");
const fs = require("fs");
const path = require("path");
const os = require("os");
Expand Down Expand Up @@ -401,7 +402,7 @@ async function runWithCopilotSDK({ sdkUri, prompt, logger, attempt = 0, model, c
log(`warning: post-completion idle watchdog fired after ${postCompletionIdleMs}ms — force-disconnecting session`);
postCompletionWatchdogTriggered = true;
void session.disconnect().catch(err => {
log(`warning: post-completion watchdog disconnect failed: ${err instanceof Error ? err.message : String(err)}`);
log(`warning: post-completion watchdog disconnect failed: ${getErrorMessage(err)}`);
});
}, postCompletionIdleMs);
} else {
Expand Down
7 changes: 4 additions & 3 deletions actions/setup/js/create_forecast_issue.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

const fs = require("node:fs");
const { getPromptPath, renderTemplateFromFile } = require("./messages_core.cjs");
const { getErrorMessage } = require("./error_helpers.cjs");

const FORECAST_REPORT_PATH = "./.cache/gh-aw/forecast/report.json";
const FORECAST_ERROR_PATH = "./.cache/gh-aw/forecast/error.json";
Expand Down Expand Up @@ -275,7 +276,7 @@ async function main() {
reportBody = fs.readFileSync(FORECAST_REPORT_PATH, "utf8").trim();
} catch (error) {
outcome = "error";
errorMessage = `Failed to read forecast report JSON at ${FORECAST_REPORT_PATH}: ${error.message}`;
errorMessage = `Failed to read forecast report JSON at ${FORECAST_REPORT_PATH}: ${getErrorMessage(error)}`;
core.warning(errorMessage);
}

Expand All @@ -284,7 +285,7 @@ async function main() {
report = JSON.parse(reportBody);
} catch (error) {
outcome = "error";
errorMessage = `Failed to parse forecast report JSON at ${FORECAST_REPORT_PATH}: ${error.message}`;
errorMessage = `Failed to parse forecast report JSON at ${FORECAST_REPORT_PATH}: ${getErrorMessage(error)}`;
core.warning(errorMessage);
}
} else if (!errorMessage) {
Expand Down Expand Up @@ -316,7 +317,7 @@ async function main() {
errorMessage = errorPayload.message.trim();
}
} catch (error) {
core.warning(`Failed to parse forecast error JSON at ${FORECAST_ERROR_PATH}: ${error.message}`);
core.warning(`Failed to parse forecast error JSON at ${FORECAST_ERROR_PATH}: ${getErrorMessage(error)}`);
}
}

Expand Down
2 changes: 1 addition & 1 deletion actions/setup/js/create_issue.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@ async function main(config = {}) {
});
core.info("✓ Added comment to parent issue #" + effectiveParentIssueNumber + " (sub-issue linking not available)");
} catch (commentError) {
core.info(`Warning: Could not add comment to parent issue: ${commentError instanceof Error ? commentError.message : String(commentError)}`);
core.info(`Warning: Could not add comment to parent issue: ${getErrorMessage(commentError)}`);
}
}
} else if (effectiveParentIssueNumber && effectiveParentRepo !== qualifiedItemRepo) {
Expand Down
Loading
Loading