#!/bin/bash # Generate Slate documentation from OpenAPI specs # # This script: # 1. Discovers all services with OpenAPI specs # 2. Uses widdershins to convert OpenAPI JSON to Slate markdown # 3. Injects the generated includes into the main index # # Usage: ./docs/scripts/generate-docs.sh [base_url] # base_url: Optional base URL for fetching specs (default: http://localhost) # # The script expects services to be running locally during CI/CD build. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DOCS_DIR="$(dirname "$SCRIPT_DIR")" PROJECT_ROOT="$(dirname "$DOCS_DIR")" INCLUDES_DIR="$DOCS_DIR/source/includes" BASE_URL="${1:-http://localhost}" echo "==> Generating API documentation from OpenAPI specs" echo " Base URL: $BASE_URL" echo " Docs dir: $DOCS_DIR" # Ensure includes directory exists mkdir -p "$INCLUDES_DIR" # Clean old service includes (keep _errors.md) find "$INCLUDES_DIR" -name '_*.md' ! -name '_errors.md' -delete 2>/dev/null || true # Track which services we generate docs for SERVICES=() # Discover services by looking for OpenAPI spec files or main.go for service_dir in "$PROJECT_ROOT"/services/*/; do [ -d "$service_dir" ] || continue service_name=$(basename "$service_dir") [ "$service_name" = ".gitkeep" ] && continue echo "==> Processing service: $service_name" # Try to fetch OpenAPI spec from running service spec_url="$BASE_URL/api/$service_name/openapi.json" spec_file="$INCLUDES_DIR/_${service_name}_spec.json" if curl -sf --connect-timeout 5 "$spec_url" > "$spec_file" 2>/dev/null; then echo " Fetched spec from $spec_url" else # Fallback: check for static spec file if [ -f "$service_dir/openapi.json" ]; then cp "$service_dir/openapi.json" "$spec_file" echo " Using static spec from $service_dir/openapi.json" else echo " WARNING: No OpenAPI spec found for $service_name, skipping" rm -f "$spec_file" continue fi fi # Convert OpenAPI to Slate markdown using widdershins output_file="$INCLUDES_DIR/_${service_name}.md" echo " Converting to markdown..." widdershins \ --language_tabs 'shell:curl' 'go:Go' \ --summary \ --omitHeader \ --resolve \ --shallowSchemas \ "$spec_file" \ -o "$output_file" # Clean up temp spec file rm -f "$spec_file" SERVICES+=("$service_name") echo " Generated: $output_file" done # Update index.html.md with service includes INDEX_FILE="$DOCS_DIR/source/index.html.md" if [ -f "$INDEX_FILE" ]; then echo "==> Updating index with service includes" # Build includes list INCLUDES="" for svc in "${SERVICES[@]}"; do INCLUDES="$INCLUDES - $svc"$'\n' done # Update the includes section in frontmatter # This is a simple approach - insert after 'includes:' line if grep -q "^includes:" "$INDEX_FILE"; then # Create temp file with updated includes awk -v services="$INCLUDES" ' /^includes:/ { print $0 print " - errors" # Add service includes n = split(services, arr, "\n") for (i = 1; i <= n; i++) { if (arr[i] != "") print arr[i] } # Skip existing includes until next frontmatter key or --- while ((getline line) > 0) { if (line ~ /^[a-z_]+:/ || line == "---") { print line break } } next } { print } ' "$INDEX_FILE" > "$INDEX_FILE.tmp" && mv "$INDEX_FILE.tmp" "$INDEX_FILE" fi echo " Updated includes: ${SERVICES[*]:-none}" fi echo "" echo "==> Documentation generation complete" echo " Services documented: ${#SERVICES[@]}" echo "" echo "To build the static site:" echo " cd $DOCS_DIR && bundle exec middleman build"