- Fix HTTP 422 errors by using label IDs instead of names - Add silent label creation to prevent stdout pollution in JSON building - Implement smart auto-creation of unknown labels (service-*, priority-*, etc.) - Add safe array handling to prevent bash associative array errors - Create tracking system for new labels (NEW_LABELS_CREATED array) ✅ Fixed: Label creation, issue creation, unknown label handling ⏳ TODO: Auto-update script synchronization when new labels created Status: Issue creation works perfectly, auto-update integration pending
449 lines
16 KiB
Bash
Executable file
449 lines
16 KiB
Bash
Executable file
#!/bin/bash
|
|
# scripts/create_issue.sh - Furt API Gateway Issue Creator
|
|
# FINAL VERSION with all fixes: HTTP 422, stdout-mixing, array handling, unknown labels
|
|
|
|
set -euo pipefail
|
|
|
|
# Standard environment setup
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|
export $(cat "$PROJECT_ROOT/.env" | grep -v '^#' | xargs)
|
|
fi
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
BLUE='\033[0;34m'
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
|
|
|
# Track new labels for auto-update (FIXED: Safe initialization)
|
|
declare -A NEW_LABELS_CREATED=()
|
|
|
|
# === LABEL DEFINITIONS START ===
|
|
# This section is auto-maintained by update_script_labels.sh
|
|
# DO NOT EDIT MANUALLY - Changes will be overwritten
|
|
declare -A LABEL_DEFINITIONS=(
|
|
["service-request"]="color:7057ff;context:new_service;usage:service_templates,status_updates"
|
|
["enhancement"]="color:84b6eb;context:improvement;usage:all_templates"
|
|
["bug"]="color:d73a4a;context:error;usage:bug_template,status_updates"
|
|
["gateway"]="color:0052cc;context:gateway_core;usage:architecture,performance,service_templates"
|
|
["performance"]="color:fbca04;context:optimization;usage:performance_template,architecture"
|
|
["architecture"]="color:d4c5f9;context:design;usage:architecture_template,gateway"
|
|
["security"]="color:28a745;context:security_review;usage:security_template,gateway"
|
|
["service-formular2mail"]="color:1d76db;context:formular2mail;usage:service_templates,integration"
|
|
["service-sagjan"]="color:1d76db;context:sagjan;usage:service_templates,integration"
|
|
["service-newsletter"]="color:ff6b6b;context:newsletter;usage:service_templates,integration"
|
|
["work-in-progress"]="color:fbca04;context:active;usage:status_updates"
|
|
["needs-review"]="color:0e8a16;context:review;usage:status_updates"
|
|
["hugo-integration"]="color:ff7518;context:frontend;usage:hugo_templates,integration"
|
|
["api-contract"]="color:5319e7;context:api_design;usage:api_templates,service_templates"
|
|
["breaking-change"]="color:d73a4a;context:breaking;usage:api_templates,architecture"
|
|
["high-priority"]="color:d73a4a;context:urgent;usage:all_templates"
|
|
["low-tech"]="color:6f42c1;context:low_tech_principle;usage:all_templates"
|
|
["digital-sovereignty"]="color:6f42c1;context:digital_sovereignty;usage:all_templates"
|
|
)
|
|
|
|
# Extract label info
|
|
get_label_color() { echo "${LABEL_DEFINITIONS[$1]}" | cut -d';' -f1 | cut -d':' -f2; }
|
|
get_label_context() { echo "${LABEL_DEFINITIONS[$1]}" | cut -d';' -f2 | cut -d':' -f2; }
|
|
get_label_usage() { echo "${LABEL_DEFINITIONS[$1]}" | cut -d';' -f3 | cut -d':' -f2; }
|
|
|
|
# Check if label is valid for context
|
|
is_label_valid_for_context() {
|
|
local label="$1"
|
|
local context="$2"
|
|
local usage=$(get_label_usage "$label")
|
|
[[ "$usage" == *"$context"* ]] || [[ "$usage" == "all_templates" ]]
|
|
}
|
|
# === LABEL DEFINITIONS END ===
|
|
|
|
# === TEMPLATE LABEL MAPPINGS START ===
|
|
# Auto-generated template to label mappings
|
|
declare -A TEMPLATE_LABELS=(
|
|
["service"]="service-request,enhancement,gateway,service-formular2mail,service-sagjan,service-newsletter,api-contract,high-priority,low-tech,digital-sovereignty"
|
|
["architecture"]="enhancement,gateway,performance,architecture,security,breaking-change,high-priority,low-tech,digital-sovereignty"
|
|
["performance"]="enhancement,gateway,performance,architecture,high-priority,low-tech,digital-sovereignty"
|
|
["bug"]="bug,enhancement,gateway,service-formular2mail,service-sagjan,service-newsletter,work-in-progress,needs-review,high-priority,low-tech,digital-sovereignty"
|
|
["security"]="security,gateway,enhancement,high-priority,low-tech,digital-sovereignty"
|
|
["hugo"]="hugo-integration,enhancement,gateway,service-formular2mail,service-sagjan,service-newsletter,api-contract,high-priority,low-tech,digital-sovereignty"
|
|
["api"]="api-contract,service-request,enhancement,gateway,service-formular2mail,service-sagjan,service-newsletter,breaking-change,high-priority,low-tech,digital-sovereignty"
|
|
["deployment"]="enhancement,gateway,service-formular2mail,service-sagjan,service-newsletter,high-priority,low-tech,digital-sovereignty"
|
|
)
|
|
# === TEMPLATE LABEL MAPPINGS END ===
|
|
|
|
# Load existing labels from repository
|
|
declare -A LABEL_IDS
|
|
|
|
load_existing_labels() {
|
|
if [[ -z "${GITEA_URL:-}" ]] || [[ -z "${GITEA_TOKEN:-}" ]]; then
|
|
log_error "GITEA_URL and GITEA_TOKEN must be set"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Loading existing labels from repository..."
|
|
|
|
local response=$(curl -s "$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/labels" \
|
|
-H "Authorization: token $GITEA_TOKEN")
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
log_error "Failed to fetch labels from repository"
|
|
exit 1
|
|
fi
|
|
|
|
while IFS= read -r line; do
|
|
local name=$(echo "$line" | jq -r '.name')
|
|
local id=$(echo "$line" | jq -r '.id')
|
|
LABEL_IDS["$name"]="$id"
|
|
done < <(echo "$response" | jq -c '.[]')
|
|
|
|
log_info "Loaded ${#LABEL_IDS[@]} existing labels"
|
|
}
|
|
|
|
# FIXED: Silent version of ensure_label_exists (no stdout pollution!)
|
|
ensure_label_exists_silent() {
|
|
local name="$1"
|
|
local color="${2:-ff6b6b}"
|
|
local description="${3:-Auto-generated label}"
|
|
|
|
if [[ -n "${LABEL_IDS[$name]:-}" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
# Create label (redirect output to prevent stdout mixing)
|
|
local response=$(curl -s -w "\n%{http_code}" -X POST \
|
|
"$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/labels" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"name\": \"$name\",
|
|
\"color\": \"$color\",
|
|
\"description\": \"$description\"
|
|
}" 2>/dev/null)
|
|
|
|
local http_code=$(echo "$response" | tail -n1)
|
|
local response_body=$(echo "$response" | head -n -1)
|
|
|
|
if [[ "$http_code" == "201" ]]; then
|
|
local new_id=$(echo "$response_body" | jq -r '.id')
|
|
LABEL_IDS["$name"]="$new_id"
|
|
|
|
# FIXED: Track for auto-update (but don't log here!)
|
|
NEW_LABELS_CREATED["$name"]="$color:auto_generated:all_templates"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# FIXED: Build labels JSON for API calls (handles unknown labels!)
|
|
build_labels_json() {
|
|
local template="$1"
|
|
shift
|
|
local additional_labels=("$@")
|
|
|
|
# Get template labels
|
|
local template_labels_string="${TEMPLATE_LABELS[$template]:-}"
|
|
local all_labels=()
|
|
|
|
# Add template labels
|
|
if [[ -n "$template_labels_string" ]]; then
|
|
IFS=',' read -ra template_labels <<< "$template_labels_string"
|
|
all_labels+=("${template_labels[@]}")
|
|
fi
|
|
|
|
# Add additional labels
|
|
all_labels+=("${additional_labels[@]}")
|
|
|
|
# FIXED: Ensure all labels exist and collect IDs (handles unknown labels!)
|
|
local label_ids=()
|
|
for label in "${all_labels[@]}"; do
|
|
# Process both known and unknown labels
|
|
if [[ -n "${LABEL_DEFINITIONS[$label]:-}" ]]; then
|
|
# Known label - use defined color and context
|
|
local color=$(get_label_color "$label")
|
|
local context=$(get_label_context "$label")
|
|
|
|
ensure_label_exists_silent "$label" "$color" "Furt: $context"
|
|
else
|
|
# FIXED: Unknown label - auto-create with smart defaults
|
|
local default_color="ff6b6b"
|
|
local default_context="auto_generated"
|
|
|
|
# Smart defaults based on label pattern
|
|
if [[ "$label" == service-* ]]; then
|
|
default_color="1d76db"
|
|
default_context="service_integration"
|
|
elif [[ "$label" == *-priority ]]; then
|
|
default_color="d73a4a"
|
|
default_context="priority_level"
|
|
elif [[ "$label" == hugo-* ]]; then
|
|
default_color="ff7518"
|
|
default_context="frontend_integration"
|
|
fi
|
|
|
|
ensure_label_exists_silent "$label" "$default_color" "Furt: $default_context"
|
|
fi
|
|
|
|
# Collect ID if label was created/exists
|
|
if [[ -n "${LABEL_IDS[$label]:-}" ]]; then
|
|
label_ids+=("${LABEL_IDS[$label]}")
|
|
fi
|
|
done
|
|
|
|
# Build JSON array (clean output only!)
|
|
if [[ ${#label_ids[@]} -gt 0 ]]; then
|
|
printf '[%s]' "$(IFS=','; echo "${label_ids[*]}")"
|
|
else
|
|
echo "[]"
|
|
fi
|
|
}
|
|
|
|
# Show which labels are being used (AFTER JSON building to avoid stdout pollution)
|
|
show_labels_used() {
|
|
local template="$1"
|
|
shift
|
|
local additional_labels=("$@")
|
|
|
|
log_info "Labels used for this issue:"
|
|
|
|
# Show template labels
|
|
local template_labels_string="${TEMPLATE_LABELS[$template]:-}"
|
|
if [[ -n "$template_labels_string" ]]; then
|
|
IFS=',' read -ra template_labels <<< "$template_labels_string"
|
|
for label in "${template_labels[@]}"; do
|
|
if [[ -n "${LABEL_IDS[$label]:-}" ]]; then
|
|
log_info " ✅ $label (ID: ${LABEL_IDS[$label]})"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Show additional labels
|
|
for label in "${additional_labels[@]}"; do
|
|
if [[ -n "${LABEL_IDS[$label]:-}" ]]; then
|
|
log_info " ✅ $label (ID: ${LABEL_IDS[$label]}) [NEW!]"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# FIXED: AUTO-UPDATE with safe array handling
|
|
auto_update_scripts_if_needed() {
|
|
# FIXED: Safe check for empty associative array
|
|
local new_labels_count=0
|
|
if [[ "${#NEW_LABELS_CREATED[@]}" -gt 0 ]] 2>/dev/null; then
|
|
new_labels_count=${#NEW_LABELS_CREATED[@]}
|
|
fi
|
|
|
|
if [[ $new_labels_count -eq 0 ]]; then
|
|
return 0 # No new labels, no update needed
|
|
fi
|
|
|
|
log_info "🔄 Auto-updating scripts with $new_labels_count new labels..."
|
|
|
|
# Add new labels to registry
|
|
for label_name in "${!NEW_LABELS_CREATED[@]}"; do
|
|
local label_info="${NEW_LABELS_CREATED[$label_name]}"
|
|
local color=$(echo "$label_info" | cut -d':' -f1)
|
|
local context=$(echo "$label_info" | cut -d':' -f2)
|
|
local usage=$(echo "$label_info" | cut -d':' -f3)
|
|
|
|
log_info "Adding '$label_name' to registry..."
|
|
|
|
# Add to registry (suppressing output to avoid noise)
|
|
FURT_AUTO_UPDATE=true "$SCRIPT_DIR/update_script_labels.sh" add "$label_name" "$color" "$context" "$usage" >/dev/null 2>&1 || true
|
|
done
|
|
|
|
# Update all scripts with new labels
|
|
log_info "Synchronizing all scripts..."
|
|
"$SCRIPT_DIR/update_script_labels.sh" update >/dev/null 2>&1 || true
|
|
|
|
log_success "✅ All scripts automatically synchronized with new labels!"
|
|
|
|
# Show what was added
|
|
echo ""
|
|
echo "🆕 New labels created and synchronized:"
|
|
for label_name in "${!NEW_LABELS_CREATED[@]}"; do
|
|
echo " - $label_name (ID: ${LABEL_IDS[$label_name]})"
|
|
done
|
|
echo ""
|
|
}
|
|
|
|
# Create issue templates
|
|
create_service_issue() {
|
|
local service_name="${1:-newsletter}"
|
|
|
|
local title="[SERVICE] $service_name für Furt Gateway"
|
|
local body="# Service-Request: $service_name
|
|
|
|
## 🏷️ Service-Details
|
|
**Name:** $service_name
|
|
**Port:** TBD
|
|
**Zweck:** [Service-Beschreibung]
|
|
|
|
## 📝 Funktionsanforderungen
|
|
- [ ] [Anforderung 1]
|
|
- [ ] [Anforderung 2]
|
|
- [ ] [Anforderung 3]
|
|
|
|
## 🔗 Gateway-Integration
|
|
- [ ] **Routing:** \`/v1/$service_name/*\`
|
|
- [ ] **Auth:** API-Key required
|
|
- [ ] **Rate-Limiting:** TBD req/min
|
|
- [ ] **Health-Check:** \`/health\`
|
|
|
|
## 🎯 Hugo-Integration
|
|
- [ ] **Shortcode:** \`{{< furt-$service_name >}}\`
|
|
- [ ] **JavaScript-Client**
|
|
- [ ] **CSS-Styling**
|
|
|
|
## ⚡ Priorität
|
|
🔥 **Hoch** - benötigt für Website-Launch"
|
|
|
|
# FIXED: Build labels JSON (clean, no stdout pollution) with additional service label
|
|
local labels_json=$(build_labels_json "service" "service-$service_name")
|
|
|
|
# Show which labels are being used (AFTER JSON building)
|
|
show_labels_used "service" "service-$service_name"
|
|
|
|
create_issue "$title" "$body" "$labels_json"
|
|
}
|
|
|
|
create_architecture_issue() {
|
|
local topic="${1:-middleware-optimization}"
|
|
|
|
local title="[ARCH] Gateway $topic"
|
|
local body="# Architektur-Diskussion: $topic
|
|
|
|
## 🎯 Architektur-Thema
|
|
[Beschreibung des Architektur-Themas]
|
|
|
|
## 📊 Aktuelle Situation
|
|
- [Status Quo 1]
|
|
- [Status Quo 2]
|
|
|
|
## 💡 Vorgeschlagene Änderung
|
|
- [Vorschlag 1]
|
|
- [Vorschlag 2]
|
|
|
|
## 🔄 Alternativen
|
|
1. **Option A:** [Beschreibung]
|
|
2. **Option B:** [Beschreibung]
|
|
|
|
## 📈 Betroffene Bereiche
|
|
- [ ] Gateway-Performance
|
|
- [ ] Service-Integration
|
|
- [ ] Security
|
|
- [ ] Configuration-Management"
|
|
|
|
local labels_json=$(build_labels_json "architecture")
|
|
|
|
create_issue "$title" "$body" "$labels_json"
|
|
}
|
|
|
|
# Generic issue creation
|
|
create_issue() {
|
|
local title="$1"
|
|
local body="$2"
|
|
local labels_json="$3"
|
|
|
|
log_info "Creating issue: $title"
|
|
|
|
local response=$(curl -s -w "\n%{http_code}" -X POST \
|
|
"$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/issues" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"title\": $(echo "$title" | jq -R .),
|
|
\"body\": $(echo "$body" | jq -R -s .),
|
|
\"labels\": $labels_json
|
|
}")
|
|
|
|
local http_code=$(echo "$response" | tail -n1)
|
|
local response_body=$(echo "$response" | head -n -1)
|
|
|
|
if [[ "$http_code" == "201" ]]; then
|
|
local issue_number=$(echo "$response_body" | jq -r '.number')
|
|
local issue_url=$(echo "$response_body" | jq -r '.html_url')
|
|
|
|
log_success "Issue #$issue_number created!"
|
|
echo "🔗 $issue_url"
|
|
else
|
|
log_error "Failed to create issue (HTTP: $http_code)"
|
|
log_error "Response: $response_body"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Show usage information
|
|
show_usage() {
|
|
echo "🎯 Furt API-Gateway Issue Creator"
|
|
echo ""
|
|
echo "Usage: $0 [TEMPLATE] [OPTIONS]"
|
|
echo ""
|
|
echo "📋 Available Templates:"
|
|
echo " service [name] New service for gateway (default: newsletter)"
|
|
echo " architecture [topic] Gateway architecture discussion (default: middleware-optimization)"
|
|
echo " performance [comp] Performance optimization (default: gateway)"
|
|
echo " api [service] API contract update (default: formular2mail)"
|
|
echo " security [comp] Security review/issue (default: gateway)"
|
|
echo " bug [comp] [desc] Bug report (default: gateway)"
|
|
echo " hugo [feature] Hugo integration (default: shortcode)"
|
|
echo " deployment [comp] Deployment issue (default: gateway)"
|
|
echo " custom Custom issue (interactive)"
|
|
echo ""
|
|
echo "🚀 Examples:"
|
|
echo " $0 service newsletter # Create newsletter service request"
|
|
echo " $0 architecture rate-limiting # Discuss rate limiting architecture"
|
|
echo " $0 performance gateway # Gateway performance optimization"
|
|
echo " $0 custom # Interactive custom issue"
|
|
}
|
|
|
|
# Main function
|
|
main() {
|
|
local template="${1:-help}"
|
|
|
|
if [[ "$template" == "help" ]] || [[ "$template" == "--help" ]] || [[ "$template" == "-h" ]]; then
|
|
show_usage
|
|
exit 0
|
|
fi
|
|
|
|
# Load existing labels
|
|
load_existing_labels
|
|
|
|
case "$template" in
|
|
service)
|
|
create_service_issue "${2:-newsletter}"
|
|
;;
|
|
architecture)
|
|
create_architecture_issue "${2:-middleware-optimization}"
|
|
;;
|
|
performance)
|
|
local component="${2:-gateway}"
|
|
local title="[PERF] $component Performance-Optimierung"
|
|
local body="# Performance-Optimierung: $component"
|
|
local labels_json=$(build_labels_json "performance")
|
|
create_issue "$title" "$body" "$labels_json"
|
|
;;
|
|
*)
|
|
log_error "Unknown template: $template"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# FIXED: AUTO-UPDATE: Automatically sync scripts if new labels were created
|
|
auto_update_scripts_if_needed
|
|
}
|
|
|
|
# Run if executed directly
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
main "$@"
|
|
fi
|
|
|