diff --git a/tools/_lib/credentials.sh b/tools/_lib/credentials.sh index 11aa113..fde4e47 100755 --- a/tools/_lib/credentials.sh +++ b/tools/_lib/credentials.sh @@ -48,7 +48,8 @@ Services and exported variables: github → GITHUB_TOKEN gitea-mosaicstack → GITEA_URL, GITEA_TOKEN gitea-usc → GITEA_URL, GITEA_TOKEN - woodpecker → WOODPECKER_URL, WOODPECKER_TOKEN + woodpecker → WOODPECKER_URL, WOODPECKER_TOKEN (uses default instance) + woodpecker- → WOODPECKER_URL, WOODPECKER_TOKEN (specific instance, e.g. woodpecker-usc) cloudflare → CLOUDFLARE_API_TOKEN (uses default instance) cloudflare- → CLOUDFLARE_API_TOKEN (specific instance, e.g. cloudflare-personal) EOF @@ -105,12 +106,37 @@ EOF [[ -n "$GITEA_URL" ]] || { echo "Error: gitea.usc.url not found" >&2; return 1; } [[ -n "$GITEA_TOKEN" ]] || { echo "Error: gitea.usc.token not found" >&2; return 1; } ;; - woodpecker) - export WOODPECKER_URL="${WOODPECKER_URL:-$(_mosaic_read_cred '.woodpecker.url')}" - export WOODPECKER_TOKEN="${WOODPECKER_TOKEN:-$(_mosaic_read_cred '.woodpecker.token')}" + woodpecker-*) + local wp_instance="${service#woodpecker-}" + export WOODPECKER_URL="${WOODPECKER_URL:-$(_mosaic_read_cred ".woodpecker.${wp_instance}.url")}" + export WOODPECKER_TOKEN="${WOODPECKER_TOKEN:-$(_mosaic_read_cred ".woodpecker.${wp_instance}.token")}" + export WOODPECKER_INSTANCE="$wp_instance" WOODPECKER_URL="${WOODPECKER_URL%/}" - [[ -n "$WOODPECKER_URL" ]] || { echo "Error: woodpecker.url not found" >&2; return 1; } - [[ -n "$WOODPECKER_TOKEN" ]] || { echo "Error: woodpecker.token not found" >&2; return 1; } + [[ -n "$WOODPECKER_URL" ]] || { echo "Error: woodpecker.${wp_instance}.url not found" >&2; return 1; } + [[ -n "$WOODPECKER_TOKEN" ]] || { echo "Error: woodpecker.${wp_instance}.token not found" >&2; return 1; } + ;; + woodpecker) + # Resolve default instance, then load it + local wp_default + wp_default="${WOODPECKER_INSTANCE:-$(_mosaic_read_cred '.woodpecker.default')}" + if [[ -z "$wp_default" ]]; then + # Fallback: try legacy flat structure (.woodpecker.url / .woodpecker.token) + local legacy_url + legacy_url="$(_mosaic_read_cred '.woodpecker.url')" + if [[ -n "$legacy_url" ]]; then + export WOODPECKER_URL="${WOODPECKER_URL:-$legacy_url}" + export WOODPECKER_TOKEN="${WOODPECKER_TOKEN:-$(_mosaic_read_cred '.woodpecker.token')}" + WOODPECKER_URL="${WOODPECKER_URL%/}" + [[ -n "$WOODPECKER_URL" ]] || { echo "Error: woodpecker.url not found" >&2; return 1; } + [[ -n "$WOODPECKER_TOKEN" ]] || { echo "Error: woodpecker.token not found" >&2; return 1; } + else + echo "Error: woodpecker.default not set and no WOODPECKER_INSTANCE env var" >&2 + echo "Available instances: $(jq -r '.woodpecker | keys | join(", ")' "$MOSAIC_CREDENTIALS_FILE" 2>/dev/null)" >&2 + return 1 + fi + else + load_credentials "woodpecker-${wp_default}" + fi ;; cloudflare-*) local cf_instance="${service#cloudflare-}" @@ -130,7 +156,7 @@ EOF ;; *) echo "Error: Unknown service '$service'" >&2 - echo "Supported: portainer, coolify, authentik, glpi, github, gitea-mosaicstack, gitea-usc, woodpecker, cloudflare, cloudflare-" >&2 + echo "Supported: portainer, coolify, authentik, glpi, github, gitea-mosaicstack, gitea-usc, woodpecker[-], cloudflare[-]" >&2 return 1 ;; esac diff --git a/tools/woodpecker/pipeline-list.sh b/tools/woodpecker/pipeline-list.sh index 21a380d..ee75207 100755 --- a/tools/woodpecker/pipeline-list.sh +++ b/tools/woodpecker/pipeline-list.sh @@ -2,48 +2,43 @@ # # pipeline-list.sh — List Woodpecker CI pipelines # -# Usage: pipeline-list.sh [-r owner/repo] [-l limit] [-f format] +# Usage: pipeline-list.sh [-r owner/repo] [-l limit] [-f format] [-a instance] # # Options: -# -r repo Repository in owner/repo format (default: current repo) -# -l limit Number of pipelines to show (default: 20) -# -f format Output format: table (default), json -# -h Show this help +# -r repo Repository in owner/repo format (default: current repo) +# -l limit Number of pipelines to show (default: 20) +# -f format Output format: table (default), json +# -a instance Woodpecker instance name (e.g. usc, mosaic) +# -h Show this help # -# Requires: woodpecker.url and woodpecker.token in credentials.json +# Requires: woodpecker credentials in credentials.json set -euo pipefail MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}" source "$MOSAIC_HOME/tools/_lib/credentials.sh" -# Check if woodpecker credentials exist before loading -CRED_FILE="${MOSAIC_CREDENTIALS_FILE:-$HOME/src/jarvis-brain/credentials.json}" -if ! jq -e '.woodpecker.token // empty | select(. != "")' "$CRED_FILE" &>/dev/null; then - echo "Error: Woodpecker API token not configured in credentials.json" >&2 - echo "" >&2 - echo "To configure:" >&2 - echo " 1. Get your token from Woodpecker CI → User Settings → API" >&2 - echo " 2. Add to credentials.json:" >&2 - echo ' "woodpecker": {"url": "https://ci.mosaicstack.dev", "token": "YOUR_TOKEN"}' >&2 - exit 1 -fi - -load_credentials woodpecker - REPO="" LIMIT=20 FORMAT="table" +WP_INSTANCE="" -while getopts "r:l:f:h" opt; do +while getopts "r:l:f:a:h" opt; do case $opt in r) REPO="$OPTARG" ;; l) LIMIT="$OPTARG" ;; f) FORMAT="$OPTARG" ;; + a) WP_INSTANCE="$OPTARG" ;; h) head -14 "$0" | grep "^#" | sed 's/^# \?//'; exit 0 ;; - *) echo "Usage: $0 [-r owner/repo] [-l limit] [-f format]" >&2; exit 1 ;; + *) echo "Usage: $0 [-r owner/repo] [-l limit] [-f format] [-a instance]" >&2; exit 1 ;; esac done +if [[ -n "$WP_INSTANCE" ]]; then + load_credentials "woodpecker-${WP_INSTANCE}" +else + load_credentials woodpecker +fi + # Auto-detect repo from git remote if not specified if [[ -z "$REPO" ]]; then remote_url=$(git remote get-url origin 2>/dev/null || true) diff --git a/tools/woodpecker/pipeline-status.sh b/tools/woodpecker/pipeline-status.sh index 95e96a9..73b959d 100755 --- a/tools/woodpecker/pipeline-status.sh +++ b/tools/woodpecker/pipeline-status.sh @@ -2,43 +2,43 @@ # # pipeline-status.sh — Check Woodpecker CI pipeline status # -# Usage: pipeline-status.sh [-r owner/repo] [-n number] [-f format] +# Usage: pipeline-status.sh [-r owner/repo] [-n number] [-f format] [-a instance] # # Options: -# -r repo Repository in owner/repo format (default: current repo) -# -n number Pipeline number (default: latest) -# -f format Output format: table (default), json -# -h Show this help +# -r repo Repository in owner/repo format (default: current repo) +# -n number Pipeline number (default: latest) +# -f format Output format: table (default), json +# -a instance Woodpecker instance name (e.g. usc, mosaic) +# -h Show this help # -# Requires: woodpecker.url and woodpecker.token in credentials.json +# Requires: woodpecker credentials in credentials.json set -euo pipefail MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}" source "$MOSAIC_HOME/tools/_lib/credentials.sh" -CRED_FILE="${MOSAIC_CREDENTIALS_FILE:-$HOME/src/jarvis-brain/credentials.json}" -if ! jq -e '.woodpecker.token // empty | select(. != "")' "$CRED_FILE" &>/dev/null; then - echo "Error: Woodpecker API token not configured in credentials.json" >&2 - echo "See: ~/.config/mosaic/tools/woodpecker/README.md" >&2 - exit 1 -fi - -load_credentials woodpecker - REPO="" NUMBER="" FORMAT="table" +WP_INSTANCE="" -while getopts "r:n:f:h" opt; do +while getopts "r:n:f:a:h" opt; do case $opt in r) REPO="$OPTARG" ;; n) NUMBER="$OPTARG" ;; f) FORMAT="$OPTARG" ;; + a) WP_INSTANCE="$OPTARG" ;; h) head -14 "$0" | grep "^#" | sed 's/^# \?//'; exit 0 ;; - *) echo "Usage: $0 [-r owner/repo] [-n number] [-f format]" >&2; exit 1 ;; + *) echo "Usage: $0 [-r owner/repo] [-n number] [-f format] [-a instance]" >&2; exit 1 ;; esac done +if [[ -n "$WP_INSTANCE" ]]; then + load_credentials "woodpecker-${WP_INSTANCE}" +else + load_credentials woodpecker +fi + if [[ -z "$REPO" ]]; then remote_url=$(git remote get-url origin 2>/dev/null || true) if [[ -n "$remote_url" ]]; then diff --git a/tools/woodpecker/pipeline-trigger.sh b/tools/woodpecker/pipeline-trigger.sh index 24a456f..cf09132 100755 --- a/tools/woodpecker/pipeline-trigger.sh +++ b/tools/woodpecker/pipeline-trigger.sh @@ -2,40 +2,40 @@ # # pipeline-trigger.sh — Trigger a Woodpecker CI pipeline # -# Usage: pipeline-trigger.sh [-r owner/repo] [-b branch] +# Usage: pipeline-trigger.sh [-r owner/repo] [-b branch] [-a instance] # # Options: -# -r repo Repository in owner/repo format (default: current repo) -# -b branch Branch to build (default: main) -# -h Show this help +# -r repo Repository in owner/repo format (default: current repo) +# -b branch Branch to build (default: main) +# -a instance Woodpecker instance name (e.g. usc, mosaic) +# -h Show this help # -# Requires: woodpecker.url and woodpecker.token in credentials.json +# Requires: woodpecker credentials in credentials.json set -euo pipefail MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}" source "$MOSAIC_HOME/tools/_lib/credentials.sh" -CRED_FILE="${MOSAIC_CREDENTIALS_FILE:-$HOME/src/jarvis-brain/credentials.json}" -if ! jq -e '.woodpecker.token // empty | select(. != "")' "$CRED_FILE" &>/dev/null; then - echo "Error: Woodpecker API token not configured in credentials.json" >&2 - echo "See: ~/.config/mosaic/tools/woodpecker/README.md" >&2 - exit 1 -fi - -load_credentials woodpecker - REPO="" BRANCH="main" +WP_INSTANCE="" -while getopts "r:b:h" opt; do +while getopts "r:b:a:h" opt; do case $opt in r) REPO="$OPTARG" ;; b) BRANCH="$OPTARG" ;; - h) head -12 "$0" | grep "^#" | sed 's/^# \?//'; exit 0 ;; - *) echo "Usage: $0 [-r owner/repo] [-b branch]" >&2; exit 1 ;; + a) WP_INSTANCE="$OPTARG" ;; + h) head -14 "$0" | grep "^#" | sed 's/^# \?//'; exit 0 ;; + *) echo "Usage: $0 [-r owner/repo] [-b branch] [-a instance]" >&2; exit 1 ;; esac done +if [[ -n "$WP_INSTANCE" ]]; then + load_credentials "woodpecker-${WP_INSTANCE}" +else + load_credentials woodpecker +fi + if [[ -z "$REPO" ]]; then remote_url=$(git remote get-url origin 2>/dev/null || true) if [[ -n "$remote_url" ]]; then