-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create Project Automation Shared Workflows (#168)
- Loading branch information
Showing
5 changed files
with
593 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
name: Project - Get Item ID Within the Project | ||
# This workflow gets the project-specific ID for an item within a project | ||
# All downstream queries and mutations of fields within the project require this ID | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
PROJECT_ID: | ||
description: "The Project's graphQL node ID" | ||
type: string | ||
required: true | ||
|
||
ITEM_NODE_ID: | ||
description: "The issue or PR's graphQL node ID" | ||
type: string | ||
required: true | ||
|
||
secrets: | ||
PROJECT_MANAGEMENT_SECRET: | ||
description: "Project Access Token" | ||
required: true | ||
|
||
outputs: | ||
ITEM_PROJECT_ID: | ||
description: "The item's project-specific ID" | ||
value: ${{ jobs.get_items_project_id.outputs.ITEM_PROJECT_ID }} | ||
|
||
jobs: | ||
get_items_project_id: | ||
runs-on: ubuntu-latest | ||
outputs: | ||
ITEM_PROJECT_ID: ${{ steps.get_item_id.outputs.ITEM_PROJECT_ID }} | ||
|
||
steps: | ||
- name: Sleep 1s | ||
id: sleep_1s | ||
run: | | ||
sleep 1 # Ensure the PR is added to the project before we query its ID | ||
- name: Get Item Project ID | ||
id: get_item_id | ||
env: | ||
GH_TOKEN: ${{ secrets.PROJECT_MANAGEMENT_SECRET }} | ||
run: | | ||
# Query up to 10 projects for the PR | ||
# There's no graphQL filter configured to query by a specific project | ||
# So we need to query all projects and filter the result ourselves | ||
gh api graphql -f query=' | ||
query { | ||
node(id: "${{ inputs.ITEM_NODE_ID }}") { | ||
... on PullRequest { | ||
projectItems(first: 10) { | ||
nodes { | ||
id | ||
project { | ||
id | ||
} | ||
} | ||
} | ||
} | ||
... on Issue { | ||
projectItems(first: 10) { | ||
nodes { | ||
id | ||
project { | ||
id | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}' > project_data.json | ||
# Use jq to do the actual filtering | ||
item_project_id=$(jq -r '.data.node.projectItems.nodes[] | | ||
select(.project.id == "${{ inputs.PROJECT_ID }}") | | ||
.id' project_data.json) | ||
echo "ITEM_PROJECT_ID=$item_project_id" >> $GITHUB_OUTPUT | ||
continue-on-error: true |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
name: Project - Get Item ID Within the Project | ||
# This workflow gets the project-specific ID for an item within a project | ||
# All downstream queries and mutations of fields within the project require this ID | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
PROJECT_ID: | ||
description: "The Project's graphQL node ID" | ||
type: string | ||
required: true | ||
|
||
ITERATION_FIELD_NAME: | ||
description: "The name of the iteration field" | ||
type: string | ||
required: true | ||
|
||
ITERATION_FIELD_ID: | ||
description: "The graphQL node ID of the iteration field" | ||
type: string | ||
required: true | ||
|
||
ITEM_PROJECT_ID: | ||
description: "The issue or PR's graphQL project-specific ID" | ||
type: string | ||
required: true | ||
|
||
UPDATE_ITEM: | ||
description: "Whether to update the item's iteration field" | ||
default: false | ||
type: boolean | ||
|
||
# Optional fields, used if UPDATE_ITEM is set to true | ||
ITEM_NODE_ID: | ||
description: "The issue or PR's graphQL node ID, only needed if updating linked issues" | ||
default: null | ||
type: string | ||
|
||
UPDATE_LINKED_ISSUES: | ||
description: "Whether to update the linked issues' iteration fields" | ||
default: false | ||
type: boolean | ||
|
||
secrets: | ||
PROJECT_MANAGEMENT_SECRET: | ||
description: "Project Access Token" | ||
required: true | ||
|
||
outputs: | ||
ITERATION_OPTION_ID: | ||
value: ${{ jobs.get_set_iteration_option_id.outputs.ITERATION_OPTION_ID }} | ||
description: "The iteration option ID" | ||
|
||
jobs: | ||
get_set_iteration_option_id: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
outputs: | ||
ITERATION_OPTION_ID: ${{ steps.get_iteration_option_id.outputs.ITERATION_OPTION_ID }} | ||
|
||
steps: | ||
- name: Get Iteration Option ID | ||
id: get_iteration_option_id | ||
env: | ||
GH_TOKEN: ${{ secrets.PROJECT_MANAGEMENT_SECRET }} | ||
run: | | ||
# Get current iteration iteration id | ||
# The current iteration is always the first element in the returned list | ||
gh api graphql -f query=' | ||
query { | ||
node(id: "${{ inputs.PROJECT_ID }}") { | ||
... on ProjectV2 { | ||
id | ||
field(name: "${{ inputs.ITERATION_FIELD_NAME }}") { | ||
... on ProjectV2IterationField { | ||
id | ||
name | ||
configuration { | ||
iterations { | ||
id | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}' > iteration_option_data.json | ||
current_iteration_option_id=$(jq -r '.data.node.field.configuration.iterations[0].id' iteration_option_data.json) | ||
echo "ITERATION_OPTION_ID=$current_iteration_option_id" >> "$GITHUB_OUTPUT" | ||
- name: Update item iteration field | ||
id: update_item_iteration_field | ||
if: ${{ inputs.UPDATE_ITEM == true }} | ||
env: | ||
GH_TOKEN: ${{ secrets.PROJECT_MANAGEMENT_SECRET }} | ||
run: | | ||
# Set the iteration based on the query above | ||
# This overwrites whatever was in it before, we may want to make an "OVERWRITE" option | ||
gh api graphql -f query=' | ||
mutation { | ||
updateProjectV2ItemFieldValue( | ||
input: { | ||
projectId: "${{ inputs.PROJECT_ID }}" | ||
itemId: "${{ inputs.ITEM_PROJECT_ID }}" | ||
fieldId: "${{ inputs.ITERATION_FIELD_ID }}" | ||
value: { | ||
iterationId: "${{ steps.get_iteration_option_id.outputs.ITERATION_OPTION_ID }}" | ||
} | ||
} | ||
) { | ||
projectV2Item { | ||
id | ||
} | ||
} | ||
}' | ||
continue-on-error: true | ||
|
||
update_linked_issues: | ||
if: ${{ inputs.UPDATE_LINKED_ISSUES == true }} | ||
permissions: | ||
contents: read | ||
uses: ./.github/workflows/project-update-linked-issues.yaml | ||
needs: get_set_iteration_option_id | ||
with: | ||
PROJECT_ID: ${{ inputs.PROJECT_ID }} | ||
PR_PROJECT_ID: ${{ inputs.ITEM_PROJECT_ID }} | ||
PR_NODE_ID: ${{ inputs.ITEM_NODE_ID }} | ||
UPDATE_FIELD_TYPE: "iteration" | ||
UPDATE_FIELD_ID: ${{ inputs.ITERATION_FIELD_ID }} | ||
UPDATE_FIELD_VALUE: ${{ needs.get_set_iteration_option_id.outputs.ITERATION_OPTION_ID }} | ||
secrets: inherit |
131 changes: 131 additions & 0 deletions
131
.github/workflows/project-get-set-single-select-field.yaml
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
name: Project - Get Item ID Within the Project | ||
# This workflow gets the project-specific ID for an item within a project | ||
# All downstream queries and mutations of fields within the project require this ID | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
PROJECT_ID: | ||
description: "The Project's graphQL node ID" | ||
type: string | ||
required: true | ||
|
||
SINGLE_SELECT_FIELD_NAME: | ||
description: "The name of the single-select field" | ||
type: string | ||
required: true | ||
|
||
SINGLE_SELECT_OPTION_VALUE: | ||
description: "The value of the option we'd like to get/set" | ||
type: string | ||
required: true | ||
|
||
SINGLE_SELECT_FIELD_ID: | ||
description: "The graphQL node ID of the single-select field" | ||
type: string | ||
required: true | ||
|
||
ITEM_PROJECT_ID: | ||
description: "The issue or PR's graphQL project-specific ID" | ||
type: string | ||
required: true | ||
|
||
UPDATE_ITEM: | ||
description: "Whether to update the item's single-select field" | ||
default: false | ||
type: boolean | ||
|
||
# Optional fields, used if UPDATE_ITEM is set to true | ||
ITEM_NODE_ID: | ||
description: "The issue or PR's graphQL node ID, only needed if updating linked issues" | ||
default: null | ||
type: string | ||
|
||
UPDATE_LINKED_ISSUES: | ||
description: "Whether to update the linked issues' single_select fields" | ||
default: false | ||
type: boolean | ||
|
||
secrets: | ||
PROJECT_MANAGEMENT_SECRET: | ||
description: "Project Access Token" | ||
required: true | ||
|
||
outputs: | ||
SINGLE_SELECT_OPTION_ID: | ||
value: ${{ jobs.get_set_single_select_option_id.outputs.SINGLE_SELECT_OPTION_ID }} | ||
description: "The single_select option ID" | ||
|
||
jobs: | ||
get_set_single_select_option_id: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
outputs: | ||
SINGLE_SELECT_OPTION_ID: ${{ steps.get_single_select_option_id.outputs.SINGLE_SELECT_OPTION_ID }} | ||
|
||
steps: | ||
- name: Get single_select Option ID | ||
id: get_single_select_option_id | ||
env: | ||
GH_TOKEN: ${{ secrets.PROJECT_MANAGEMENT_SECRET }} | ||
run: | | ||
# Get single_select option id | ||
gh api graphql -f query=' | ||
query { | ||
node(id: "${{ inputs.PROJECT_ID }}") { | ||
... on ProjectV2 { | ||
id | ||
field(name: "${{ inputs.SINGLE_SELECT_FIELD_NAME }}") { | ||
... on ProjectV2SingleSelectField { | ||
id | ||
options(names: "${{ inputs.SINGLE_SELECT_OPTION_VALUE }}") {id} | ||
} | ||
} | ||
} | ||
} | ||
}' > single_select_option_data.json | ||
current_single_select_option_id=$(jq -r '.data.node.field.options[0].id' single_select_option_data.json) | ||
echo "SINGLE_SELECT_OPTION_ID=$current_single_select_option_id" >> "$GITHUB_OUTPUT" | ||
- name: Update item single_select field | ||
id: update_item_single_select_field | ||
if: ${{ inputs.UPDATE_ITEM == true }} | ||
env: | ||
GH_TOKEN: ${{ secrets.PROJECT_MANAGEMENT_SECRET }} | ||
run: | | ||
# Set the single_select based on the query above | ||
# This overwrites whatever was in it before, we may want to make an "OVERWRITE" option | ||
gh api graphql -f query=' | ||
mutation { | ||
updateProjectV2ItemFieldValue( | ||
input: { | ||
projectId: "${{ inputs.PROJECT_ID }}" | ||
itemId: "${{ inputs.ITEM_PROJECT_ID }}" | ||
fieldId: "${{ inputs.SINGLE_SELECT_FIELD_ID }}" | ||
value: { | ||
singleSelectOptionId: "${{ steps.get_single_select_option_id.outputs.SINGLE_SELECT_OPTION_ID }}" | ||
} | ||
} | ||
) { | ||
projectV2Item { | ||
id | ||
} | ||
} | ||
}' | ||
continue-on-error: true | ||
|
||
update_linked_issues: | ||
if: ${{ inputs.UPDATE_LINKED_ISSUES == true }} | ||
permissions: | ||
contents: read | ||
uses: ./.github/workflows/project-update-linked-issues.yaml | ||
needs: get_set_single_select_option_id | ||
with: | ||
PROJECT_ID: ${{ inputs.PROJECT_ID }} | ||
PR_PROJECT_ID: ${{ inputs.ITEM_PROJECT_ID }} | ||
PR_NODE_ID: ${{ inputs.ITEM_NODE_ID }} | ||
UPDATE_FIELD_TYPE: "single_select" | ||
UPDATE_FIELD_ID: ${{ inputs.SINGLE_SELECT_FIELD_ID }} | ||
UPDATE_FIELD_VALUE: ${{ needs.get_set_single_select_option_id.outputs.SINGLE_SELECT_OPTION_ID }} | ||
secrets: inherit |
Oops, something went wrong.