From 4a8b37c9262c6517fc3aada295bfb0a5c45df703 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 2 Sep 2025 21:13:27 +0100 Subject: [PATCH 1/3] allow target of add-issue-comment --- docs/safe-outputs.md | 22 +++- pkg/parser/schemas/main_workflow_schema.json | 10 ++ pkg/workflow/compiler.go | 35 +++++- pkg/workflow/js/create_comment.cjs | 53 +++++++-- pkg/workflow/output_test.go | 115 +++++++++++++++++++ 5 files changed, 219 insertions(+), 16 deletions(-) diff --git a/docs/safe-outputs.md b/docs/safe-outputs.md index 28612e20352..daae47b5b1f 100644 --- a/docs/safe-outputs.md +++ b/docs/safe-outputs.md @@ -11,6 +11,16 @@ The `safe-outputs:` element of your workflow's frontmatter declares that your ag 2. The compiler automatically generates additional jobs that read this output and perform the requested actions 3. Only these generated jobs receive the necessary write permissions +For example: + +```yaml +safe-outputs: + create-issue: + add-issue-comment: +``` + +This declares that the workflow should create at most one new issue and add at most one comment to the triggering issue or pull request based on the agentic workflow's output. + ## Available Output Types ### New Issue Creation (`create-issue:` / `create-issues:`) @@ -53,7 +63,7 @@ The compiled workflow will have additional prompting describing that, to create ### Issue Comment Creation (`add-issue-comment:` / `add-issue-comments:`) -Adding comment creation to the `safe-outputs:` section declares that the workflow should conclude with posting comments on the triggering issue or pull request based on the workflow's output. +Adding comment creation to the `safe-outputs:` section declares that the workflow should conclude with posting comments based on the workflow's output. By default, comments are posted on the triggering issue or pull request, but this can be configured using the `target` option. **Singular Form (adds exactly one comment):** ```yaml @@ -68,6 +78,16 @@ safe-outputs: max: 3 # Optional: maximum number of comments (default: 10) ``` +**Configuration options:** +```yaml +safe-outputs: + add-issue-comment: + target: "*" # Optional: target for comments + # "triggering" (default) - only comment on triggering issue/PR + # "*" - allow comments on any issue (requires issue_number in agent output) + # explicit number - comment on specific issue number +``` + The agentic part of your workflow should describe the comment(s) it wants posted. **Example natural language to generate the output:** diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 3298e95c05c..3b97968d08c 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -1046,6 +1046,12 @@ { "type": "object", "description": "Configuration for creating GitHub issue/PR comments from agentic workflow output", + "properties": { + "target": { + "type": "string", + "description": "Target for comments: 'triggering' (default), '*' (any issue), or explicit issue number" + } + }, "additionalProperties": false }, { @@ -1065,6 +1071,10 @@ "description": "Maximum number of comments to create (default: 10)", "minimum": 1, "maximum": 100 + }, + "target": { + "type": "string", + "description": "Target for comments: 'triggering' (default), '*' (any issue), or explicit issue number" } }, "additionalProperties": false diff --git a/pkg/workflow/compiler.go b/pkg/workflow/compiler.go index c51e4244391..d8e46332197 100644 --- a/pkg/workflow/compiler.go +++ b/pkg/workflow/compiler.go @@ -163,7 +163,8 @@ type AddIssueCommentConfig struct { // AddIssueCommentsConfig holds configuration for creating GitHub issue/PR comments from agent output type AddIssueCommentsConfig struct { - Max int `yaml:"max,omitempty"` // Maximum number of comments to create + Max int `yaml:"max,omitempty"` // Maximum number of comments to create + Target string `yaml:"target,omitempty"` // Target for comments: "triggering" (default), "*" (any issue), or explicit issue number } // CreatePullRequestsConfig holds configuration for creating GitHub pull requests from agent output @@ -1786,6 +1787,10 @@ func (c *Compiler) buildCreateOutputAddIssueCommentJob(data *WorkflowData, mainJ steps = append(steps, " env:\n") // Pass the agent output content from the main job steps = append(steps, fmt.Sprintf(" GITHUB_AW_AGENT_OUTPUT: ${{ needs.%s.outputs.output }}\n", mainJobName)) + // Pass the comment target configuration + if data.SafeOutputs.AddIssueComments.Target != "" { + steps = append(steps, fmt.Sprintf(" GITHUB_AW_COMMENT_TARGET: %q\n", data.SafeOutputs.AddIssueComments.Target)) + } steps = append(steps, " with:\n") steps = append(steps, " script: |\n") @@ -1800,9 +1805,19 @@ func (c *Compiler) buildCreateOutputAddIssueCommentJob(data *WorkflowData, mainJ "comment_url": "${{ steps.create_comment.outputs.comment_url }}", } + // Determine the job condition based on target configuration + var jobCondition string + if data.SafeOutputs.AddIssueComments.Target == "*" { + // Allow the job to run in any context when target is "*" + jobCondition = "if: always()" // This allows the job to run even without triggering issue/PR + } else { + // Default behavior: only run in issue or PR context + jobCondition = "if: github.event.issue.number || github.event.pull_request.number" + } + job := &Job{ Name: "create_issue_comment", - If: "if: github.event.issue.number || github.event.pull_request.number", // Only run in issue or PR context + If: jobCondition, RunsOn: "runs-on: ubuntu-latest", Permissions: "permissions:\n contents: read\n issues: write\n pull-requests: write", TimeoutMinutes: 10, // 10-minute timeout as required @@ -2623,6 +2638,13 @@ func (c *Compiler) parseCommentsConfig(outputMap map[string]any) *AddIssueCommen } } } + + // Parse target field (for both singular and plural forms) + if target, exists := configMap["target"]; exists { + if targetStr, ok := target.(string); ok { + commentsConfig.Target = targetStr + } + } } return commentsConfig @@ -2981,7 +3003,14 @@ func (c *Compiler) generateOutputCollectionStep(yaml *strings.Builder, data *Wor safeOutputsConfig["create-issue"] = true } if data.SafeOutputs.AddIssueComments != nil { - safeOutputsConfig["add-issue-comment"] = true + // Pass the full comment configuration including target + commentConfig := map[string]interface{}{ + "enabled": true, + } + if data.SafeOutputs.AddIssueComments.Target != "" { + commentConfig["target"] = data.SafeOutputs.AddIssueComments.Target + } + safeOutputsConfig["add-issue-comment"] = commentConfig } if data.SafeOutputs.CreatePullRequests != nil { safeOutputsConfig["create-pull-request"] = true diff --git a/pkg/workflow/js/create_comment.cjs b/pkg/workflow/js/create_comment.cjs index 979de66118f..1bfcf5a79d5 100644 --- a/pkg/workflow/js/create_comment.cjs +++ b/pkg/workflow/js/create_comment.cjs @@ -36,12 +36,17 @@ async function main() { console.log(`Found ${commentItems.length} add-issue-comment item(s)`); + // Get the target configuration from environment variable + const commentTarget = process.env.GITHUB_AW_COMMENT_TARGET || "triggering"; + console.log(`Comment target configuration: ${commentTarget}`); + // Check if we're in an issue or pull request context const isIssueContext = context.eventName === 'issues' || context.eventName === 'issue_comment'; const isPRContext = context.eventName === 'pull_request' || context.eventName === 'pull_request_review' || context.eventName === 'pull_request_review_comment'; - if (!isIssueContext && !isPRContext) { - console.log('Not running in issue or pull request context, skipping comment creation'); + // Validate context based on target configuration + if (commentTarget === "triggering" && !isIssueContext && !isPRContext) { + console.log('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); return; } @@ -56,22 +61,46 @@ async function main() { let issueNumber; let commentEndpoint; - if (isIssueContext) { - if (context.payload.issue) { - issueNumber = context.payload.issue.number; + if (commentTarget === "*") { + // For target "*", we need an explicit issue number from the comment item + if (commentItem.issue_number) { + issueNumber = parseInt(commentItem.issue_number, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number specified: ${commentItem.issue_number}`); + continue; + } commentEndpoint = 'issues'; } else { - console.log('Issue context detected but no issue found in payload'); + console.log('Target is "*" but no issue_number specified in comment item'); continue; } - } else if (isPRContext) { - if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - commentEndpoint = 'issues'; // PR comments use the issues API endpoint - } else { - console.log('Pull request context detected but no pull request found in payload'); + } else if (commentTarget && commentTarget !== "triggering") { + // Explicit issue number specified in target + issueNumber = parseInt(commentTarget, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number in target configuration: ${commentTarget}`); continue; } + commentEndpoint = 'issues'; + } else { + // Default behavior: use triggering issue/PR + if (isIssueContext) { + if (context.payload.issue) { + issueNumber = context.payload.issue.number; + commentEndpoint = 'issues'; + } else { + console.log('Issue context detected but no issue found in payload'); + continue; + } + } else if (isPRContext) { + if (context.payload.pull_request) { + issueNumber = context.payload.pull_request.number; + commentEndpoint = 'issues'; // PR comments use the issues API endpoint + } else { + console.log('Pull request context detected but no pull request found in payload'); + continue; + } + } } if (!issueNumber) { diff --git a/pkg/workflow/output_test.go b/pkg/workflow/output_test.go index 65fc0d26114..9992370c8ba 100644 --- a/pkg/workflow/output_test.go +++ b/pkg/workflow/output_test.go @@ -387,6 +387,121 @@ This workflow tests the output.add-issue-comment configuration parsing with null } } +func TestOutputCommentConfigTargetParsing(t *testing.T) { + // Create temporary directory for test files + tmpDir, err := os.MkdirTemp("", "output-comment-target-test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // Test case with target: "*" + testContent := `--- +on: + issues: + types: [opened] +permissions: + contents: read + issues: write + pull-requests: write +engine: claude +safe-outputs: + add-issue-comment: + target: "*" +--- + +# Test Output Issue Comment Target Configuration + +This workflow tests the output.add-issue-comment target configuration parsing. +` + + testFile := filepath.Join(tmpDir, "test-output-issue-comment-target.md") + if err := os.WriteFile(testFile, []byte(testContent), 0644); err != nil { + t.Fatal(err) + } + + compiler := NewCompiler(false, "", "test") + + // Parse the workflow data + workflowData, err := compiler.parseWorkflowFile(testFile) + if err != nil { + t.Fatalf("Unexpected error parsing workflow with target comment config: %v", err) + } + + // Verify output configuration is parsed correctly + if workflowData.SafeOutputs == nil { + t.Fatal("Expected output configuration to be parsed") + } + + if workflowData.SafeOutputs.AddIssueComments == nil { + t.Fatal("Expected issue_comment configuration to be parsed") + } + + if workflowData.SafeOutputs.AddIssueComments.Target != "*" { + t.Fatalf("Expected target to be '*', got '%s'", workflowData.SafeOutputs.AddIssueComments.Target) + } +} + +func TestOutputCommentPluralTargetParsing(t *testing.T) { + // Create temporary directory for test files + tmpDir, err := os.MkdirTemp("", "output-comment-plural-target-test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // Test case with plural form and target configuration + testContent := `--- +on: + issues: + types: [opened] +permissions: + contents: read + issues: write + pull-requests: write +engine: claude +safe-outputs: + add-issue-comments: + max: 3 + target: "123" +--- + +# Test Output Issue Comments Plural Target Configuration + +This workflow tests the add-issue-comments plural target configuration parsing. +` + + testFile := filepath.Join(tmpDir, "test-output-issue-comments-target.md") + if err := os.WriteFile(testFile, []byte(testContent), 0644); err != nil { + t.Fatal(err) + } + + compiler := NewCompiler(false, "", "test") + + // Parse the workflow data + workflowData, err := compiler.parseWorkflowFile(testFile) + if err != nil { + t.Fatalf("Unexpected error parsing workflow with plural target comment config: %v", err) + } + + // Verify output configuration is parsed correctly + if workflowData.SafeOutputs == nil { + t.Fatal("Expected output configuration to be parsed") + } + + if workflowData.SafeOutputs.AddIssueComments == nil { + t.Fatal("Expected issue_comment configuration to be parsed") + } + + if workflowData.SafeOutputs.AddIssueComments.Max != 3 { + t.Fatalf("Expected max to be 3, got %d", workflowData.SafeOutputs.AddIssueComments.Max) + } + + if workflowData.SafeOutputs.AddIssueComments.Target != "123" { + t.Fatalf("Expected target to be '123', got '%s'", workflowData.SafeOutputs.AddIssueComments.Target) + } +} + func TestOutputCommentJobGeneration(t *testing.T) { // Create temporary directory for test files tmpDir, err := os.MkdirTemp("", "output-comment-job-test") From 599805be3fe2e7ee8c15edb49d1e9d49b037d44f Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 2 Sep 2025 21:15:00 +0100 Subject: [PATCH 2/3] allow target of add-issue-comment --- .../test-claude-add-issue-comment.lock.yml | 54 ++++++++++++++----- .github/workflows/test-claude-alias.lock.yml | 54 ++++++++++++++----- .../test-codex-add-issue-comment.lock.yml | 54 ++++++++++++++----- .github/workflows/test-codex-alias.lock.yml | 54 ++++++++++++++----- .github/workflows/test-proxy.lock.yml | 54 ++++++++++++++----- 5 files changed, 205 insertions(+), 65 deletions(-) diff --git a/.github/workflows/test-claude-add-issue-comment.lock.yml b/.github/workflows/test-claude-add-issue-comment.lock.yml index 0b4f49479ea..07ffdb39937 100644 --- a/.github/workflows/test-claude-add-issue-comment.lock.yml +++ b/.github/workflows/test-claude-add-issue-comment.lock.yml @@ -425,7 +425,7 @@ jobs: uses: actions/github-script@v7 env: GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }} - GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":true}" + GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":{\"enabled\":true}}" with: script: | async function main() { @@ -1126,11 +1126,15 @@ jobs: return; } console.log(`Found ${commentItems.length} add-issue-comment item(s)`); + // Get the target configuration from environment variable + const commentTarget = process.env.GITHUB_AW_COMMENT_TARGET || "triggering"; + console.log(`Comment target configuration: ${commentTarget}`); // Check if we're in an issue or pull request context const isIssueContext = context.eventName === 'issues' || context.eventName === 'issue_comment'; const isPRContext = context.eventName === 'pull_request' || context.eventName === 'pull_request_review' || context.eventName === 'pull_request_review_comment'; - if (!isIssueContext && !isPRContext) { - console.log('Not running in issue or pull request context, skipping comment creation'); + // Validate context based on target configuration + if (commentTarget === "triggering" && !isIssueContext && !isPRContext) { + console.log('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); return; } const createdComments = []; @@ -1141,22 +1145,46 @@ jobs: // Determine the issue/PR number and comment endpoint for this comment let issueNumber; let commentEndpoint; - if (isIssueContext) { - if (context.payload.issue) { - issueNumber = context.payload.issue.number; + if (commentTarget === "*") { + // For target "*", we need an explicit issue number from the comment item + if (commentItem.issue_number) { + issueNumber = parseInt(commentItem.issue_number, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number specified: ${commentItem.issue_number}`); + continue; + } commentEndpoint = 'issues'; } else { - console.log('Issue context detected but no issue found in payload'); + console.log('Target is "*" but no issue_number specified in comment item'); continue; } - } else if (isPRContext) { - if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - commentEndpoint = 'issues'; // PR comments use the issues API endpoint - } else { - console.log('Pull request context detected but no pull request found in payload'); + } else if (commentTarget && commentTarget !== "triggering") { + // Explicit issue number specified in target + issueNumber = parseInt(commentTarget, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number in target configuration: ${commentTarget}`); continue; } + commentEndpoint = 'issues'; + } else { + // Default behavior: use triggering issue/PR + if (isIssueContext) { + if (context.payload.issue) { + issueNumber = context.payload.issue.number; + commentEndpoint = 'issues'; + } else { + console.log('Issue context detected but no issue found in payload'); + continue; + } + } else if (isPRContext) { + if (context.payload.pull_request) { + issueNumber = context.payload.pull_request.number; + commentEndpoint = 'issues'; // PR comments use the issues API endpoint + } else { + console.log('Pull request context detected but no pull request found in payload'); + continue; + } + } } if (!issueNumber) { console.log('Could not determine issue or pull request number'); diff --git a/.github/workflows/test-claude-alias.lock.yml b/.github/workflows/test-claude-alias.lock.yml index b2700fabe56..81fc1e7d079 100644 --- a/.github/workflows/test-claude-alias.lock.yml +++ b/.github/workflows/test-claude-alias.lock.yml @@ -663,7 +663,7 @@ jobs: uses: actions/github-script@v7 env: GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }} - GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":true}" + GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":{\"enabled\":true}}" with: script: | async function main() { @@ -1364,11 +1364,15 @@ jobs: return; } console.log(`Found ${commentItems.length} add-issue-comment item(s)`); + // Get the target configuration from environment variable + const commentTarget = process.env.GITHUB_AW_COMMENT_TARGET || "triggering"; + console.log(`Comment target configuration: ${commentTarget}`); // Check if we're in an issue or pull request context const isIssueContext = context.eventName === 'issues' || context.eventName === 'issue_comment'; const isPRContext = context.eventName === 'pull_request' || context.eventName === 'pull_request_review' || context.eventName === 'pull_request_review_comment'; - if (!isIssueContext && !isPRContext) { - console.log('Not running in issue or pull request context, skipping comment creation'); + // Validate context based on target configuration + if (commentTarget === "triggering" && !isIssueContext && !isPRContext) { + console.log('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); return; } const createdComments = []; @@ -1379,22 +1383,46 @@ jobs: // Determine the issue/PR number and comment endpoint for this comment let issueNumber; let commentEndpoint; - if (isIssueContext) { - if (context.payload.issue) { - issueNumber = context.payload.issue.number; + if (commentTarget === "*") { + // For target "*", we need an explicit issue number from the comment item + if (commentItem.issue_number) { + issueNumber = parseInt(commentItem.issue_number, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number specified: ${commentItem.issue_number}`); + continue; + } commentEndpoint = 'issues'; } else { - console.log('Issue context detected but no issue found in payload'); + console.log('Target is "*" but no issue_number specified in comment item'); continue; } - } else if (isPRContext) { - if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - commentEndpoint = 'issues'; // PR comments use the issues API endpoint - } else { - console.log('Pull request context detected but no pull request found in payload'); + } else if (commentTarget && commentTarget !== "triggering") { + // Explicit issue number specified in target + issueNumber = parseInt(commentTarget, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number in target configuration: ${commentTarget}`); continue; } + commentEndpoint = 'issues'; + } else { + // Default behavior: use triggering issue/PR + if (isIssueContext) { + if (context.payload.issue) { + issueNumber = context.payload.issue.number; + commentEndpoint = 'issues'; + } else { + console.log('Issue context detected but no issue found in payload'); + continue; + } + } else if (isPRContext) { + if (context.payload.pull_request) { + issueNumber = context.payload.pull_request.number; + commentEndpoint = 'issues'; // PR comments use the issues API endpoint + } else { + console.log('Pull request context detected but no pull request found in payload'); + continue; + } + } } if (!issueNumber) { console.log('Could not determine issue or pull request number'); diff --git a/.github/workflows/test-codex-add-issue-comment.lock.yml b/.github/workflows/test-codex-add-issue-comment.lock.yml index df3983f8514..93bd57d92d9 100644 --- a/.github/workflows/test-codex-add-issue-comment.lock.yml +++ b/.github/workflows/test-codex-add-issue-comment.lock.yml @@ -363,7 +363,7 @@ jobs: uses: actions/github-script@v7 env: GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }} - GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":true}" + GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":{\"enabled\":true}}" with: script: | async function main() { @@ -1009,11 +1009,15 @@ jobs: return; } console.log(`Found ${commentItems.length} add-issue-comment item(s)`); + // Get the target configuration from environment variable + const commentTarget = process.env.GITHUB_AW_COMMENT_TARGET || "triggering"; + console.log(`Comment target configuration: ${commentTarget}`); // Check if we're in an issue or pull request context const isIssueContext = context.eventName === 'issues' || context.eventName === 'issue_comment'; const isPRContext = context.eventName === 'pull_request' || context.eventName === 'pull_request_review' || context.eventName === 'pull_request_review_comment'; - if (!isIssueContext && !isPRContext) { - console.log('Not running in issue or pull request context, skipping comment creation'); + // Validate context based on target configuration + if (commentTarget === "triggering" && !isIssueContext && !isPRContext) { + console.log('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); return; } const createdComments = []; @@ -1024,22 +1028,46 @@ jobs: // Determine the issue/PR number and comment endpoint for this comment let issueNumber; let commentEndpoint; - if (isIssueContext) { - if (context.payload.issue) { - issueNumber = context.payload.issue.number; + if (commentTarget === "*") { + // For target "*", we need an explicit issue number from the comment item + if (commentItem.issue_number) { + issueNumber = parseInt(commentItem.issue_number, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number specified: ${commentItem.issue_number}`); + continue; + } commentEndpoint = 'issues'; } else { - console.log('Issue context detected but no issue found in payload'); + console.log('Target is "*" but no issue_number specified in comment item'); continue; } - } else if (isPRContext) { - if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - commentEndpoint = 'issues'; // PR comments use the issues API endpoint - } else { - console.log('Pull request context detected but no pull request found in payload'); + } else if (commentTarget && commentTarget !== "triggering") { + // Explicit issue number specified in target + issueNumber = parseInt(commentTarget, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number in target configuration: ${commentTarget}`); continue; } + commentEndpoint = 'issues'; + } else { + // Default behavior: use triggering issue/PR + if (isIssueContext) { + if (context.payload.issue) { + issueNumber = context.payload.issue.number; + commentEndpoint = 'issues'; + } else { + console.log('Issue context detected but no issue found in payload'); + continue; + } + } else if (isPRContext) { + if (context.payload.pull_request) { + issueNumber = context.payload.pull_request.number; + commentEndpoint = 'issues'; // PR comments use the issues API endpoint + } else { + console.log('Pull request context detected but no pull request found in payload'); + continue; + } + } } if (!issueNumber) { console.log('Could not determine issue or pull request number'); diff --git a/.github/workflows/test-codex-alias.lock.yml b/.github/workflows/test-codex-alias.lock.yml index 8e3810405e6..aaec95cc435 100644 --- a/.github/workflows/test-codex-alias.lock.yml +++ b/.github/workflows/test-codex-alias.lock.yml @@ -663,7 +663,7 @@ jobs: uses: actions/github-script@v7 env: GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }} - GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":true}" + GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":{\"enabled\":true}}" with: script: | async function main() { @@ -1364,11 +1364,15 @@ jobs: return; } console.log(`Found ${commentItems.length} add-issue-comment item(s)`); + // Get the target configuration from environment variable + const commentTarget = process.env.GITHUB_AW_COMMENT_TARGET || "triggering"; + console.log(`Comment target configuration: ${commentTarget}`); // Check if we're in an issue or pull request context const isIssueContext = context.eventName === 'issues' || context.eventName === 'issue_comment'; const isPRContext = context.eventName === 'pull_request' || context.eventName === 'pull_request_review' || context.eventName === 'pull_request_review_comment'; - if (!isIssueContext && !isPRContext) { - console.log('Not running in issue or pull request context, skipping comment creation'); + // Validate context based on target configuration + if (commentTarget === "triggering" && !isIssueContext && !isPRContext) { + console.log('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); return; } const createdComments = []; @@ -1379,22 +1383,46 @@ jobs: // Determine the issue/PR number and comment endpoint for this comment let issueNumber; let commentEndpoint; - if (isIssueContext) { - if (context.payload.issue) { - issueNumber = context.payload.issue.number; + if (commentTarget === "*") { + // For target "*", we need an explicit issue number from the comment item + if (commentItem.issue_number) { + issueNumber = parseInt(commentItem.issue_number, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number specified: ${commentItem.issue_number}`); + continue; + } commentEndpoint = 'issues'; } else { - console.log('Issue context detected but no issue found in payload'); + console.log('Target is "*" but no issue_number specified in comment item'); continue; } - } else if (isPRContext) { - if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - commentEndpoint = 'issues'; // PR comments use the issues API endpoint - } else { - console.log('Pull request context detected but no pull request found in payload'); + } else if (commentTarget && commentTarget !== "triggering") { + // Explicit issue number specified in target + issueNumber = parseInt(commentTarget, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number in target configuration: ${commentTarget}`); continue; } + commentEndpoint = 'issues'; + } else { + // Default behavior: use triggering issue/PR + if (isIssueContext) { + if (context.payload.issue) { + issueNumber = context.payload.issue.number; + commentEndpoint = 'issues'; + } else { + console.log('Issue context detected but no issue found in payload'); + continue; + } + } else if (isPRContext) { + if (context.payload.pull_request) { + issueNumber = context.payload.pull_request.number; + commentEndpoint = 'issues'; // PR comments use the issues API endpoint + } else { + console.log('Pull request context detected but no pull request found in payload'); + continue; + } + } } if (!issueNumber) { console.log('Could not determine issue or pull request number'); diff --git a/.github/workflows/test-proxy.lock.yml b/.github/workflows/test-proxy.lock.yml index 3f878abbf21..4fe21c5ad52 100644 --- a/.github/workflows/test-proxy.lock.yml +++ b/.github/workflows/test-proxy.lock.yml @@ -425,7 +425,7 @@ jobs: uses: actions/github-script@v7 env: GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }} - GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":true}" + GITHUB_AW_SAFE_OUTPUTS_CONFIG: "{\"add-issue-comment\":{\"enabled\":true}}" with: script: | async function main() { @@ -1126,11 +1126,15 @@ jobs: return; } console.log(`Found ${commentItems.length} add-issue-comment item(s)`); + // Get the target configuration from environment variable + const commentTarget = process.env.GITHUB_AW_COMMENT_TARGET || "triggering"; + console.log(`Comment target configuration: ${commentTarget}`); // Check if we're in an issue or pull request context const isIssueContext = context.eventName === 'issues' || context.eventName === 'issue_comment'; const isPRContext = context.eventName === 'pull_request' || context.eventName === 'pull_request_review' || context.eventName === 'pull_request_review_comment'; - if (!isIssueContext && !isPRContext) { - console.log('Not running in issue or pull request context, skipping comment creation'); + // Validate context based on target configuration + if (commentTarget === "triggering" && !isIssueContext && !isPRContext) { + console.log('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); return; } const createdComments = []; @@ -1141,22 +1145,46 @@ jobs: // Determine the issue/PR number and comment endpoint for this comment let issueNumber; let commentEndpoint; - if (isIssueContext) { - if (context.payload.issue) { - issueNumber = context.payload.issue.number; + if (commentTarget === "*") { + // For target "*", we need an explicit issue number from the comment item + if (commentItem.issue_number) { + issueNumber = parseInt(commentItem.issue_number, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number specified: ${commentItem.issue_number}`); + continue; + } commentEndpoint = 'issues'; } else { - console.log('Issue context detected but no issue found in payload'); + console.log('Target is "*" but no issue_number specified in comment item'); continue; } - } else if (isPRContext) { - if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - commentEndpoint = 'issues'; // PR comments use the issues API endpoint - } else { - console.log('Pull request context detected but no pull request found in payload'); + } else if (commentTarget && commentTarget !== "triggering") { + // Explicit issue number specified in target + issueNumber = parseInt(commentTarget, 10); + if (isNaN(issueNumber) || issueNumber <= 0) { + console.log(`Invalid issue number in target configuration: ${commentTarget}`); continue; } + commentEndpoint = 'issues'; + } else { + // Default behavior: use triggering issue/PR + if (isIssueContext) { + if (context.payload.issue) { + issueNumber = context.payload.issue.number; + commentEndpoint = 'issues'; + } else { + console.log('Issue context detected but no issue found in payload'); + continue; + } + } else if (isPRContext) { + if (context.payload.pull_request) { + issueNumber = context.payload.pull_request.number; + commentEndpoint = 'issues'; // PR comments use the issues API endpoint + } else { + console.log('Pull request context detected but no pull request found in payload'); + continue; + } + } } if (!issueNumber) { console.log('Could not determine issue or pull request number'); From 71354d683e4c226f1f3ee9036126a000178c19ea Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 2 Sep 2025 21:18:46 +0100 Subject: [PATCH 3/3] fix test --- pkg/workflow/js/create_comment.test.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/workflow/js/create_comment.test.cjs b/pkg/workflow/js/create_comment.test.cjs index 4ec1552a141..0d9c3552cf7 100644 --- a/pkg/workflow/js/create_comment.test.cjs +++ b/pkg/workflow/js/create_comment.test.cjs @@ -103,7 +103,7 @@ describe('create_comment.cjs', () => { // Execute the script await eval(`(async () => { ${createCommentScript} })()`); - expect(consoleSpy).toHaveBeenCalledWith('Not running in issue or pull request context, skipping comment creation'); + expect(consoleSpy).toHaveBeenCalledWith('Target is "triggering" but not running in issue or pull request context, skipping comment creation'); expect(mockGithub.rest.issues.createComment).not.toHaveBeenCalled(); consoleSpy.mockRestore();