Team Assignment #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Team Assignment | |
| on: | |
| issues: | |
| types: [labeled] | |
| jobs: | |
| assign-to-team: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Process team label | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.PROJECTS_PAT }} | |
| script: | | |
| const label = context.payload.label.name; | |
| const issueNumber = context.payload.issue.number; | |
| // Check if label matches team:<team_name> pattern | |
| const teamMatch = label.match(/^team:(.+)$/); | |
| if (!teamMatch) { | |
| console.log(`Label "${label}" does not match team:<team_name> pattern, skipping`); | |
| return; | |
| } | |
| const teamName = teamMatch[1]; | |
| console.log(`Processing team assignment for team: ${teamName}`); | |
| const podaacProjectNumber = 75; | |
| const org = 'podaac'; | |
| const repo = context.repo.repo; | |
| // Define reusable GraphQL mutation for updating project status | |
| const updateStatusMutation = ` | |
| mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: String!) { | |
| updateProjectV2ItemFieldValue( | |
| input: { | |
| projectId: $projectId | |
| itemId: $itemId | |
| fieldId: $fieldId | |
| value: { singleSelectOptionId: $value } | |
| } | |
| ) { | |
| projectV2Item { | |
| id | |
| } | |
| } | |
| } | |
| `; | |
| // ======================================== | |
| // Step 1: Update status to "triaged" in podaac project | |
| // ======================================== | |
| console.log('Step 1: Updating podaac project status to "triaged"...'); | |
| // Get the podaac project information | |
| const podaacProjectQuery = ` | |
| query($org: String!, $number: Int!) { | |
| organization(login: $org) { | |
| projectV2(number: $number) { | |
| id | |
| fields(first: 20) { | |
| nodes { | |
| ... on ProjectV2SingleSelectField { | |
| id | |
| name | |
| options { | |
| id | |
| name | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| `; | |
| const podaacProjectData = await github.graphql(podaacProjectQuery, { | |
| org: org, | |
| number: podaacProjectNumber | |
| }); | |
| const podaacProject = podaacProjectData.organization.projectV2; | |
| const podaacStatusField = podaacProject.fields.nodes.find(field => field.name === 'Status'); | |
| const triagedOption = podaacStatusField?.options.find(option => option.name === 'triaged'); | |
| if (!triagedOption) { | |
| core.warning('Could not find "triaged" status option in podaac project'); | |
| } else { | |
| // Get the issue's project item in podaac project | |
| const issueProjectItemQuery = ` | |
| query($org: String!, $repo: String!, $number: Int!) { | |
| repository(owner: $org, name: $repo) { | |
| issue(number: $number) { | |
| projectItems(first: 10) { | |
| nodes { | |
| id | |
| project { | |
| id | |
| number | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| `; | |
| const issueData = await github.graphql(issueProjectItemQuery, { | |
| org: org, | |
| repo: repo, | |
| number: issueNumber | |
| }); | |
| const projectItems = issueData.repository.issue.projectItems.nodes; | |
| const podaacProjectItem = projectItems.find(item => item.project.id === podaacProject.id); | |
| if (!podaacProjectItem) { | |
| core.warning('Issue is not in podaac project, cannot update status'); | |
| } else { | |
| // Update the status to "triaged" | |
| await github.graphql(updateStatusMutation, { | |
| projectId: podaacProject.id, | |
| itemId: podaacProjectItem.id, | |
| fieldId: podaacStatusField.id, | |
| value: triagedOption.id | |
| }); | |
| console.log('✅ Successfully updated status to "triaged" in podaac project'); | |
| } | |
| } | |
| // ======================================== | |
| // Step 2: Add to team project if it exists | |
| // ======================================== | |
| console.log(`Step 2: Looking for team project named "${teamName}"...`); | |
| // Search for team project by name | |
| const teamProjectSearchQuery = ` | |
| query($org: String!, $searchQuery: String!) { | |
| organization(login: $org) { | |
| projectsV2(first: 20, query: $searchQuery) { | |
| nodes { | |
| id | |
| number | |
| title | |
| fields(first: 20) { | |
| nodes { | |
| ... on ProjectV2SingleSelectField { | |
| id | |
| name | |
| options { | |
| id | |
| name | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| `; | |
| const teamProjectSearchData = await github.graphql(teamProjectSearchQuery, { | |
| org: org, | |
| searchQuery: teamName | |
| }); | |
| const teamProjects = teamProjectSearchData.organization.projectsV2.nodes; | |
| const teamProject = teamProjects.find(p => p.title.toLowerCase() === teamName.toLowerCase()); | |
| if (!teamProject) { | |
| console.log(`⚠️ No project found with name "${teamName}", skipping team project assignment`); | |
| core.notice(`No project found for team "${teamName}". If you want the issue added to a team project, create a project named "${teamName}".`); | |
| return; | |
| } | |
| console.log(`Found team project: ${teamProject.title} (number: ${teamProject.number})`); | |
| // Check if issue is already in the team project | |
| const issueWithProjectsQuery = ` | |
| query($org: String!, $repo: String!, $number: Int!) { | |
| repository(owner: $org, name: $repo) { | |
| issue(number: $number) { | |
| id | |
| projectItems(first: 20) { | |
| nodes { | |
| id | |
| project { | |
| id | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| `; | |
| const issueWithProjects = await github.graphql(issueWithProjectsQuery, { | |
| org: org, | |
| repo: repo, | |
| number: issueNumber | |
| }); | |
| const issueNodeId = issueWithProjects.repository.issue.id; | |
| const existingTeamProjectItem = issueWithProjects.repository.issue.projectItems.nodes.find( | |
| item => item.project.id === teamProject.id | |
| ); | |
| let teamProjectItemId; | |
| let wasAlreadyInProject = false; | |
| if (existingTeamProjectItem) { | |
| // Issue is already in team project | |
| teamProjectItemId = existingTeamProjectItem.id; | |
| wasAlreadyInProject = true; | |
| console.log(`ℹ️ Issue is already in team project "${teamName}"`); | |
| } else { | |
| // Add issue to team project | |
| const addToProjectMutation = ` | |
| mutation($projectId: ID!, $contentId: ID!) { | |
| addProjectV2ItemById(input: { | |
| projectId: $projectId | |
| contentId: $contentId | |
| }) { | |
| item { | |
| id | |
| } | |
| } | |
| } | |
| `; | |
| const addResult = await github.graphql(addToProjectMutation, { | |
| projectId: teamProject.id, | |
| contentId: issueNodeId | |
| }); | |
| teamProjectItemId = addResult.addProjectV2ItemById.item.id; | |
| console.log(`✅ Successfully added issue to team project "${teamName}"`); | |
| } | |
| // Summary | |
| const summaryItems = [`Processed team label: ${teamName}`]; | |
| if (triagedOption && podaacProjectItem) { | |
| summaryItems.push(`Updated podaac project status to "triaged"`); | |
| } | |
| if (wasAlreadyInProject) { | |
| summaryItems.push(`Issue was already in team project "${teamName}"`); | |
| } else { | |
| summaryItems.push(`Added issue to team project "${teamName}"`); | |
| } | |
| core.summary | |
| .addHeading(`Team Assignment Complete: ${teamName}`) | |
| .addList(summaryItems) | |
| .write(); |