Skip to content

Commit 742ca9c

Browse files
chore: sync actions from gh-aw@v0.65.7 (#64)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 2f59ed4 commit 742ca9c

6 files changed

Lines changed: 87 additions & 64 deletions

setup/js/add_reaction_and_edit_comment.cjs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ async function main() {
5454

5555
let reactionEndpoint;
5656
let commentUpdateEndpoint;
57-
let shouldCreateComment = false;
5857
const eventName = context.eventName;
5958
const owner = context.repo.owner;
6059
const repo = context.repo.repo;
@@ -69,7 +68,6 @@ async function main() {
6968
}
7069
reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`;
7170
commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`;
72-
shouldCreateComment = true;
7371
break;
7472
}
7573

@@ -87,7 +85,6 @@ async function main() {
8785
reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`;
8886
// Create new comment on the issue itself, not on the comment
8987
commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumberForComment}/comments`;
90-
shouldCreateComment = true;
9188
break;
9289
}
9390

@@ -100,7 +97,6 @@ async function main() {
10097
// PRs are "issues" for the reactions endpoint
10198
reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`;
10299
commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`;
103-
shouldCreateComment = true;
104100
break;
105101
}
106102

@@ -118,7 +114,6 @@ async function main() {
118114
reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`;
119115
// Create new comment on the PR itself (using issues endpoint since PRs are issues)
120116
commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumberForReviewComment}/comments`;
121-
shouldCreateComment = true;
122117
break;
123118
}
124119

@@ -132,7 +127,6 @@ async function main() {
132127
const discussion = await getDiscussionId(owner, repo, discussionNumber);
133128
reactionEndpoint = discussion.id; // Store node ID for GraphQL
134129
commentUpdateEndpoint = `discussion:${discussionNumber}`; // Special format to indicate discussion
135-
shouldCreateComment = true;
136130
break;
137131
}
138132

@@ -150,7 +144,6 @@ async function main() {
150144
}
151145
reactionEndpoint = commentNodeId; // Store node ID for GraphQL
152146
commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; // Special format
153-
shouldCreateComment = true;
154147
break;
155148
}
156149

@@ -162,18 +155,15 @@ async function main() {
162155
core.info(`Reaction API endpoint: ${reactionEndpoint}`);
163156

164157
// For discussions, reactionEndpoint is a node ID (GraphQL), otherwise it's a REST API path
165-
const isDiscussionEvent = eventName === "discussion" || eventName === "discussion_comment";
166-
if (isDiscussionEvent) {
158+
if (eventName === "discussion" || eventName === "discussion_comment") {
167159
await addDiscussionReaction(reactionEndpoint, reaction);
168160
} else {
169161
await addReaction(reactionEndpoint, reaction);
170162
}
171163

172-
if (shouldCreateComment && commentUpdateEndpoint) {
164+
if (commentUpdateEndpoint) {
173165
core.info(`Comment endpoint: ${commentUpdateEndpoint}`);
174166
await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName);
175-
} else {
176-
core.info(`Skipping comment for event type: ${eventName}`);
177167
}
178168
} catch (error) {
179169
const errorMessage = getErrorMessage(error);
@@ -309,29 +299,19 @@ async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) {
309299
eventType: eventTypeDescription,
310300
});
311301

312-
// Sanitize before adding workflow markers to preserve them
313-
let commentBody = sanitizeContent(workflowLinkText);
314-
315-
// Add lock notice if lock-for-agent is enabled for issues or issue_comment
316302
const lockForAgent = process.env.GH_AW_LOCK_FOR_AGENT === "true";
317-
if (lockForAgent && (eventName === "issues" || eventName === "issue_comment")) {
318-
commentBody += "\n\n🔒 This issue has been locked while the workflow is running to prevent concurrent modifications.";
319-
}
320-
321303
const workflowId = process.env.GITHUB_WORKFLOW || "";
322304
const trackerId = process.env.GH_AW_TRACKER_ID || "";
323305

