Skip to content

Commit 39d0a7f

Browse files
authored
Add issues:write permission to activation/conclusion jobs when lock-for-agent is enabled (#6268)
1 parent 2279d82 commit 39d0a7f

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

.github/workflows/ai-moderator.lock.yml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/workflow/compiler_jobs.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,7 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate
11051105

11061106
// Set permissions - activation job always needs contents:read for GitHub API access
11071107
// Also add reaction permissions if reaction is configured and not "none"
1108+
// Also add issues:write permission if lock-for-agent is enabled (for locking issues)
11081109
permsMap := map[PermissionScope]PermissionLevel{
11091110
PermissionContents: PermissionRead, // Always needed for GitHub API access to check file commits
11101111
}
@@ -1115,6 +1116,11 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate
11151116
permsMap[PermissionPullRequests] = PermissionWrite
11161117
}
11171118

1119+
// Add issues:write permission if lock-for-agent is enabled (even without reaction)
1120+
if data.LockForAgent {
1121+
permsMap[PermissionIssues] = PermissionWrite
1122+
}
1123+
11181124
perms := NewPermissionsFromMap(permsMap)
11191125
permissions := perms.RenderToYAML()
11201126

pkg/workflow/lock_for_agent_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,18 @@ Test workflow with lock-for-agent but no reaction.
144144
if strings.Contains(yamlContent, "GH_AW_LOCK_FOR_AGENT: \"true\"") {
145145
t.Error("Generated YAML should not set GH_AW_LOCK_FOR_AGENT env var without reaction step")
146146
}
147+
148+
// Verify activation job has issues: write permission for locking
149+
activationJobSection := extractJobSection(yamlContent, "activation")
150+
if !strings.Contains(activationJobSection, "issues: write") {
151+
t.Error("Activation job should have issues: write permission when lock-for-agent is enabled")
152+
}
153+
154+
// Verify conclusion job has issues: write permission for unlocking
155+
conclusionJobSection := extractJobSection(yamlContent, "conclusion")
156+
if !strings.Contains(conclusionJobSection, "issues: write") {
157+
t.Error("Conclusion job should have issues: write permission when lock-for-agent is enabled")
158+
}
147159
}
148160

149161
func TestLockForAgentDisabled(t *testing.T) {
@@ -204,6 +216,71 @@ Test workflow without lock-for-agent.
204216
if strings.Contains(yamlContent, "GH_AW_LOCK_FOR_AGENT: \"true\"") {
205217
t.Error("Generated YAML should not set GH_AW_LOCK_FOR_AGENT env var when lock-for-agent is disabled")
206218
}
219+
220+
// Verify activation job has issues: write permission due to reaction (not lock-for-agent)
221+
activationJobSection := extractJobSection(yamlContent, "activation")
222+
if !strings.Contains(activationJobSection, "issues: write") {
223+
t.Error("Activation job should have issues: write permission when reaction is enabled")
224+
}
225+
}
226+
227+
func TestLockForAgentDisabledWithoutReaction(t *testing.T) {
228+
// Create temporary directory for test files
229+
tmpDir := testutil.TempDir(t, "lock-disabled-no-reaction-test")
230+
231+
// Create a test markdown file without lock-for-agent and without reaction
232+
testContent := `---
233+
on:
234+
issues:
235+
types: [opened]
236+
engine: copilot
237+
safe-outputs:
238+
add-comment: {}
239+
---
240+
241+
# Test Without Lock For Agent and Without Reaction
242+
243+
Test workflow without lock-for-agent and without reaction.
244+
`
245+
246+
testFile := filepath.Join(tmpDir, "test-no-lock-no-reaction.md")
247+
if err := os.WriteFile(testFile, []byte(testContent), 0644); err != nil {
248+
t.Fatal(err)
249+
}
250+
251+
compiler := NewCompiler(false, "", "test")
252+
253+
// Parse the workflow
254+
workflowData, err := compiler.ParseWorkflowFile(testFile)
255+
if err != nil {
256+
t.Fatalf("Failed to parse workflow: %v", err)
257+
}
258+
259+
// Verify lock-for-agent field is false by default
260+
if workflowData.LockForAgent {
261+
t.Error("Expected LockForAgent to be false by default")
262+
}
263+
264+
// Generate YAML and verify it does not contain lock/unlock steps
265+
yamlContent, err := compiler.generateYAML(workflowData, testFile)
266+
if err != nil {
267+
t.Fatalf("Failed to generate YAML: %v", err)
268+
}
269+
270+
// Lock and unlock steps should not be present
271+
if strings.Contains(yamlContent, "Lock issue for agent workflow") {
272+
t.Error("Generated YAML should not contain lock step when lock-for-agent is disabled")
273+
}
274+
275+
if strings.Contains(yamlContent, "Unlock issue after agent workflow") {
276+
t.Error("Generated YAML should not contain unlock step when lock-for-agent is disabled")
277+
}
278+
279+
// Verify activation job does NOT have issues: write permission (no reaction and no lock-for-agent)
280+
activationJobSection := extractJobSection(yamlContent, "activation")
281+
if strings.Contains(activationJobSection, "issues: write") {
282+
t.Error("Activation job should NOT have issues: write permission when lock-for-agent is disabled and no reaction is configured")
283+
}
207284
}
208285

209286
func TestLockForAgentOnPullRequest(t *testing.T) {

0 commit comments

Comments
 (0)