Skip to main content
Glama

DollhouseMCP

by DollhouseMCP
sync-project-priorities.shโ€ข13.8 kB
#!/bin/bash # Enhanced script to automatically discover and update GitHub Project priority fields # This script: # 1. Automatically finds your project and priority field # 2. Updates priority field option names from P0/P1/P2 to emoji-based names # 3. Syncs issues with priority labels to the project priority field set -e # Colors GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' echo -e "${BLUE}=== GitHub Project Priority Sync Tool ===${NC}" echo "" # Validate permissions before proceeding validate_permissions() { if ! gh auth status --hostname github.com 2>/dev/null | grep -q "project"; then echo -e "${RED}Error: Missing project permissions${NC}" echo "Run: gh auth refresh -s project" exit 1 fi } # Check permissions first validate_permissions # Get current user and repo info OWNER=$(gh api user --jq .login) REPO_OWNER=$(gh repo view --json owner --jq .owner.login) REPO_NAME=$(gh repo view --json name --jq .name) echo -e "${GREEN}Repository: $REPO_OWNER/$REPO_NAME${NC}" echo -e "${GREEN}User: $OWNER${NC}" echo "" # Function to list user's projects list_projects() { echo -e "${YELLOW}Fetching your projects...${NC}" PROJECTS=$(gh api graphql -f query=' query($login: String!) { user(login: $login) { projectsV2(first: 20) { nodes { id title number } } } } ' -f login="$OWNER" --jq '.data.user.projectsV2.nodes[]') if [ -z "$PROJECTS" ]; then echo -e "${RED}No projects found${NC}" return 1 fi echo -e "${CYAN}Your projects:${NC}" echo "$PROJECTS" | jq -r '"\(.number). \(.title) (ID: \(.id))"' } # Function to get project fields get_project_fields() { local PROJECT_ID=$1 FIELDS=$(gh api graphql -f query=' query($projectId: ID!) { node(id: $projectId) { ... on ProjectV2 { fields(first: 50) { nodes { ... on ProjectV2Field { id name dataType } ... on ProjectV2SingleSelectField { id name dataType options { id name color } } } } } } } ' -f projectId="$PROJECT_ID" --jq '.data.node.fields.nodes[] | select(.dataType == "SINGLE_SELECT")') echo "$FIELDS" } # Function to find priority field find_priority_field() { local PROJECT_ID=$1 echo -e "${YELLOW}Looking for Priority field...${NC}" PRIORITY_FIELD=$(gh api graphql -f query=' query($projectId: ID!) { node(id: $projectId) { ... on ProjectV2 { fields(first: 50) { nodes { ... on ProjectV2SingleSelectField { id name dataType options { id name color } } } } } } } ' -f projectId="$PROJECT_ID" --jq '.data.node.fields.nodes[] | select(.name == "Priority" or .name == "priority" or (.options[]?.name | test("P[0-2]|High|Medium|Low"; "i")))') if [ -z "$PRIORITY_FIELD" ]; then echo -e "${RED}No Priority field found${NC}" return 1 fi echo "$PRIORITY_FIELD" | jq -r '"Found field: \(.name) (ID: \(.id))"' echo "$PRIORITY_FIELD" } # Function to update field options update_priority_options() { local PROJECT_ID=$1 local FIELD_ID=$2 local FIELD_DATA=$3 echo -e "\n${YELLOW}Current priority options:${NC}" echo "$FIELD_DATA" | jq -r '.options[] | " \(.name) (ID: \(.id), Color: \(.color))"' # Extract option IDs local OPTIONS=$(echo "$FIELD_DATA" | jq -r '.options[]') # Try to identify P0/P1/P2 or High/Medium/Low options local HIGH_OPTION="" local MEDIUM_OPTION="" local LOW_OPTION="" while IFS= read -r option; do local NAME=$(echo "$option" | jq -r '.name') local ID=$(echo "$option" | jq -r '.id') # Match patterns for high/medium/low priorities if [[ "$NAME" =~ P0|Critical|Urgent|High ]] || [[ "$NAME" == "High" ]]; then HIGH_OPTION=$ID elif [[ "$NAME" =~ P1|Medium ]] || [[ "$NAME" == "Medium" ]]; then MEDIUM_OPTION=$ID elif [[ "$NAME" =~ P2|Low ]] || [[ "$NAME" == "Low" ]]; then LOW_OPTION=$ID fi done <<< "$OPTIONS" echo -e "\n${CYAN}Detected mappings:${NC}" [ -n "$HIGH_OPTION" ] && echo " High Priority: ID $HIGH_OPTION" [ -n "$MEDIUM_OPTION" ] && echo " Medium Priority: ID $MEDIUM_OPTION" [ -n "$LOW_OPTION" ] && echo " Low Priority: ID $LOW_OPTION" echo -e "\n${YELLOW}Update option names? (y/n)${NC}" read -p "> " confirm if [ "$confirm" != "y" ]; then return 0 fi # Build options array for mutation local OPTIONS_JSON="[" local FIRST=true if [ -n "$HIGH_OPTION" ]; then [ "$FIRST" = true ] && FIRST=false || OPTIONS_JSON+="," OPTIONS_JSON+="{\"id\": \"$HIGH_OPTION\", \"name\": \"๐Ÿ”ด High\", \"color\": \"RED\"}" fi if [ -n "$MEDIUM_OPTION" ]; then [ "$FIRST" = true ] && FIRST=false || OPTIONS_JSON+="," OPTIONS_JSON+="{\"id\": \"$MEDIUM_OPTION\", \"name\": \"๐ŸŸก Medium\", \"color\": \"YELLOW\"}" fi if [ -n "$LOW_OPTION" ]; then [ "$FIRST" = true ] && FIRST=false || OPTIONS_JSON+="," OPTIONS_JSON+="{\"id\": \"$LOW_OPTION\", \"name\": \"๐ŸŸข Low\", \"color\": \"GREEN\"}" fi OPTIONS_JSON+="]" echo -e "\n${YELLOW}Updating field options...${NC}" RESULT=$(gh api graphql -f query=' mutation($projectId: ID!, $fieldId: ID!, $options: [ProjectV2SingleSelectFieldOptionInput!]!) { updateProjectV2SingleSelectField( input: { projectId: $projectId fieldId: $fieldId options: $options } ) { projectV2Field { ... on ProjectV2SingleSelectField { id name options { id name color } } } } } ' -f projectId="$PROJECT_ID" -f fieldId="$FIELD_ID" -f options="$OPTIONS_JSON" 2>&1) if [ $? -eq 0 ]; then echo -e "${GREEN}โœ“ Field options updated successfully!${NC}" echo "$RESULT" | jq -r '.data.updateProjectV2SingleSelectField.projectV2Field.options[] | " \(.name) (Color: \(.color))"' else echo -e "${RED}โœ— Error updating field options${NC}" echo "$RESULT" return 1 fi # Return the option IDs for syncing echo "$HIGH_OPTION|$MEDIUM_OPTION|$LOW_OPTION" } # Function to sync issues sync_issues_to_project() { local PROJECT_ID=$1 local FIELD_ID=$2 local HIGH_ID=$3 local MEDIUM_ID=$4 local LOW_ID=$5 echo -e "\n${YELLOW}Syncing issues with priority labels...${NC}" # Process each priority level for priority in "high:$HIGH_ID:๐Ÿ”ด High" "medium:$MEDIUM_ID:๐ŸŸก Medium" "low:$LOW_ID:๐ŸŸข Low"; do IFS=':' read -r LABEL OPTION_ID DISPLAY_NAME <<< "$priority" if [ -z "$OPTION_ID" ] || [ "$OPTION_ID" = "null" ]; then echo -e "\n${YELLOW}Skipping $DISPLAY_NAME (no option ID)${NC}" continue fi echo -e "\n${BLUE}Processing $DISPLAY_NAME issues...${NC}" # Get issues with this priority label ISSUES=$(gh issue list --label "priority: $LABEL" --limit 100 --json number,title,state --jq '.[] | select(.state == "OPEN")') if [ -z "$ISSUES" ]; then echo " No open issues with label 'priority: $LABEL'" continue fi local COUNT=0 local SUCCESS=0 echo "$ISSUES" | while IFS= read -r issue; do NUMBER=$(echo "$issue" | jq -r .number) TITLE=$(echo "$issue" | jq -r .title) COUNT=$((COUNT + 1)) echo -n " Issue #$NUMBER: ${TITLE:0:50}... " # Get issue node ID ISSUE_NODE_ID=$(gh api repos/$REPO_OWNER/$REPO_NAME/issues/$NUMBER --jq .node_id 2>/dev/null) if [ -z "$ISSUE_NODE_ID" ]; then echo -e "${RED}โœ— (couldn't get issue ID)${NC}" continue fi # Check if issue is in project and get item ID ITEM_DATA=$(gh api graphql -f query=' query($projectId: ID!, $issueId: ID!) { node(id: $projectId) { ... on ProjectV2 { items(first: 100) { nodes { id content { ... on Issue { id } } } } } } } ' -f projectId="$PROJECT_ID" -f issueId="$ISSUE_NODE_ID" 2>/dev/null) ITEM_ID=$(echo "$ITEM_DATA" | jq -r ".data.node.items.nodes[] | select(.content.id == \"$ISSUE_NODE_ID\") | .id" 2>/dev/null) if [ -z "$ITEM_ID" ] || [ "$ITEM_ID" = "null" ]; then # Add to project first ADD_RESULT=$(gh api graphql -f query=' mutation($projectId: ID!, $contentId: ID!) { addProjectV2ItemById(input: {projectId: $projectId, contentId: $contentId}) { item { id } } } ' -f projectId="$PROJECT_ID" -f contentId="$ISSUE_NODE_ID" 2>/dev/null) ITEM_ID=$(echo "$ADD_RESULT" | jq -r '.data.addProjectV2ItemById.item.id' 2>/dev/null) if [ -z "$ITEM_ID" ] || [ "$ITEM_ID" = "null" ]; then echo -e "${YELLOW}โœ— (couldn't add to project)${NC}" continue fi fi # Update priority field UPDATE_RESULT=$(gh api graphql -f query=' mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: String!) { updateProjectV2ItemFieldValue( input: { projectId: $projectId itemId: $itemId fieldId: $fieldId value: { singleSelectOptionId: $value } } ) { projectV2Item { id } } } ' -f projectId="$PROJECT_ID" -f itemId="$ITEM_ID" -f fieldId="$FIELD_ID" -f value="$OPTION_ID" 2>&1) if [ $? -eq 0 ]; then echo -e "${GREEN}โœ“${NC}" SUCCESS=$((SUCCESS + 1)) else echo -e "${RED}โœ—${NC}" fi done echo " Processed $COUNT issues, $SUCCESS updated successfully" done echo -e "\n${GREEN}Sync complete!${NC}" } # Main execution main() { # Step 1: List and select project list_projects echo "" read -p "Enter project number: " PROJECT_NUM # Validate project number if ! [[ "$PROJECT_NUM" =~ ^[0-9]+$ ]]; then echo -e "${RED}Error: Project number must be a positive integer${NC}" exit 1 fi # Get project ID PROJECT_ID=$(gh api graphql -f query=' query($login: String!, $number: Int!) { user(login: $login) { projectV2(number: $number) { id title } } } ' -f login="$OWNER" -F number=$PROJECT_NUM --jq '.data.user.projectV2.id') if [ -z "$PROJECT_ID" ] || [ "$PROJECT_ID" = "null" ]; then echo -e "${RED}Project not found${NC}" exit 1 fi PROJECT_TITLE=$(gh api graphql -f query=' query($login: String!, $number: Int!) { user(login: $login) { projectV2(number: $number) { title } } } ' -f login="$OWNER" -F number=$PROJECT_NUM --jq '.data.user.projectV2.title') echo -e "${GREEN}Selected project: $PROJECT_TITLE${NC}" # Step 2: Find priority field FIELD_DATA=$(find_priority_field "$PROJECT_ID") if [ -z "$FIELD_DATA" ]; then echo -e "${RED}No priority field found in this project${NC}" exit 1 fi FIELD_ID=$(echo "$FIELD_DATA" | jq -r '.id' | head -n1) # Step 3: Update field options echo -e "\n${CYAN}Step 1: Update Priority Field Options${NC}" OPTION_IDS=$(update_priority_options "$PROJECT_ID" "$FIELD_ID" "$FIELD_DATA" | tail -n1) # Parse option IDs IFS='|' read -r HIGH_ID MEDIUM_ID LOW_ID <<< "$OPTION_IDS" # Step 4: Sync issues echo -e "\n${CYAN}Step 2: Sync Issues with Priority Labels${NC}" read -p "Sync issues now? (y/n): " sync_confirm if [ "$sync_confirm" = "y" ]; then sync_issues_to_project "$PROJECT_ID" "$FIELD_ID" "$HIGH_ID" "$MEDIUM_ID" "$LOW_ID" fi echo -e "\n${GREEN}All done!${NC}" echo -e "View your project at: https://github.com/users/$OWNER/projects/$PROJECT_NUM" } # Run main function main

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DollhouseMCP/DollhouseMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server