From 1a45ef3ca65b6e8b969b05ef509faa299a4f841b Mon Sep 17 00:00:00 2001 From: Josh Johanning Date: Thu, 14 Nov 2024 21:56:26 -0600 Subject: [PATCH] feat: adding issue types / sub-issues scripts --- gh-cli/README.md | 16 ++++ gh-cli/add-sub-issue-to-issue.sh | 79 ++++++++++++++++++++ gh-cli/remove-issue-issue-type.sh | 68 +++++++++++++++++ gh-cli/remove-sub-issue-from-issue.sh | 101 ++++++++++++++++++++++++++ gh-cli/update-issue-issue-type.sh | 76 +++++++++++++++++++ 5 files changed, 340 insertions(+) create mode 100755 gh-cli/add-sub-issue-to-issue.sh create mode 100755 gh-cli/remove-issue-issue-type.sh create mode 100755 gh-cli/remove-sub-issue-from-issue.sh create mode 100755 gh-cli/update-issue-issue-type.sh diff --git a/gh-cli/README.md b/gh-cli/README.md index 7d10307..4baa7fa 100644 --- a/gh-cli/README.md +++ b/gh-cli/README.md @@ -112,6 +112,10 @@ Use the [get-enterprise-id.sh](./get-enterprise-id.sh) or [get-organization-id.s See the [docs](https://docs.github.com/en/graphql/reference/mutations#createipallowlistentry) for further information. +### add-sub-issue-to-issue.sh + +Adds a sub-issue (child) to an issue (parent). See: [Community Discussions Post](https://github.com/orgs/community/discussions/139932) + ### add-team-to-repositories-from-list.sh This script adds a specified team to a list of repositories with specified permissions. @@ -1164,6 +1168,14 @@ Removes an enterprise user. See notes: 1. List org members and get the id from there: `./get-organization-members.sh` 2. Get user id: `./get-user-id.sh` +### remove-issue-issue-type.sh + +Remove the issue type from an issue (set it to `null`). See: [Community Discussions Post](https://github.com/orgs/community/discussions/139933) + +### remove-sub-issue-from-issue.sh + +Removes a sub-issue (child) from an issue (parent). See: [Community Discussions Post](https://github.com/orgs/community/discussions/139932) + ### remove-users-from-organization.sh Removes a list of users from the organization. @@ -1265,6 +1277,10 @@ Updates a branch protection rule for a given branch. Adds your account to an organization in an enterprise as an owner, member, or leave the organization. This requires the user running the script to be an Enterprise Owner. +### update-issue-issue-type.sh + +Updates / sets the issue type for an issue. See: [Community Discussions Post](https://github.com/orgs/community/discussions/139933) + ### verify-team-membership.sh Simple script to verify that a user is a member of a team diff --git a/gh-cli/add-sub-issue-to-issue.sh b/gh-cli/add-sub-issue-to-issue.sh new file mode 100755 index 0000000..e400794 --- /dev/null +++ b/gh-cli/add-sub-issue-to-issue.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Adds a sub-issue (child) to an issue (parent) + +if [ -z "$4" ]; then + echo "Usage: $0 " + echo "Example: ./add-sub-issue-to-issue.sh joshjohanning-org migrating-ado-to-gh-issues-v2 5 6" + exit 1 +fi + +org="$1" +repo="$2" +parent_issue_number="$3" +child_issue_number="$4" + +# Define color codes +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Function to fetch the issue ID given the issue number +fetch_issue_id() { + local org=$1 + local repo=$2 + local issue_number=$3 + + issue_id=$(gh api graphql -F owner="$org" -f repository="$repo" -F number="$issue_number" -f query=' + query ($owner: String!, $repository: String!, $number: Int!) { + repository(owner: $owner, name: $repository) { + issue(number: $number) { + id + } + } + }' --jq '.data.repository.issue.id') + + # Check if the query was successful + if [ $? -ne 0 ] || [ -z "$issue_id" ]; then + echo -e "${RED}Issue #$issue_number not found in repository '$repo' of organization '$org'.${NC}" + exit 1 + fi + + echo "$issue_id" +} + +# Fetch the parent issue ID given the issue number +parent_issue_id=$(fetch_issue_id "$org" "$repo" "$parent_issue_number") + +# Fetch the child issue ID given the issue number +child_issue_id=$(fetch_issue_id "$org" "$repo" "$child_issue_number") + +# Set the issue type on the issue +gh api graphql -H GraphQL-Features:issue_types -H GraphQL-Features:sub_issues -f parrentIssueId="$parent_issue_id" -f childIssueId="$child_issue_id" -f query=' +mutation($parrentIssueId: ID!, $childIssueId: ID!) { + addSubIssue(input: { issueId: $parrentIssueId, subIssueId: $childIssueId }) { + issue { + title + number + url + issueType { + name + } + } + subIssue { + title + number + url + issueType { + name + } + } + } +}' + +# Check if the mutation was successful +if [ $? -eq 0 ]; then + echo "Successfully added issue $org/$repo#$child_issue_number as a sub-issue to $org/$repo#$parent_issue_number." +else + echo -e "${RED}Failed to add issue $org/$repo#$child_issue_number as a sub-issue to $org/$repo#$parent_issue_number.${NC}" + exit 1 +fi diff --git a/gh-cli/remove-issue-issue-type.sh b/gh-cli/remove-issue-issue-type.sh new file mode 100755 index 0000000..09e0325 --- /dev/null +++ b/gh-cli/remove-issue-issue-type.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Remove the issue type from an issue (set it to `null`) + +if [ -z "$3" ]; then + echo "Usage: $0 " + echo "Example: ./remove-issue-issue-type.sh joshjohanning-org migrating-ado-to-gh-issues-v2 5" + exit 1 +fi + +org="$1" +repo="$2" +issue_number="$3" + +# Define color codes +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Fetch the issue ID given the issue number +issue=$(gh api graphql -H GraphQL-Features:issue_types -f owner="$org" -f repository="$repo" -F number="$issue_number" -f query=' +query ($owner: String!, $repository: String!, $number: Int!) { + repository(owner: $owner, name: $repository) { + issue(number: $number) { + id + issueType { + name + } + } + } +}') + +# Check if the query was successful +if [ $? -ne 0 ]; then + echo -e "${RED}Issue #$issue_number not found in $org/$repo${NC}" + exit 1 +fi + +issue_id=$(echo "$issue" | jq -r '.data.repository.issue.id') +issue_type=$(echo "$issue" | jq -r '.data.repository.issue.issueType.name') + +# Check if the issue type is already null +if [ "$issue_type" == "null" ]; then + echo -e "${RED}The issue type is already null for issue #$issue_number in $org/$repo${NC}" + exit 1 +fi + +# Remove the issue type on the issue +gh api graphql -H GraphQL-Features:issue_types -f issueId="$issue_id" -f query=' +mutation($issueId: ID!) { + updateIssueIssueType(input: {issueId: $issueId, issueTypeId: null}) { + issue { + title + number + url + issueType { + name + } + } + } +}' + +# Check if the mutation was successful +if [ $? -eq 0 ]; then + echo "Issue type removed for issue #$issue_number." +else + echo -e "${RED}Failed to remove issue type for issue $org/$repo#$issue_number.${NC}" + exit 1 +fi diff --git a/gh-cli/remove-sub-issue-from-issue.sh b/gh-cli/remove-sub-issue-from-issue.sh new file mode 100755 index 0000000..e7d8450 --- /dev/null +++ b/gh-cli/remove-sub-issue-from-issue.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# Removes a sub-issue (child) from an issue (parent) + +if [ -z "$4" ]; then + echo "Usage: $0 " + echo "Example: ./remove-sub-issue-to-issue.sh joshjohanning-org migrating-ado-to-gh-issues-v2 5 bug" + exit 1 +fi + +org="$1" +repo="$2" +parent_issue_number="$3" +child_issue_number="$4" + +# Define color codes +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Function to fetch the issue ID given the issue number +fetch_issue_id() { + local org=$1 + local repo=$2 + local issue_number=$3 + + issue_id=$(gh api graphql -F owner="$org" -F repository="$repo" -F number="$issue_number" -f query=' + query ($owner: String!, $repository: String!, $number: Int!) { + repository(owner: $owner, name: $repository) { + issue(number: $number) { + id + } + } + }' --jq '.data.repository.issue.id') + + # Check if the query was successful + if [ $? -ne 0 ] || [ -z "$issue_id" ]; then + echo -e "${RED}Issue #$issue_number not found in repository '$repo' of organization '$org'.${NC}" + exit 1 + fi + + echo "$issue_id" +} + +# Fetch the parent issue ID given the issue number +parent_issue_id=$(fetch_issue_id "$org" "$repo" "$parent_issue_number") + +# Fetch the child issue ID given the issue number +child_issue_id=$(fetch_issue_id "$org" "$repo" "$child_issue_number") + +child_issues=$(gh api graphql -H GraphQL-Features:sub_issues -F parrentIssueId="$parent_issue_id" -f query=' + query ($parrentIssueId: ID!) { + node(id: $parrentIssueId) { + ... on Issue { + subIssues(first: 10) { + nodes { + number + id + } + } + } + } + }') + +# Check if the child issue number is in the list of child issues +if echo "$child_issues" | jq -e --argjson child_issue_number "$child_issue_number" '.data.node.subIssues.nodes[] | select(.number == $child_issue_number)' > /dev/null; then + echo "Child issue #$child_issue_number is a sub-issue of parent issue #$parent_issue_number." +else + echo -e "${RED}Child issue #$child_issue_number is not a sub-issue of parent issue #$parent_issue_number.${NC}" + exit 1 +fi + +# Set the issue type on the issue +gh api graphql -H GraphQL-Features:issue_types -H GraphQL-Features:sub_issues -f parrentIssueId="$parent_issue_id" -f childIssueId="$child_issue_id" -f query=' +mutation($parrentIssueId: ID!, $childIssueId: ID!) { + removeSubIssue(input: { issueId: $parrentIssueId, subIssueId: $childIssueId }) { + issue { + title + number + url + issueType { + name + } + } + subIssue { + title + number + url + issueType { + name + } + } + } +}' + +# Check if the mutation was successful +if [ $? -eq 0 ]; then + echo "Successfully removed issue $org/$repo#$child_issue_number as a sub-issue to $org/$repo#$parent_issue_number." +else + echo -e "${RED}Failed to remove issue $org/$repo#$child_issue_number as a sub-issue to $org/$repo#$parent_issue_number.${NC}" + exit 1 +fi diff --git a/gh-cli/update-issue-issue-type.sh b/gh-cli/update-issue-issue-type.sh new file mode 100755 index 0000000..c808cbd --- /dev/null +++ b/gh-cli/update-issue-issue-type.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# Updates / sets the issue type for an issue + +if [ -z "$4" ]; then + echo "Usage: $0 " + echo "Example: ./update-issue-issue-type.sh joshjohanning-org migrating-ado-to-gh-issues-v2 5 'user story'" + exit 1 +fi + +org="$1" +repo="$2" +issue_number="$3" +type=$(echo "$4" | tr '[:upper:]' '[:lower:]') + +# Define color codes +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Fetch issue types and filter to get the ID where name equals $type_upper +issue_type_id=$(gh api graphql -H GraphQL-Features:issue_types -f owner="$org" -f query=' +query($owner: String!) { + organization(login: $owner) { + issueTypes(first: 100) { + nodes { + id + name + } + } + } +}' | jq -r --arg type "$type" '.data.organization.issueTypes.nodes[] | select(.name | ascii_downcase == $type) | .id') + +# Check if issue type ID was found +if [ -z "$issue_type_id" ]; then + echo "Issue type '$type' not found in organization '$org'." + exit 1 +fi + +# Fetch the issue ID given the issue number +issue_id=$(gh api graphql -f owner="$org" -f repository="$repo" -F number="$issue_number" -f query=' +query ($owner: String!, $repository: String!, $number: Int!) { + repository(owner: $owner, name: $repository) { + issue(number: $number) { + id + } + } +}' --jq '.data.repository.issue.id') + +# Check if the query was successful +if [ $? -ne 0 ]; then + echo -e "${RED}Issue #$issue_number not found in $org/$repo${NC}" + exit 1 +fi + +# Set the issue type on the issue +gh api graphql -H GraphQL-Features:issue_types -f issueId="$issue_id" -f issueTypeId="$issue_type_id" -f query=' +mutation($issueId: ID!, $issueTypeId: ID!) { + updateIssueIssueType(input: {issueId: $issueId, issueTypeId: $issueTypeId}) { + issue { + title + number + url + issueType { + name + } + } + } +}' + +# Check if the mutation was successful +if [ $? -eq 0 ]; then + echo "Issue type set to '$type' for issue #$issue_number." +else + echo -e "${RED}Failed to set issue type for issue $org/$repo#$issue_number.${NC}" + exit 1 +fi