Created
February 9, 2026 23:08
-
-
Save designfrontier/7e588e35ac942ae087cc2ec789d7c2f4 to your computer and use it in GitHub Desktop.
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
| #!/usr/bin/env bash | |
| # https://id.atlassian.com/manage-profile/security/api-tokens | |
| # for getting your tokens :pointup: | |
| # Required env vars: | |
| # JIRA_TOKEN=token from above here | |
| # JIRA_USERNAME=voze email | |
| # JIRA_BASE_URL=https://voze.atlassian.net | |
| # JIRA_TICKET_TYPES=("Tech Debt Task" "Bug" "Task" "Support Request") | |
| # JIRA_PROJECTS=("VE") | |
| # put these somewhere that gets them in the env vars before running the script | |
| JIRA_TEAMS=("Doritos Locos" "Baja Blast" "Bug Triage" "Cheesy Gordita Crunch" "Diablo Sauce") | |
| get_team_id() { | |
| case "$1" in | |
| "Doritos Locos") echo "dbf42f58-9e39-4323-bd1d-dd4e349ef535" ;; | |
| "Baja Blast") echo "ad1beac6-e009-477c-a3d6-7ba9bfae3007" ;; | |
| "Bug Triage") echo "072cf690-bba8-4376-98db-6af85ef892de" ;; | |
| "Cheesy Gordita Crunch") echo "6c7c02ac-fb09-4e5a-9e2e-64747d35ed6d" ;; | |
| "Diablo Sauce") echo "b406269c-77dd-4c7d-bc78-b462d1ed0395" ;; | |
| esac | |
| } | |
| show_help() { | |
| cat << EOF | |
| create-jira - Create Jira tickets from command line or interactively | |
| USAGE: | |
| create-jira [OPTIONS] | |
| create-jira SUMMARY DESCRIPTION TEAM [TYPE] [PROJECT] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| MODES: | |
| Interactive Mode (no arguments): | |
| create-jira | |
| Prompts for all required information interactively. | |
| CLI Mode (with arguments): | |
| create-jira "Summary" "Description" "Team" ["Type"] ["Project"] | |
| Creates ticket directly with provided arguments. | |
| Type defaults to "Task", Project defaults to "VE". | |
| ARGUMENTS: | |
| SUMMARY Brief one-line summary of the ticket | |
| DESCRIPTION Detailed description (can be multi-line) | |
| TEAM Assigned team (required) | |
| Valid teams: Doritos Locos, Baja Blast, Bug Triage, | |
| Cheesy Gordita Crunch, Diablo Sauce | |
| TYPE Ticket type (optional, default: Task) | |
| Valid types: Tech Debt Task, Bug, Task, Support Request | |
| PROJECT Project key (optional, default: VE) | |
| Valid projects: VE | |
| EXAMPLES: | |
| # Interactive mode | |
| create-jira | |
| # Create a Task (default type) in VE (default project) | |
| create-jira "Fix login bug" "Users unable to login after 2FA" "Baja Blast" | |
| # Create a Bug in VE | |
| create-jira "Fix login bug" "Users unable to login" "Bug Triage" "Bug" | |
| # Create a Tech Debt Task with full specification | |
| create-jira "Refactor auth module" "Split into smaller functions" "Doritos Locos" "Tech Debt Task" "VE" | |
| # Read description from file | |
| create-jira "Migrate SQL view" "\$(cat description.txt)" "Cheesy Gordita Crunch" "Tech Debt Task" | |
| ENVIRONMENT VARIABLES: | |
| Required (should be in ~/.localvars): | |
| JIRA_TOKEN API token from Atlassian | |
| JIRA_USERNAME Your Voze email | |
| JIRA_BASE_URL https://voze.atlassian.net | |
| JIRA_TICKET_TYPES Array of valid ticket types | |
| JIRA_PROJECTS Array of valid project keys | |
| REQUIREMENTS: | |
| - jq (install with: brew install jq) | |
| - curl | |
| - Valid Jira API credentials in ~/.localvars | |
| OUTPUT: | |
| On success, prints ticket key and URL: | |
| ✓ Ticket created: VE-1234 | |
| https://voze.atlassian.net/browse/VE-1234 | |
| On error, prints HTTP status and error details. | |
| EOF | |
| exit 0 | |
| } | |
| # Check for help flag | |
| if [[ "$1" == "-h" || "$1" == "--help" ]]; then | |
| show_help | |
| fi | |
| source ~/.localvars | |
| # Check if jq is available (required for proper JSON encoding) | |
| if ! command -v jq &> /dev/null; then | |
| echo "Error: jq is required but not installed. Install with: brew install jq" | |
| exit 1 | |
| fi | |
| # Check if arguments provided (CLI mode) | |
| if [ $# -ge 3 ]; then | |
| # CLI mode | |
| SUMMARY="$1" | |
| DESCRIPTION="$2" | |
| TEAM="$3" | |
| TYPE="${4:-Task}" # Default to Task | |
| PROJECT="${5:-VE}" # Default to VE | |
| # Validate team | |
| VALID_TEAM=false | |
| for valid_team in "${JIRA_TEAMS[@]}"; do | |
| if [ "$TEAM" = "$valid_team" ]; then | |
| VALID_TEAM=true | |
| break | |
| fi | |
| done | |
| if [ "$VALID_TEAM" = false ]; then | |
| echo "Error: Invalid team '$TEAM'. Must be one of: ${JIRA_TEAMS[*]}" | |
| exit 1 | |
| fi | |
| # Validate type | |
| VALID_TYPE=false | |
| for valid_type in "${JIRA_TICKET_TYPES[@]}"; do | |
| if [ "$TYPE" = "$valid_type" ]; then | |
| VALID_TYPE=true | |
| break | |
| fi | |
| done | |
| if [ "$VALID_TYPE" = false ]; then | |
| echo "Error: Invalid type '$TYPE'. Must be one of: ${JIRA_TICKET_TYPES[*]}" | |
| exit 1 | |
| fi | |
| # Validate project | |
| VALID_PROJECT=false | |
| for valid_project in "${JIRA_PROJECTS[@]}"; do | |
| if [ "$PROJECT" = "$valid_project" ]; then | |
| VALID_PROJECT=true | |
| break | |
| fi | |
| done | |
| if [ "$VALID_PROJECT" = false ]; then | |
| echo "Error: Invalid project '$PROJECT'. Must be one of: ${JIRA_PROJECTS[*]}" | |
| exit 1 | |
| fi | |
| else | |
| # Interactive mode (original behavior) | |
| GIT_MESSAGE=$(git log -n 1) | |
| read -p "Brief Summary:" SUMMARY | |
| read -p "Description:" DESCRIPTION | |
| echo "" | |
| echo 'Please enter ticket type: ' | |
| select T in "${JIRA_TICKET_TYPES[@]}" | |
| do | |
| case $T in | |
| "Tech Debt Task") | |
| TYPE="Tech Debt Task"; break | |
| ;; | |
| "Bug") | |
| TYPE="Bug"; break | |
| ;; | |
| "Task") | |
| TYPE="Task"; break | |
| ;; | |
| "Support Request") | |
| TYPE="Support Request"; break | |
| ;; | |
| *) echo "invalid option $REPLY";; | |
| esac | |
| done | |
| echo "" | |
| echo 'Please select team: ' | |
| select TM in "${JIRA_TEAMS[@]}" | |
| do | |
| if [[ -n "$TM" ]]; then | |
| TEAM="$TM"; break | |
| else | |
| echo "invalid option $REPLY" | |
| fi | |
| done | |
| echo "" | |
| echo 'Please select project: ' | |
| select P in "${JIRA_PROJECTS[@]}" | |
| do | |
| case $P in | |
| "VE") | |
| PROJECT="VE"; break | |
| ;; | |
| *) echo "invalid option $REPLY";; | |
| esac | |
| done | |
| fi | |
| # Resolve team name to ID | |
| TEAM_ID=$(get_team_id "$TEAM") | |
| # Build JSON using jq for proper escaping | |
| JSON=$(jq -n \ | |
| --arg project "$PROJECT" \ | |
| --arg summary "$SUMMARY" \ | |
| --arg description "$DESCRIPTION" \ | |
| --arg type "$TYPE" \ | |
| --arg team_id "$TEAM_ID" \ | |
| '{ | |
| fields: { | |
| project: {key: $project}, | |
| summary: $summary, | |
| description: $description, | |
| issuetype: {name: $type}, | |
| customfield_10001: $team_id | |
| } | |
| }') | |
| # Make API request and capture both body and status code | |
| RESPONSE=$(curl -sS -w "\n%{http_code}" \ | |
| -u "$JIRA_USERNAME:$JIRA_TOKEN" \ | |
| -X POST \ | |
| --data "$JSON" \ | |
| -H "Content-Type: application/json" \ | |
| "$JIRA_BASE_URL/rest/api/2/issue/") | |
| HTTP_CODE=$(echo "$RESPONSE" | tail -1) | |
| BODY=$(echo "$RESPONSE" | sed '$d') | |
| # Check if request was successful | |
| if [ "$HTTP_CODE" = "201" ]; then | |
| KEY=$(echo "$BODY" | jq -r '.key') | |
| echo "✓ Ticket created: $KEY" | |
| echo "$JIRA_BASE_URL/browse/$KEY" | |
| # Only try to open if we're in an interactive terminal | |
| if [ -t 0 ]; then | |
| open "$JIRA_BASE_URL/browse/$KEY" 2>/dev/null || true | |
| fi | |
| else | |
| echo "Error creating ticket (HTTP $HTTP_CODE):" | |
| echo "$BODY" | jq -r '.errorMessages[]?, .errors | to_entries[]? | "\(.key): \(.value)"' 2>/dev/null || echo "$BODY" | |
| exit 1 | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment