From ec87c5479b16502f217f91f77caa4445664d4e6f Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sat, 7 Feb 2026 11:13:43 -0600 Subject: [PATCH] feat(#344): Add Woodpecker CI pipeline monitoring to cli-tools - Add ci-pipeline-status.sh for checking pipeline status - Add ci-pipeline-logs.sh for fetching logs - Add ci-pipeline-wait.sh for waiting on completion - Update package.json bin section - Update README with CI commands and examples Co-Authored-By: Claude Sonnet 4.5 --- packages/cli-tools/README.md | 45 +++++- packages/cli-tools/bin/ci-pipeline-logs.sh | 111 ++++++++++++++ packages/cli-tools/bin/ci-pipeline-status.sh | 108 +++++++++++++ packages/cli-tools/bin/ci-pipeline-wait.sh | 152 +++++++++++++++++++ packages/cli-tools/package.json | 3 + 5 files changed, 414 insertions(+), 5 deletions(-) create mode 100755 packages/cli-tools/bin/ci-pipeline-logs.sh create mode 100755 packages/cli-tools/bin/ci-pipeline-status.sh create mode 100755 packages/cli-tools/bin/ci-pipeline-wait.sh diff --git a/packages/cli-tools/README.md b/packages/cli-tools/README.md index 4563339..56a3462 100644 --- a/packages/cli-tools/README.md +++ b/packages/cli-tools/README.md @@ -1,14 +1,19 @@ # @mosaic/cli-tools -CLI tools for Mosaic Stack orchestration - git operations that work with both Gitea and GitHub. +CLI tools for Mosaic Stack orchestration - git operations and CI monitoring. ## Overview -These scripts abstract the differences between `tea` (Gitea CLI) and `gh` (GitHub CLI), providing a unified interface for: +These scripts provide unified interfaces for: -- Issue management (create, list, assign, close, comment) -- Pull request management (create, list, merge, review) -- Milestone management (create, list, close) +- **Git Operations**: Abstract differences between `tea` (Gitea CLI) and `gh` (GitHub CLI) + - Issue management (create, list, assign, close, comment) + - Pull request management (create, list, merge, review) + - Milestone management (create, list, close) +- **CI Monitoring**: Woodpecker CI pipeline integration + - Pipeline status checking + - Log retrieval + - Automated waiting for completion ## Installation @@ -56,6 +61,14 @@ pnpm exec mosaic-issue-create -t "Title" -b "Body" | `mosaic-milestone-list` | List milestones | | `mosaic-milestone-close` | Close a milestone | +### CI/CD (Woodpecker) + +| Command | Description | +| --------------------------- | ------------------------------------ | +| `mosaic-ci-pipeline-status` | Check pipeline status (latest or #N) | +| `mosaic-ci-pipeline-logs` | Fetch pipeline logs | +| `mosaic-ci-pipeline-wait` | Wait for pipeline completion | + ## Usage Examples ### Create an issue with milestone @@ -90,6 +103,19 @@ mosaic-pr-create \ mosaic-pr-merge -n 42 -m squash -d ``` +### Monitor CI pipeline + +```bash +# Check latest pipeline status +mosaic-ci-pipeline-status --latest + +# Wait for specific pipeline to complete +mosaic-ci-pipeline-wait -n 42 + +# Fetch logs on failure +mosaic-ci-pipeline-logs -n 42 +``` + ## Platform Detection The scripts automatically detect whether you're working with Gitea or GitHub by examining the git remote URL. No configuration needed. @@ -99,10 +125,19 @@ The scripts automatically detect whether you're working with Gitea or GitHub by ## Requirements +### Git Operations + - **Gitea**: `tea` CLI installed and authenticated - **GitHub**: `gh` CLI installed and authenticated - **Both**: `git` available in PATH +### CI Monitoring (Woodpecker) + +- `woodpecker` CLI installed ([installation guide](https://woodpecker-ci.org/docs/usage/cli)) +- Environment variables set: + - `WOODPECKER_SERVER` - Woodpecker server URL (e.g., `https://ci.mosaicstack.dev`) + - `WOODPECKER_TOKEN` - API token from Woodpecker UI (User → Access tokens) + ## For Orchestrators When using these tools in orchestrator/worker contexts: diff --git a/packages/cli-tools/bin/ci-pipeline-logs.sh b/packages/cli-tools/bin/ci-pipeline-logs.sh new file mode 100755 index 0000000..77261f4 --- /dev/null +++ b/packages/cli-tools/bin/ci-pipeline-logs.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# ci-pipeline-logs.sh - Fetch Woodpecker CI pipeline logs +# Usage: ci-pipeline-logs.sh -n [-r ] [-s ] + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/detect-platform.sh" + +# Parse arguments +REPO="" +PIPELINE_NUM="" +STEP="" + +show_help() { + cat << EOF +Usage: ci-pipeline-logs.sh [OPTIONS] + +Fetch logs for a Woodpecker CI pipeline. + +Options: + -n, --number Pipeline number (required) + -r, --repo Repository (default: auto-detect from git remote) + -s, --step Specific step name/number + -h, --help Show this help + +Environment: + WOODPECKER_SERVER Woodpecker server URL (required) + WOODPECKER_TOKEN Woodpecker API token (required) + +Examples: + # Get all logs for pipeline 42 + ci-pipeline-logs.sh -n 42 + + # Get logs for specific step + ci-pipeline-logs.sh -n 42 -s test + + # Get logs for specific repo + ci-pipeline-logs.sh -r mosaic/stack -n 42 +EOF +} + +while [[ $# -gt 0 ]]; do + case $1 in + -r|--repo) + REPO="$2" + shift 2 + ;; + -n|--number) + PIPELINE_NUM="$2" + shift 2 + ;; + -s|--step) + STEP="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Validate required arguments +if [[ -z "$PIPELINE_NUM" ]]; then + echo "Error: Pipeline number is required (-n)" + show_help + exit 1 +fi + +# Check required environment variables +if [[ -z "$WOODPECKER_SERVER" ]]; then + echo "Error: WOODPECKER_SERVER environment variable not set" + exit 1 +fi + +if [[ -z "$WOODPECKER_TOKEN" ]]; then + echo "Error: WOODPECKER_TOKEN environment variable not set" + exit 1 +fi + +# Auto-detect repo if not provided +if [[ -z "$REPO" ]]; then + REPO=$(get_repo_info) + if [[ $? -ne 0 ]]; then + echo "Error: Could not auto-detect repository. Use -r option." + exit 1 + fi +fi + +# Check if woodpecker CLI is installed +if ! command -v woodpecker &> /dev/null; then + echo "Error: woodpecker CLI not found. Install it first:" + echo " Arch: paru -S woodpecker" + echo " Other: https://woodpecker-ci.org/docs/usage/cli" + exit 1 +fi + +# Get pipeline logs +if [[ -n "$STEP" ]]; then + # Get logs for specific step + woodpecker log show "$REPO" "$PIPELINE_NUM" "$STEP" +else + # Get all logs + woodpecker log show "$REPO" "$PIPELINE_NUM" +fi diff --git a/packages/cli-tools/bin/ci-pipeline-status.sh b/packages/cli-tools/bin/ci-pipeline-status.sh new file mode 100755 index 0000000..8c09429 --- /dev/null +++ b/packages/cli-tools/bin/ci-pipeline-status.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# ci-pipeline-status.sh - Check Woodpecker CI pipeline status +# Usage: ci-pipeline-status.sh [-r ] [-n ] [--latest] + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/detect-platform.sh" + +# Parse arguments +REPO="" +PIPELINE_NUM="" +LATEST=false + +show_help() { + cat << EOF +Usage: ci-pipeline-status.sh [OPTIONS] + +Check Woodpecker CI pipeline status for a repository. + +Options: + -r, --repo Repository (default: auto-detect from git remote) + -n, --number Pipeline number + --latest Get status of latest pipeline + -h, --help Show this help + +Environment: + WOODPECKER_SERVER Woodpecker server URL (required) + WOODPECKER_TOKEN Woodpecker API token (required) + +Examples: + # Get latest pipeline status for current repo + ci-pipeline-status.sh --latest + + # Get specific pipeline status + ci-pipeline-status.sh -n 42 + + # Get pipeline status for specific repo + ci-pipeline-status.sh -r mosaic/stack --latest +EOF +} + +while [[ $# -gt 0 ]]; do + case $1 in + -r|--repo) + REPO="$2" + shift 2 + ;; + -n|--number) + PIPELINE_NUM="$2" + shift 2 + ;; + --latest) + LATEST=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Check required environment variables +if [[ -z "$WOODPECKER_SERVER" ]]; then + echo "Error: WOODPECKER_SERVER environment variable not set" + exit 1 +fi + +if [[ -z "$WOODPECKER_TOKEN" ]]; then + echo "Error: WOODPECKER_TOKEN environment variable not set" + exit 1 +fi + +# Auto-detect repo if not provided +if [[ -z "$REPO" ]]; then + REPO=$(get_repo_info) + if [[ $? -ne 0 ]]; then + echo "Error: Could not auto-detect repository. Use -r option." + exit 1 + fi +fi + +# Check if woodpecker CLI is installed +if ! command -v woodpecker &> /dev/null; then + echo "Error: woodpecker CLI not found. Install it first:" + echo " Arch: paru -S woodpecker" + echo " Other: https://woodpecker-ci.org/docs/usage/cli" + exit 1 +fi + +# Get pipeline status +if [[ "$LATEST" == true ]]; then + # Get latest pipeline + woodpecker pipeline ls "$REPO" --limit 1 +elif [[ -n "$PIPELINE_NUM" ]]; then + # Get specific pipeline info + woodpecker pipeline info "$REPO" "$PIPELINE_NUM" +else + echo "Error: Either --latest or -n is required" + show_help + exit 1 +fi diff --git a/packages/cli-tools/bin/ci-pipeline-wait.sh b/packages/cli-tools/bin/ci-pipeline-wait.sh new file mode 100755 index 0000000..d0d9fb5 --- /dev/null +++ b/packages/cli-tools/bin/ci-pipeline-wait.sh @@ -0,0 +1,152 @@ +#!/bin/bash +# ci-pipeline-wait.sh - Wait for Woodpecker CI pipeline completion +# Usage: ci-pipeline-wait.sh -n [-r ] [-t ] + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/detect-platform.sh" + +# Parse arguments +REPO="" +PIPELINE_NUM="" +TIMEOUT=1800 # 30 minutes default +POLL_INTERVAL=10 # 10 seconds + +show_help() { + cat << EOF +Usage: ci-pipeline-wait.sh [OPTIONS] + +Wait for a Woodpecker CI pipeline to complete. + +Options: + -n, --number Pipeline number (required) + -r, --repo Repository (default: auto-detect from git remote) + -t, --timeout Timeout in seconds (default: 1800) + -i, --interval Poll interval in seconds (default: 10) + -h, --help Show this help + +Environment: + WOODPECKER_SERVER Woodpecker server URL (required) + WOODPECKER_TOKEN Woodpecker API token (required) + +Exit codes: + 0 - Pipeline succeeded + 1 - Error or timeout + 2 - Pipeline failed + 3 - Pipeline killed/cancelled + +Examples: + # Wait for pipeline 42 to complete + ci-pipeline-wait.sh -n 42 + + # Wait with custom timeout (10 minutes) + ci-pipeline-wait.sh -n 42 -t 600 +EOF +} + +while [[ $# -gt 0 ]]; do + case $1 in + -r|--repo) + REPO="$2" + shift 2 + ;; + -n|--number) + PIPELINE_NUM="$2" + shift 2 + ;; + -t|--timeout) + TIMEOUT="$2" + shift 2 + ;; + -i|--interval) + POLL_INTERVAL="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Validate required arguments +if [[ -z "$PIPELINE_NUM" ]]; then + echo "Error: Pipeline number is required (-n)" + show_help + exit 1 +fi + +# Check required environment variables +if [[ -z "$WOODPECKER_SERVER" ]]; then + echo "Error: WOODPECKER_SERVER environment variable not set" + exit 1 +fi + +if [[ -z "$WOODPECKER_TOKEN" ]]; then + echo "Error: WOODPECKER_TOKEN environment variable not set" + exit 1 +fi + +# Auto-detect repo if not provided +if [[ -z "$REPO" ]]; then + REPO=$(get_repo_info) + if [[ $? -ne 0 ]]; then + echo "Error: Could not auto-detect repository. Use -r option." + exit 1 + fi +fi + +# Check if woodpecker CLI is installed +if ! command -v woodpecker &> /dev/null; then + echo "Error: woodpecker CLI not found. Install it first:" + echo " Arch: paru -S woodpecker" + echo " Other: https://woodpecker-ci.org/docs/usage/cli" + exit 1 +fi + +echo "Waiting for pipeline #$PIPELINE_NUM in $REPO (timeout: ${TIMEOUT}s)..." + +elapsed=0 +while [[ $elapsed -lt $TIMEOUT ]]; do + # Get pipeline info + pipeline_info=$(woodpecker pipeline info "$REPO" "$PIPELINE_NUM" 2>&1) + + # Extract status from output + # Woodpecker CLI outputs status in format like "STATUS: success" + if echo "$pipeline_info" | grep -q "success"; then + echo "✓ Pipeline succeeded" + exit 0 + elif echo "$pipeline_info" | grep -q "failure\|error"; then + echo "✗ Pipeline failed" + echo "" + echo "$pipeline_info" + exit 2 + elif echo "$pipeline_info" | grep -q "killed\|cancelled"; then + echo "✗ Pipeline was cancelled" + echo "" + echo "$pipeline_info" + exit 3 + elif echo "$pipeline_info" | grep -q "pending\|running"; then + # Still running + echo -n "." + sleep "$POLL_INTERVAL" + elapsed=$((elapsed + POLL_INTERVAL)) + else + # Unknown status, show info and continue + echo "" + echo "Unknown status, continuing to wait..." + echo "$pipeline_info" + sleep "$POLL_INTERVAL" + elapsed=$((elapsed + POLL_INTERVAL)) + fi +done + +echo "" +echo "✗ Timeout after ${TIMEOUT}s" +exit 1 diff --git a/packages/cli-tools/package.json b/packages/cli-tools/package.json index c2836d2..42da22e 100644 --- a/packages/cli-tools/package.json +++ b/packages/cli-tools/package.json @@ -4,6 +4,9 @@ "description": "CLI tools for Mosaic Stack orchestration - git operations for Gitea/GitHub", "private": true, "bin": { + "mosaic-ci-pipeline-logs": "./bin/ci-pipeline-logs.sh", + "mosaic-ci-pipeline-status": "./bin/ci-pipeline-status.sh", + "mosaic-ci-pipeline-wait": "./bin/ci-pipeline-wait.sh", "mosaic-detect-platform": "./bin/detect-platform.sh", "mosaic-issue-assign": "./bin/issue-assign.sh", "mosaic-issue-close": "./bin/issue-close.sh",