Setting the file. One moment. Squad Issue Assign · {skill Name} · github/gh-aw · Skills Docsworkflows/squad-issue-assign.yml
workflows/squad-issue-assign.yml
YAML·157 lines·6 KB
14 if: startsWith(github.event.label.name, 'squad:')
15 runs-on: ubuntu-latest
16 steps:
17 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 #v4
18
19 - name: Identify assigned member and trigger work
20 uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b #v7
21 with:
22 script: |
23 const fs = require('fs');
24 const issue = context.payload.issue;
25 const label = context.payload.label.name;
26
27 // Extract member name from label (e.g., "squad:ripley" → "ripley")
28 const memberName = label.replace('squad:', '').toLowerCase();
29
30 const teamFile = '.squad/team.md';
31 if (!fs.existsSync(teamFile)) {
32 core.warning('No .squad/team.md found — cannot assign work');
33 return;
34 }
35
36 const content = fs.readFileSync(teamFile, 'utf8');
37 const lines = content.split('\n');
38
39 // Check if this is a coding agent assignment
40 const isCopilotAssignment = memberName === 'copilot';
41
42 let assignedMember = null;
43 if (isCopilotAssignment) {
44 assignedMember = { name: '@copilot', role: 'Coding Agent' };
45 } else {
46 let inMembersTable = false;
47 for (const line of lines) {
48 if (line.match(/^##\s+(Members|Team Roster)/i)) {
49 inMembersTable = true;
50 continue;
51 }
52 if (inMembersTable && line.startsWith('## ')) {
53 break;
54 }
55 if (inMembersTable && line.startsWith('|') && !line.includes('---') && !line.includes('Name')) {
56 const cells = line.split('|').map(c => c.trim()).filter(Boolean);
57 if (cells.length >= 2 && cells[0].toLowerCase() === memberName) {
58 assignedMember = { name: cells[0], role: cells[1] };
59 break;
60 }
61 }
62 }
63 }
64
65 if (!assignedMember) {
66 core.warning(`No member found matching label "${label}"`);
67 await github.rest.issues.createComment({
68 owner: context.repo.owner,
69 repo: context.repo.repo,
70 issue_number: issue.number,
71 body: `⚠️ No squad member found matching label \`${label}\`. Check \`.squad/team.md\` for valid member names.`
72 });
73 return;
74 }
75
76 // Post assignment acknowledgment
77 let comment;
78 if (isCopilotAssignment) {
79 comment = [
80 `### 🤖 Routed to @copilot (Coding Agent)`,
81 '',
82 `**Issue:** #${issue.number} — ${issue.title}`,
83 '',
84 `@copilot has been assigned and will pick this up automatically.`,
85 '',
86 `> The coding agent will create a \`copilot/*\` branch and open a draft PR.`,
87 `> Review the PR as you would any team member's work.`,
88 ].join('\n');
89 } else {
90 comment = [
91 `### 📋 Assigned to ${assignedMember.name} (${assignedMember.role})`,
92 '',
93 `**Issue:** #${issue.number} — ${issue.title}`,
94 '',
95 `${assignedMember.name} will pick this up in the next Copilot session.`,
96 '',
97 `> **For Copilot coding agent:** If enabled, this issue will be worked automatically.`,
98 `> Otherwise, start a Copilot session and say:`,
99 `> \`${assignedMember.name}, work on issue #${issue.number}\``,
100 ].join('\n');
101 }
102
103 await github.rest.issues.createComment({
104 owner: context.repo.owner,
105 repo: context.repo.repo,
106 issue_number: issue.number,
107 body: comment
108 });
109
110 core.info(`Issue #${issue.number} assigned to ${assignedMember.name} (${assignedMember.role})`);
111
112 # Separate step: assign @copilot using PAT (required for coding agent)
113 - name: Assign @copilot coding agent
114 if: github.event.label.name == 'squad:copilot'
115 uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b #v7
116 with:
117 github-token: ${{ secrets.COPILOT_ASSIGN_TOKEN }}
118 script: |
119 const owner = context.repo.owner;
120 const repo = context.repo.repo;
121 const issue_number = context.payload.issue.number;
122
123 // Get the default branch name (main, master, etc.)
124 const { data: repoData } = await github.rest.repos.get({ owner, repo });
125 const baseBranch = repoData.default_branch;
126
127 try {
128 await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/assignees', {
129 owner,
130 repo,
131 issue_number,
132 assignees: ['copilot-swe-agent[bot]'],
133 agent_assignment: {
134 target_repo: `${owner}/${repo}`,
135 base_branch: baseBranch,
136 custom_instructions: '',
137 custom_agent: '',
138 model: ''
139 },
140 headers: {
141 'X-GitHub-Api-Version': '2022-11-28'
142 }
143 });
144 core.info(`Assigned copilot-swe-agent to issue #${issue_number} (base: ${baseBranch})`);
145 } catch (err) {
146 core.warning(`Assignment with agent_assignment failed: ${err.message}`);
147 // Fallback: try without agent_assignment
148 try {
149 await github.rest.issues.addAssignees({
150 owner, repo, issue_number,
151 assignees: ['copilot-swe-agent']
152 });
153 core.info(`Fallback assigned copilot-swe-agent to issue #${issue_number}`);
154 } catch (err2) {
155 core.warning(`Fallback also failed: ${err2.message}`);
156 }
157 }