new collections NOAA GHRSST G19 ABI L2P L3C v3.0 #37
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
| # Automate the triage of issues by team as they are labeled with team:<team_name>. | |
| # This workflow will update the status in the main podaac project to "triaged" and add the issue to the corresponding team project if it exists. | |
| # This helps ensure that issues are properly categorized and visible to the right teams without requiring manual triage in the "needs:triage" column. | |
| name: Team Assignment | |
| on: | |
| issues: | |
| types: [labeled] | |
| jobs: | |
| assign-to-team: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Process team label | |
| uses: actions/github-script@v9 | |
| 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'); | |
| let podaacProjectItem = null; | |
| let podaacStatusUpdated = false; | |
| 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; | |
| 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 | |
| }); | |
| podaacStatusUpdated = true; | |
| 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 (podaacStatusUpdated) { | |
| 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(); |