@@ -84,44 +84,25 @@ async function main() {
8484
8585 try {
8686 switch ( eventName ) {
87- case "issues" : {
88- const number = context . payload ?. issue ?. number ;
89- if ( ! number ) {
90- core . setFailed ( `${ ERR_NOT_FOUND } : Issue number not found in event payload` ) ;
91- return ;
92- }
93- commentEndpoint = `/repos/${ owner } /${ repo } /issues/${ number } /comments` ;
94- break ;
95- }
96-
87+ case "issues" :
9788 case "issue_comment" : {
9889 const number = context . payload ?. issue ?. number ;
9990 if ( ! number ) {
10091 core . setFailed ( `${ ERR_NOT_FOUND } : Issue number not found in event payload` ) ;
10192 return ;
10293 }
103- // Create new comment on the issue itself, not on the comment
104- commentEndpoint = `/repos/${ owner } /${ repo } /issues/${ number } /comments` ;
105- break ;
106- }
107-
108- case "pull_request" : {
109- const number = context . payload ?. pull_request ?. number ;
110- if ( ! number ) {
111- core . setFailed ( `${ ERR_NOT_FOUND } : Pull request number not found in event payload` ) ;
112- return ;
113- }
11494 commentEndpoint = `/repos/${ owner } /${ repo } /issues/${ number } /comments` ;
11595 break ;
11696 }
11797
98+ case "pull_request" :
11899 case "pull_request_review_comment" : {
119100 const number = context . payload ?. pull_request ?. number ;
120101 if ( ! number ) {
121102 core . setFailed ( `${ ERR_NOT_FOUND } : Pull request number not found in event payload` ) ;
122103 return ;
123104 }
124- // Create new comment on the PR itself (using issues endpoint since PRs are issues)
105+ // PRs use the issues comment endpoint
125106 commentEndpoint = `/repos/${ owner } /${ repo } /issues/${ number } /comments` ;
126107 break ;
127108 }
@@ -156,123 +137,118 @@ async function main() {
156137 await addCommentWithWorkflowLink ( commentEndpoint , runUrl , eventName ) ;
157138 } catch ( error ) {
158139 const errorMessage = getErrorMessage ( error ) ;
159- core . error ( `Failed to create comment: ${ errorMessage } ` ) ;
160140 // Don't fail the job - just warn since this is not critical
161141 core . warning ( `Failed to create comment with workflow link: ${ errorMessage } ` ) ;
162142 }
163143}
164144
165145/**
166- * Add a comment with a workflow run link
167- * @param {string } endpoint - The GitHub API endpoint to create the comment (or special format for discussions)
146+ * Build the comment body text for a workflow run link.
147+ * Sanitizes the content and appends all required markers.
148+ * @param {string } eventName - The event type
168149 * @param {string } runUrl - The URL of the workflow run
169- * @param {string } eventName - The event type (to determine the comment text)
150+ * @returns {string } The assembled comment body
170151 */
171- async function addCommentWithWorkflowLink ( endpoint , runUrl , eventName ) {
172- // Get workflow name from environment variable
152+ function buildCommentBody ( eventName , runUrl ) {
173153 const workflowName = process . env . GH_AW_WORKFLOW_NAME || "Workflow" ;
174-
175- // Determine the event type description using lookup object
176154 const eventTypeDescription = EVENT_TYPE_DESCRIPTIONS [ eventName ] ?? "event" ;
177155
178- // Use getRunStartedMessage for the workflow link text (supports custom messages)
179- const workflowLinkText = getRunStartedMessage ( {
180- workflowName : workflowName ,
181- runUrl : runUrl ,
182- eventType : eventTypeDescription ,
183- } ) ;
184-
185- // Sanitize the workflow link text to prevent injection attacks (defense in depth for custom message templates)
186- // This must happen BEFORE adding workflow markers to preserve them
187- let commentBody = sanitizeContent ( workflowLinkText ) ;
156+ // Sanitize before adding markers (defense in depth for custom message templates)
157+ let body = sanitizeContent ( getRunStartedMessage ( { workflowName, runUrl, eventType : eventTypeDescription } ) ) ;
188158
189159 // Add lock notice if lock-for-agent is enabled for issues or issue_comment
190- const lockForAgent = process . env . GH_AW_LOCK_FOR_AGENT === "true" ;
191- if ( lockForAgent && ( eventName === "issues" || eventName === "issue_comment" ) ) {
192- commentBody += "\n\n🔒 This issue has been locked while the workflow is running to prevent concurrent modifications." ;
160+ if ( process . env . GH_AW_LOCK_FOR_AGENT === "true" && ( eventName === "issues" || eventName === "issue_comment" ) ) {
161+ body += "\n\n🔒 This issue has been locked while the workflow is running to prevent concurrent modifications." ;
193162 }
194163
195- // Add workflow-id and tracker-id markers for hide-older-comments feature
164+ // Add workflow-id marker for hide-older-comments feature
196165 const workflowId = process . env . GITHUB_WORKFLOW || "" ;
197- const trackerId = process . env . GH_AW_TRACKER_ID || "" ;
198-
199- // Add workflow-id marker if available
200166 if ( workflowId ) {
201- commentBody += `\n\n${ generateWorkflowIdMarker ( workflowId ) } ` ;
167+ body += `\n\n${ generateWorkflowIdMarker ( workflowId ) } ` ;
202168 }
203169
204- // Add tracker-id marker if available (for backwards compatibility)
170+ // Add tracker-id marker for backwards compatibility
171+ const trackerId = process . env . GH_AW_TRACKER_ID || "" ;
205172 if ( trackerId ) {
206- commentBody += `\n\n<!-- gh-aw-tracker-id: ${ trackerId } -->` ;
173+ body += `\n\n<!-- gh-aw-tracker-id: ${ trackerId } -->` ;
207174 }
208175
209- // Add comment type marker to identify this as a reaction comment
210- // This prevents it from being hidden by hide-older-comments
211- commentBody += `\n\n<!-- gh-aw-comment-type: reaction -->` ;
176+ // Identify this as a reaction comment (prevents it from being hidden by hide-older-comments)
177+ body += `\n\n<!-- gh-aw-comment-type: reaction -->` ;
212178
213- // Handle discussion events specially
214- if ( eventName === "discussion" ) {
215- // Parse discussion number from special format: "discussion:NUMBER"
216- const discussionNumber = parseInt ( endpoint . split ( ":" ) [ 1 ] , 10 ) ;
179+ return body ;
180+ }
217181
218- // Get discussion node ID using helper function
219- const discussionId = await getDiscussionNodeId ( discussionNumber ) ;
182+ /**
183+ * Post a GraphQL comment to a discussion, optionally as a threaded reply.
184+ * @param {number } discussionNumber - The discussion number
185+ * @param {string } commentBody - The comment body
186+ * @param {string|null } replyToNodeId - Parent comment node ID for threading (null for top-level)
187+ */
188+ async function postDiscussionComment ( discussionNumber , commentBody , replyToNodeId = null ) {
189+ const discussionId = await getDiscussionNodeId ( discussionNumber ) ;
220190
221- const result = await github . graphql (
191+ /** @type {any } */
192+ let result ;
193+ if ( replyToNodeId ) {
194+ result = await github . graphql (
195+ `
196+ mutation($dId: ID!, $body: String!, $replyToId: ID!) {
197+ addDiscussionComment(input: { discussionId: $dId, body: $body, replyToId: $replyToId }) {
198+ comment { id url }
199+ }
200+ }` ,
201+ { dId : discussionId , body : commentBody , replyToId : replyToNodeId }
202+ ) ;
203+ } else {
204+ result = await github . graphql (
222205 `
223206 mutation($dId: ID!, $body: String!) {
224207 addDiscussionComment(input: { discussionId: $dId, body: $body }) {
225- comment {
226- id
227- url
228- }
208+ comment { id url }
229209 }
230210 }` ,
231211 { dId : discussionId , body : commentBody }
232212 ) ;
213+ }
233214
234- const comment = result . addDiscussionComment . comment ;
235- setCommentOutputs ( comment . id , comment . url ) ;
215+ const comment = result . addDiscussionComment . comment ;
216+ setCommentOutputs ( comment . id , comment . url ) ;
217+ }
218+
219+ /**
220+ * Add a comment with a workflow run link
221+ * @param {string } endpoint - The GitHub API endpoint to create the comment (or special format for discussions)
222+ * @param {string } runUrl - The URL of the workflow run
223+ * @param {string } eventName - The event type (to determine the comment text)
224+ */
225+ async function addCommentWithWorkflowLink ( endpoint , runUrl , eventName ) {
226+ const commentBody = buildCommentBody ( eventName , runUrl ) ;
227+
228+ if ( eventName === "discussion" ) {
229+ // Parse discussion number from special format: "discussion:NUMBER"
230+ const discussionNumber = parseInt ( endpoint . split ( ":" ) [ 1 ] , 10 ) ;
231+ await postDiscussionComment ( discussionNumber , commentBody ) ;
236232 return ;
237- } else if ( eventName === "discussion_comment" ) {
233+ }
234+
235+ if ( eventName === "discussion_comment" ) {
238236 // Parse discussion number from special format: "discussion_comment:NUMBER:COMMENT_ID"
239237 const discussionNumber = parseInt ( endpoint . split ( ":" ) [ 1 ] , 10 ) ;
240238
241- // Get discussion node ID using helper function
242- const discussionId = await getDiscussionNodeId ( discussionNumber ) ;
243-
244- // Get the comment node ID to use as the parent for threading.
245- // GitHub Discussions only supports two nesting levels, so if the triggering comment is
246- // itself a reply, we resolve the top-level parent's node ID.
239+ // GitHub Discussions only supports two nesting levels, so resolve the top-level parent's node ID
247240 const commentNodeId = await resolveTopLevelDiscussionCommentId ( github , context . payload ?. comment ?. node_id ) ;
248-
249- const result = await github . graphql (
250- `
251- mutation($dId: ID!, $body: String!, $replyToId: ID!) {
252- addDiscussionComment(input: { discussionId: $dId, body: $body, replyToId: $replyToId }) {
253- comment {
254- id
255- url
256- }
257- }
258- }` ,
259- { dId : discussionId , body : commentBody , replyToId : commentNodeId }
260- ) ;
261-
262- const comment = result . addDiscussionComment . comment ;
263- setCommentOutputs ( comment . id , comment . url ) ;
241+ await postDiscussionComment ( discussionNumber , commentBody , commentNodeId ) ;
264242 return ;
265243 }
266244
267245 // Create a new comment for non-discussion events
268246 const createResponse = await github . request ( "POST " + endpoint , {
269247 body : commentBody ,
270- headers : {
271- Accept : "application/vnd.github+json" ,
272- } ,
248+ headers : { Accept : "application/vnd.github+json" } ,
273249 } ) ;
274250
275251 setCommentOutputs ( createResponse . data . id , createResponse . data . html_url ) ;
276252}
277253
278- module . exports = { main, addCommentWithWorkflowLink } ;
254+ module . exports = { main, addCommentWithWorkflowLink, buildCommentBody , postDiscussionComment } ;
0 commit comments