324-
if (workflowId) {
325-
commentBody += `\n\n${generateWorkflowIdMarker(workflowId)}`;
326-
}
327-
328-
// Add tracker-id marker if available (for backwards compatibility)
329-
if (trackerId) {
330-
commentBody += `\n\n<!-- gh-aw-tracker-id: ${trackerId} -->`;
331-
}
332-
333-
// Add comment type marker to identify this as a reaction comment
334-
commentBody += `\n\n<!-- gh-aw-comment-type: reaction -->`;
306+
// Build comment body from parts, sanitizing first to preserve workflow markers
307+
const commentParts = [
308+
sanitizeContent(workflowLinkText),
309+
...(lockForAgent && (eventName === "issues" || eventName === "issue_comment") ? ["🔒 This issue has been locked while the workflow is running to prevent concurrent modifications."] : []),
310+
...(workflowId ? [generateWorkflowIdMarker(workflowId)] : []),
311+
...(trackerId ? [`<!-- gh-aw-tracker-id: ${trackerId} -->`] : []),
312+
"<!-- gh-aw-comment-type: reaction -->",
313+
];
314+
const commentBody = commentParts.join("\n\n");
335315

336316
if (eventName === "discussion") {
337317
// Parse discussion number from special format: "discussion:NUMBER"

setup/js/check_workflow_timestamp_api.cjs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
/// <reference types="@actions/github-script" />
33

44
/**
5-
* Check workflow lock file integrity using frontmatter hash validation.
5+
* Check for a stale workflow lock file using frontmatter hash comparison.
66
* This script verifies that the stored frontmatter hash in the lock file
7-
* matches the recomputed hash from the source .md file, regardless of
8-
* commit timestamps.
7+
* matches the recomputed hash from the source .md file, detecting cases where
8+
* the workflow was edited without recompiling the lock file. It does not
9+
* provide tamper protection — use code review to guard against intentional
10+
* modifications.
911
*
1012
* Supports both same-repo and cross-repo reusable workflow scenarios:
1113
* - Primary: GitHub API (uses GITHUB_WORKFLOW_REF to identify source repo)
@@ -33,17 +35,23 @@ async function main() {
3335
const workflowMdPath = `.github/workflows/${workflowBasename}.md`;
3436
const lockFilePath = `.github/workflows/${workflowFile}`;
3537

36-
core.info(`Checking workflow lock file integrity using frontmatter hash:`);
38+
core.info(`Checking for stale lock file using frontmatter hash:`);
3739
core.info(` Source: ${workflowMdPath}`);
3840
core.info(` Lock file: ${lockFilePath}`);
3941

40-
// Determine workflow source repository from GITHUB_WORKFLOW_REF for cross-repo support.
41-
// GITHUB_WORKFLOW_REF format: owner/repo/.github/workflows/file.yml@ref
42-
// This env var always reflects the repo where the workflow file is defined,
43-
// not the repo where the triggering event occurred (context.repo).
44-
// When running cross-repo via org rulesets, context.repo points to the target
45-
// repository, not the repository that defines the workflow files.
46-
const workflowEnvRef = process.env.GITHUB_WORKFLOW_REF || "";
42+
// Determine workflow source repository from the workflow ref for cross-repo support.
43+
//
44+
// For cross-repo workflow_call invocations (reusable workflows called from another repo),
45+
// the GITHUB_WORKFLOW_REF env var always points to the TOP-LEVEL CALLER's workflow, not
46+
// the reusable workflow being executed. This causes the script to look for lock files in
47+
// the wrong repository.
48+
//
49+
// The GitHub Actions expression ${{ github.workflow_ref }} is injected as GH_AW_CONTEXT_WORKFLOW_REF
50+
// by the compiler and correctly identifies the CURRENT reusable workflow's ref even in
51+
// cross-repo workflow_call scenarios. We prefer it over GITHUB_WORKFLOW_REF when available.
52+
//
53+
// Ref: https://github.com/github/gh-aw/issues/23935
54+
const workflowEnvRef = process.env.GH_AW_CONTEXT_WORKFLOW_REF || process.env.GITHUB_WORKFLOW_REF || "";
4755
const currentRepo = process.env.GITHUB_REPOSITORY || `${context.repo.owner}/${context.repo.repo}`;
4856

4957
// Parse owner, repo, and optional ref from GITHUB_WORKFLOW_REF as a single unit so that
@@ -70,7 +78,11 @@ async function main() {
7078
ref = undefined;
7179
}
7280

73-
core.info(`GITHUB_WORKFLOW_REF: ${workflowEnvRef || "(not set)"}`);
81+
const contextWorkflowRef = process.env.GH_AW_CONTEXT_WORKFLOW_REF;
82+
core.info(`GITHUB_WORKFLOW_REF: ${process.env.GITHUB_WORKFLOW_REF || "(not set)"}`);
83+
if (contextWorkflowRef) {
84+
core.info(`GH_AW_CONTEXT_WORKFLOW_REF: ${contextWorkflowRef} (used for source repo resolution)`);
85+
}
7486
core.info(`GITHUB_REPOSITORY: ${currentRepo}`);
7587
core.info(`Resolved source repo: ${owner}/${repo} @ ${ref || "(default branch)"}`);
7688

@@ -193,11 +205,11 @@ async function main() {
193205
if (!hashComparison) {
194206
// Could not compute hash - be conservative and fail
195207
core.warning("Could not compare frontmatter hashes - assuming lock file is outdated");
196-
const warningMessage = `Lock file '${lockFilePath}' integrity check failed! Could not verify frontmatter hash for '${workflowMdPath}'. Run 'gh aw compile' to regenerate the lock file.`;
208+
const warningMessage = `Lock file '${lockFilePath}' is outdated or unverifiable! Could not verify frontmatter hash for '${workflowMdPath}'. Run 'gh aw compile' to regenerate the lock file.`;
197209

198210
let summary = core.summary
199211
.addRaw("### ⚠️ Workflow Lock File Warning\n\n")
200-
.addRaw("**WARNING**: Lock file integrity check failed. Could not verify frontmatter hash.\n\n")
212+
.addRaw("**WARNING**: Could not verify whether lock file is up to date. Frontmatter hash check failed.\n\n")
201213
.addRaw("**Files:**\n")
202214
.addRaw(`- Source: \`${workflowMdPath}\`\n`)
203215
.addRaw(`- Lock: \`${lockFilePath}\`\n\n`)

setup/js/messages_footer.cjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ function getFooterAgentFailureIssueMessage(ctx) {
205205

206206
// Default footer template with link to workflow run
207207
let defaultFooter = "> Generated from [{workflow_name}]({agentic_workflow_url})";
208+
// Append effective tokens with ● symbol when available (compact format, no "ET" label)
209+
if (effectiveTokens) {
210+
defaultFooter += `{effective_tokens_suffix}`;
211+
}
208212
// Append history link when available
209213
if (ctx.historyUrl) {
210214
defaultFooter += " · [◷]({history_url})";
@@ -239,6 +243,10 @@ function getFooterAgentFailureCommentMessage(ctx) {
239243

240244
// Default footer template with link to workflow run
241245
let defaultFooter = "> Generated from [{workflow_name}]({agentic_workflow_url})";
246+
// Append effective tokens with ● symbol when available (compact format, no "ET" label)
247+
if (effectiveTokens) {
248+
defaultFooter += `{effective_tokens_suffix}`;
249+
}
242250
// Append history link when available
243251
if (ctx.historyUrl) {
244252
defaultFooter += " · [◷]({history_url})";

setup/js/pr_helpers.cjs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,33 @@
33
/**
44
* Detect if a pull request is from a fork repository.
55
*
6-
* Uses multiple signals for robust detection:
7-
* 1. Check if head.repo.fork is explicitly true (GitHub's fork flag)
8-
* 2. Compare repository full names if both repos exist
9-
* 3. Handle deleted fork case (head.repo is null)
6+
* A "fork PR" means the head and base are in *different* repositories
7+
* (cross-repo PR). Detection uses two signals:
8+
* 1. Handle deleted fork case (head.repo is null)
9+
* 2. Compare repository full names — different names mean cross-repo
10+
*
11+
* NOTE: We intentionally do NOT check head.repo.fork. That flag indicates
12+
* whether the repository *itself* is a fork of another repo, not whether
13+
* the PR is cross-repo. A same-repo PR in a forked repository (common in
14+
* OSS) would have fork=true but is NOT a cross-repo fork PR. Using that
15+
* flag caused false positives that forced `gh pr checkout` instead of fast
16+
* `git fetch`, which then failed due to stale GH_HOST values. See #24208.
1017
*
1118
* @param {object} pullRequest - The pull request object from GitHub context
1219
* @returns {{isFork: boolean, reason: string}} Fork detection result with reason
1320
*/
1421
function detectForkPR(pullRequest) {
15-
let isFork = false;
16-
let reason = "same repository";
17-
1822
if (!pullRequest.head?.repo) {
1923
// Head repo is null - likely a deleted fork
20-
isFork = true;
21-
reason = "head repository deleted (was likely a fork)";
22-
} else if (pullRequest.head.repo.fork === true) {
23-
// GitHub's explicit fork flag
24-
isFork = true;
25-
reason = "head.repo.fork flag is true";
26-
} else if (pullRequest.head.repo.full_name !== pullRequest.base?.repo?.full_name) {
27-
// Different repository names
28-
isFork = true;
29-
reason = "different repository names";
24+
return { isFork: true, reason: "head repository deleted (was likely a fork)" };
25+
}
26+
27+
if (pullRequest.head.repo.full_name !== pullRequest.base?.repo?.full_name) {
28+
// Different repository names — this is a cross-repo (fork) PR
29+
return { isFork: true, reason: "different repository names" };
3030
}
3131

32-
return { isFork, reason };
32+
return { isFork: false, reason: "same repository" };
3333
}
3434

3535
/**

setup/md/agent_failure_issue.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,13 @@ Debug this workflow failure using your favorite Agent CLI and the `agentic-workf
3535
</details>
3636

3737
> [!TIP]
38+
> <details>
39+
> <summary><b>Stop reporting this workflow as a failure</b></summary>
40+
>
3841
> To stop a workflow from creating failure issues, set `report-failure-as-issue: false` in its frontmatter:
3942
> ```yaml
4043
> safe-outputs:
4144
> report-failure-as-issue: false
4245
> ```
46+
>
47+
> </details>

setup/sh/configure_gh_for_ghe.sh

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,27 @@ main() {
6262
local github_host
6363
github_host=$(detect_github_host)
6464

65-
# If the host is github.com, no configuration is needed
65+
# If the host is github.com, no GHE configuration is needed.
66+
# However, we must clear any stale GH_HOST value to prevent gh CLI
67+
# from targeting the wrong host (e.g., a leftover localhost:18443
68+
# from a prior DIFC proxy run). See #24208.
6669
if [ "$github_host" = "github.com" ]; then
70+
if [ -n "${GH_HOST:-}" ] && [ "${GH_HOST}" != "github.com" ]; then
71+
echo "Clearing stale GH_HOST=${GH_HOST} (expected github.com)"
72+
unset GH_HOST
73+
if [ -n "${GITHUB_ENV:-}" ]; then
74+
echo "GH_HOST=github.com" >> "${GITHUB_ENV}"
75+
fi
76+
fi
6777
echo "Using public GitHub (github.com) - no additional gh configuration needed"
78+
# Clear any stale GH_HOST to prevent gh CLI mismatches
79+
if [ -n "${GH_HOST:-}" ] && [ "${GH_HOST}" != "github.com" ]; then
80+
echo "Clearing stale GH_HOST" >&2
81+
unset GH_HOST
82+
if [ -n "${GITHUB_ENV:-}" ]; then
83+
echo "GH_HOST=" >> "${GITHUB_ENV}"
84+
fi
85+
fi
6886
return 0
6987
fi
7088

0 commit comments

Comments
 (0)