diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..73489f9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +# Atlantis with Overmind CLI +FROM ghcr.io/runatlantis/atlantis:latest + +# Switch to root to install +USER root + +# Install Overmind CLI from GitHub releases +RUN curl -fsSL https://github.com/overmindtech/cli/releases/download/v1.11.1/overmind_cli_Linux_x86_64.tar.gz -o /tmp/overmind.tar.gz && \ + tar -xzf /tmp/overmind.tar.gz -C /usr/local/bin && \ + rm /tmp/overmind.tar.gz && \ + chmod +x /usr/local/bin/overmind + +# Verify installation +RUN overmind --version + +# Switch back to atlantis user +USER atlantis diff --git a/README.md b/README.md index 108ea3e..12c86d2 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ This integration adds automated blast radius analysis and complete lifecycle tra - Atlantis server (self-hosted or cloud) - Overmind account ([sign up](https://app.overmind.tech)) +- Overmind CLI installed on Atlantis server - Terraform 0.12 or later ### Setup @@ -30,10 +31,6 @@ This integration adds automated blast radius analysis and complete lifecycle tra ```bash # Copy atlantis.yaml to your repository root cp atlantis.yaml /path/to/your/repo/ - - # Copy the integration script - cp scripts/overmind-integration.sh /path/to/your/repo/scripts/ - chmod +x /path/to/your/repo/scripts/overmind-integration.sh ``` 3. **Set the environment variable** on your Atlantis server: @@ -56,11 +53,22 @@ Test the integration locally before deploying: # Set your API key export OVM_API_KEY="your-overmind-api-key" -# Run the quick test +# Quick test - just submits a plan ./quick-test.sh + +# Full lifecycle test - simulates complete Atlantis workflow +./full-lifecycle-test.sh ``` -This will create a Terraform plan and submit it to Overmind for analysis. +The **quick test** creates a Terraform plan and submits it to Overmind. + +The **full lifecycle test** simulates the complete Atlantis workflow: +1. `terraform init` + `terraform plan` +2. `overmind submit-plan` - creates change +3. `overmind start-change` - marks as running +4. `terraform apply` - applies changes +5. `overmind end-change` - marks as complete +6. `overmind get-change` - retrieves summary ## How It Works @@ -75,7 +83,7 @@ Atlantis executes Terraform plan ↓ Plan submitted to Overmind (submit-plan) ↓ -Change ID saved for apply phase +Change URL returned, UUID extracted and saved ↓ Risk analysis available in Overmind dashboard ↓ @@ -94,10 +102,12 @@ The integration provides full lifecycle tracking of infrastructure changes: **Plan Phase:** 1. Executes `terraform plan` -2. Converts plan to JSON format -3. Submits to Overmind via `submit-plan` -4. Saves the Change ID to `.overmind-change-id` file -5. Links to PR and adds repository tags +2. Converts plan to JSON file (CLI requires a file, not stdin) +3. Submits JSON file to Overmind via `submit-plan` +4. Captures the change URL from stdout (e.g., `https://app.overmind.tech/changes/{uuid}/blast-radius`) +5. Extracts the UUID and saves it to `.overmind-change-id` file +6. Tags the change with repository and workspace info +7. Cleans up temporary JSON file **Apply Phase:** 1. Reads saved Change ID from `.overmind-change-id` @@ -107,6 +117,8 @@ The integration provides full lifecycle tracking of infrastructure changes: 5. Retrieves final change summary 6. Cleans up temporary files +> **Note:** The CLI outputs the change URL to stdout. It does not automatically post comments to PRs - view analysis in the Overmind dashboard or check Atlantis logs for the change URL. + ## Configuration ### Repository-Specific Setup @@ -123,31 +135,43 @@ workflows: - init - plan - run: | - # Submit plan and save Change ID - terraform show -json $PLANFILE | \ - overmind changes submit-plan - \ + # Convert plan to JSON (CLI requires a file, not stdin) + terraform show -json $PLANFILE > .overmind-plan.json + + # Submit and capture the change URL from output + CHANGE_URL=$(overmind changes submit-plan .overmind-plan.json \ --ticket-link "$PULL_REQUEST_URL" \ --tags "atlantis=true,repo=$BASE_REPO_NAME" \ - --format json > .overmind-response.json + 2>&1 | grep -oE 'https://[^ ]+' | head -1) + + rm -f .overmind-plan.json - CHANGE_ID=$(cat .overmind-response.json | grep -o '"uuid":"[^"]*"' | head -1 | cut -d'"' -f4) - echo "$CHANGE_ID" > .overmind-change-id + # Extract UUID from the URL (format: .../changes/{uuid}/blast-radius) + CHANGE_ID=$(echo "$CHANGE_URL" | grep -oE '[0-9a-f-]{36}') + + if [ -n "$CHANGE_ID" ]; then + echo "$CHANGE_ID" > .overmind-change-id + echo "View at: $CHANGE_URL" + fi apply: steps: - run: | - # Mark change as starting - CHANGE_ID=$(cat .overmind-change-id) - overmind changes start-change --uuid "$CHANGE_ID" + if [ -f .overmind-change-id ]; then + CHANGE_ID=$(cat .overmind-change-id) + overmind changes start-change --uuid "$CHANGE_ID" || true + fi - apply - run: | - # Mark change as complete - CHANGE_ID=$(cat .overmind-change-id) - overmind changes end-change --uuid "$CHANGE_ID" - overmind changes get-change --uuid "$CHANGE_ID" --format markdown + if [ -f .overmind-change-id ]; then + CHANGE_ID=$(cat .overmind-change-id) + overmind changes end-change --uuid "$CHANGE_ID" || true + overmind changes get-change --uuid "$CHANGE_ID" --format markdown || true + rm -f .overmind-change-id + fi ``` -The workflow saves the Change ID during `plan` to a file (`.overmind-change-id`), which is then used during `apply` to track the complete lifecycle. +The workflow saves the plan to a JSON file (required by the CLI), submits it, captures the change URL from the output, and extracts the UUID for the apply phase. **Fallback Hook (for repositories without custom workflows):** @@ -158,9 +182,10 @@ repos: - run: | # Simple post-plan submission for basic integration if [ "$COMMAND_NAME" = "plan" ]; then - terraform show -json "$PLANFILE" | \ - overmind changes submit-plan - \ + terraform show -json "$PLANFILE" > .overmind-plan.json + overmind changes submit-plan .overmind-plan.json \ --ticket-link "$PULL_REQUEST_URL" + rm -f .overmind-plan.json fi ``` @@ -177,6 +202,25 @@ repos: Place `scripts/overmind-integration.sh` on your Atlantis server and reference it in your server configuration. +## Valid CLI Flags + +### `submit-plan` Command + +| Flag | Description | +|------|-------------| +| `--ticket-link` | URL to the associated ticket/PR | +| `--tags` | Comma-separated key=value pairs (e.g., `repo=myrepo,env=prod`) | +| `--title` | Title for the change | +| `--description` | Description of the change | +| `--blast-radius-link-depth` | Depth for blast radius link analysis | +| `--blast-radius-max-items` | Maximum items in blast radius | +| `--blast-radius-max-time` | Maximum time for blast radius calculation | + +> **Note:** +> - `--format` and `--labels` flags are **not available** on `submit-plan` +> - The CLI requires a **file path** (not stdin) - piping with `-` is not supported +> - The change URL is printed to stdout on its own line + ## Features - **Complete Lifecycle Tracking** - Track changes from plan → apply → completion @@ -211,6 +255,7 @@ These variables are automatically provided by Atlantis: - `BASE_REPO_OWNER` - Repository owner - `PULL_NUM` - Pull request number - `WORKSPACE` - Terraform workspace name +- `COMMAND_NAME` - The Atlantis command being run (plan, apply, etc.) ## Targeted Plans @@ -253,9 +298,9 @@ overmind --version ### No Analysis Appearing -The integration submits plans to Overmind but doesn't post comments to PRs by default. View analysis at: +The CLI outputs the change URL to stdout but doesn't automatically post comments to PRs. View analysis at: - [Overmind Dashboard](https://app.overmind.tech) -- Use the change link from Atlantis logs +- Check Atlantis logs for the change URL ### Apply Fails with "Change ID not found" @@ -269,6 +314,19 @@ This occurs when the `.overmind-change-id` file is missing: **Prevention:** Ensure you're using the same workspace for plan and apply +### Could Not Extract Change ID + +If you see "Could not extract Change ID from URL": + +**Check:** +- The `submit-plan` command completed successfully +- The URL format matches expected pattern (contains a UUID) + +**Common Issues:** +- Network connectivity to Overmind API +- Invalid API key +- Empty plan (no changes) + ### Change Not Marked as Complete If `end-change` fails: @@ -310,7 +368,8 @@ See `docker-compose.yml` for configuration details. | `atlantis-server.yaml` | Example server-side configuration | | `scripts/overmind-integration.sh` | Reusable integration hook script | | `docker-compose.yml` | Docker setup for local testing | -| `quick-test.sh` | Local testing script | +| `quick-test.sh` | Quick plan submission test | +| `full-lifecycle-test.sh` | Full lifecycle test (plan → apply with all Overmind steps) | | `main.tf` | Example Terraform configuration | ## Security Considerations diff --git a/atlantis-server.yaml b/atlantis-server.yaml index e87b6d1..dc77d19 100644 --- a/atlantis-server.yaml +++ b/atlantis-server.yaml @@ -14,7 +14,7 @@ repos: post_workflow_hooks: - run: | # Only run for successful plans - if [ "$ATLANTIS_PLAN_EXIT_CODE" != "0" ]; then + if [ "${ATLANTIS_PLAN_EXIT_CODE:-0}" != "0" ]; then echo "Plan failed, skipping Overmind analysis" exit 0 fi @@ -25,20 +25,36 @@ repos: exit 0 fi - # Convert plan to JSON - terraform show -json $PLANFILE > tfplan.json - # Build tags - TAGS="atlantis=true,repo=$REPO_NAME,workspace=$WORKSPACE" - if [ ! -z "$ATLANTIS_TERRAFORM_TARGET" ]; then + TAGS="atlantis=true,repo=${BASE_REPO_NAME:-$REPO_NAME},workspace=${WORKSPACE:-default}" + if [ -n "$ATLANTIS_TERRAFORM_TARGET" ]; then TAGS="$TAGS,target=$ATLANTIS_TERRAFORM_TARGET" fi - # Submit to Overmind - overmind changes submit-plan tfplan.json \ + # Convert plan to JSON (CLI requires a file, not stdin) + terraform show -json "$PLANFILE" > .overmind-plan.json + + # Submit to Overmind and capture output + OUTPUT=$(overmind changes submit-plan .overmind-plan.json \ --ticket-link "$PULL_REQUEST_URL" \ - --tags "$TAGS" + --tags "$TAGS" \ + 2>&1) + + # Clean up temp file + rm -f .overmind-plan.json - # Post results - overmind changes get-change --format markdown | \ - gh pr comment $PULL_NUM --body-file - + # Extract the clean URL (CLI prints it on its own line) + CHANGE_URL=$(echo "$OUTPUT" | grep '^https://' | tail -1) + + if [ -n "$CHANGE_URL" ]; then + echo "✅ Plan submitted to Overmind" + echo "View at: $CHANGE_URL" + + # Extract UUID for lifecycle tracking + CHANGE_ID=$(echo "$CHANGE_URL" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') + if [ -n "$CHANGE_ID" ]; then + echo "$CHANGE_ID" > .overmind-change-id + fi + else + echo "⚠️ Warning: Overmind submission may have failed" + fi diff --git a/atlantis.yaml b/atlantis.yaml index 21799a0..d6123ba 100644 --- a/atlantis.yaml +++ b/atlantis.yaml @@ -11,21 +11,36 @@ workflows: - init - plan - run: | - # Submit plan to Overmind and save change ID for apply phase + # Submit plan to Overmind and capture the change URL echo "Submitting plan to Overmind..." - terraform show -json $PLANFILE | \ - overmind changes submit-plan - \ + + # Convert plan to JSON (CLI requires a file, not stdin) + terraform show -json $PLANFILE > .overmind-plan.json + + # Submit and capture output (CLI prints clean URL on last line) + OUTPUT=$(overmind changes submit-plan .overmind-plan.json \ --ticket-link "$PULL_REQUEST_URL" \ --tags "atlantis=true,repo=$BASE_REPO_NAME,workspace=$WORKSPACE" \ - --format json > .overmind-response.json + 2>&1) + + # Clean up temp file + rm -f .overmind-plan.json - # Extract and save change ID - CHANGE_ID=$(cat .overmind-response.json | grep -o '"uuid":"[^"]*"' | head -1 | cut -d'"' -f4) - echo "$CHANGE_ID" > .overmind-change-id + # Extract the clean URL (printed on its own line starting with https://) + CHANGE_URL=$(echo "$OUTPUT" | grep '^https://' | tail -1) - echo "✅ Plan submitted to Overmind" - echo "Change ID: $CHANGE_ID" - echo "View at: https://app.overmind.tech/changes/$CHANGE_ID/blast-radius" + # Extract UUID from the URL (format: .../changes/{uuid}/blast-radius) + CHANGE_ID=$(echo "$CHANGE_URL" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') + + if [ -z "$CHANGE_ID" ]; then + echo "⚠️ Warning: Could not extract Change ID" + echo "Plan may have been submitted - check Overmind dashboard" + else + echo "$CHANGE_ID" > .overmind-change-id + echo "✅ Plan submitted to Overmind" + echo "Change ID: $CHANGE_ID" + echo "View at: $CHANGE_URL" + fi apply: steps: @@ -34,7 +49,10 @@ workflows: if [ -f .overmind-change-id ]; then CHANGE_ID=$(cat .overmind-change-id) echo "🚀 Starting change: $CHANGE_ID" - overmind changes start-change --uuid "$CHANGE_ID" || echo "Warning: Could not mark change as started" + overmind changes start-change --uuid "$CHANGE_ID" || \ + echo "⚠️ Warning: Could not mark change as started" + else + echo "⚠️ No Change ID found - skipping lifecycle tracking" fi - apply - run: | @@ -42,15 +60,17 @@ workflows: if [ -f .overmind-change-id ]; then CHANGE_ID=$(cat .overmind-change-id) echo "✅ Marking change as complete: $CHANGE_ID" - overmind changes end-change --uuid "$CHANGE_ID" || echo "Warning: Could not mark change as complete" + overmind changes end-change --uuid "$CHANGE_ID" || \ + echo "⚠️ Warning: Could not mark change as complete" # Get final change summary echo "" echo "📊 Final Change Summary:" - overmind changes get-change --uuid "$CHANGE_ID" --format markdown || echo "Could not retrieve change summary" + overmind changes get-change --uuid "$CHANGE_ID" --format markdown || \ + echo "⚠️ Could not retrieve change summary" # Cleanup - rm -f .overmind-change-id .overmind-response.json + rm -f .overmind-change-id fi # Post-workflow hooks for repositories without custom workflows @@ -63,12 +83,27 @@ repos: if [ "$COMMAND_NAME" = "plan" ] && [ -f "$PLANFILE" ] && [ ! -f .overmind-change-id ]; then echo "=== Overmind Integration Hook ===" - # Convert plan to JSON and submit to Overmind - terraform show -json "$PLANFILE" | \ - overmind changes submit-plan - \ + # Convert plan to JSON (CLI requires a file, not stdin) + terraform show -json "$PLANFILE" > .overmind-plan.json + + # Submit and capture output + OUTPUT=$(overmind changes submit-plan .overmind-plan.json \ --ticket-link "${PULL_REQUEST_URL:-https://github.com/$BASE_REPO_OWNER/$BASE_REPO_NAME/pull/$PULL_NUM}" \ - --tags "atlantis=true,repo=$BASE_REPO_NAME" || echo "Warning: Overmind submission failed" + --tags "atlantis=true,repo=$BASE_REPO_NAME" \ + 2>&1) + + # Clean up temp file + rm -f .overmind-plan.json + + # Extract the clean URL + CHANGE_URL=$(echo "$OUTPUT" | grep '^https://' | tail -1) + + if [ -n "$CHANGE_URL" ]; then + echo "✅ Plan submitted to Overmind" + echo "View at: $CHANGE_URL" + else + echo "⚠️ Warning: Overmind submission may have failed" + fi echo "=== Overmind Hook Complete ===" fi - diff --git a/docker-compose.yml b/docker-compose.yml index f6e9039..29984c9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,8 @@ services: atlantis: - image: ghcr.io/runatlantis/atlantis:latest + build: + context: . + dockerfile: Dockerfile ports: - "4141:4141" environment: @@ -9,17 +11,10 @@ services: - ATLANTIS_GH_TOKEN=${GITHUB_TOKEN} - ATLANTIS_GH_WEBHOOK_SECRET=${WEBHOOK_SECRET} - ATLANTIS_PORT=4141 - - ATLANTIS_ATLANTIS_URL=${ATLANTIS_URL} + - ATLANTIS_ATLANTIS_URL=${ATLANTIS_URL:-http://localhost:4141} - ATLANTIS_LOG_LEVEL=debug - - ATLANTIS_REPO_CONFIG_JSON=${REPO_CONFIG} - # AWS credentials for Terraform - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - - AWS_DEFAULT_REGION=eu-west-1 # Overmind API key - OVM_API_KEY=${OVM_API_KEY} volumes: - - ~/.aws:/home/atlantis/.aws:ro - - ./scripts:/scripts + - ./scripts:/scripts:ro command: server - diff --git a/quick-test.sh b/quick-test.sh index 950aa4d..1a6e969 100755 --- a/quick-test.sh +++ b/quick-test.sh @@ -23,15 +23,36 @@ fi echo "📋 Creating Terraform plan..." terraform plan -out=test.tfplan -# Submit to Overmind +# Convert plan to JSON (CLI requires a file, not stdin) echo "" +echo "🔄 Converting plan to JSON..." +terraform show -json test.tfplan > test.tfplan.json + +# Submit to Overmind echo "🔄 Submitting plan to Overmind..." -terraform show -json test.tfplan | overmind changes submit-plan - \ +OUTPUT=$(overmind changes submit-plan test.tfplan.json \ --ticket-link "https://github.com/overmindtech/atlantis-example/pull/test-$(date +%s)" \ - --tags "test=local,user=$USER" + --tags "test=local,user=$USER" \ + 2>&1) + +# The CLI prints the clean URL on the last line +CHANGE_URL=$(echo "$OUTPUT" | grep '^https://' | tail -1) echo "" -echo "✅ Done! View your analysis at: https://app.overmind.tech" -echo "" -echo "Clean up: rm test.tfplan" +if [ -n "$CHANGE_URL" ]; then + echo "✅ Plan submitted successfully!" + echo "View your analysis at: $CHANGE_URL" + + # Extract and display the Change ID + CHANGE_ID=$(echo "$CHANGE_URL" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') + if [ -n "$CHANGE_ID" ]; then + echo "Change ID: $CHANGE_ID" + fi +else + echo "⚠️ Warning: Could not capture change URL" + echo "Output was:" + echo "$OUTPUT" +fi +echo "" +echo "Clean up: rm test.tfplan test.tfplan.json" diff --git a/run-atlantis-local.sh b/run-atlantis-local.sh new file mode 100755 index 0000000..2ef57b5 --- /dev/null +++ b/run-atlantis-local.sh @@ -0,0 +1,119 @@ +#!/bin/bash +# Run Atlantis locally with Overmind integration +# This script helps you test the full Atlantis + Overmind workflow + +set -e + +echo "🚀 Atlantis + Overmind Local Setup" +echo "===================================" +echo "" + +# Check required tools +command -v docker >/dev/null 2>&1 || { echo "❌ Docker is required but not installed."; exit 1; } +command -v ngrok >/dev/null 2>&1 || { echo "❌ ngrok is required but not installed."; exit 1; } + +# Check required environment variables +MISSING_VARS=() +[ -z "$GITHUB_TOKEN" ] && MISSING_VARS+=("GITHUB_TOKEN") +[ -z "$GITHUB_USER" ] && MISSING_VARS+=("GITHUB_USER") +[ -z "$OVM_API_KEY" ] && MISSING_VARS+=("OVM_API_KEY") + +if [ ${#MISSING_VARS[@]} -gt 0 ]; then + echo "❌ Missing required environment variables:" + for var in "${MISSING_VARS[@]}"; do + echo " - $var" + done + echo "" + echo "Set them with:" + echo " export GITHUB_TOKEN='ghp_...' # GitHub Personal Access Token" + echo " export GITHUB_USER='your-username' # Your GitHub username" + echo " export OVM_API_KEY='ovm_api_...' # Overmind API key" + echo "" + echo "To create a GitHub token:" + echo " 1. Go to https://github.com/settings/tokens" + echo " 2. Generate new token (classic)" + echo " 3. Select scopes: repo, admin:repo_hook" + exit 1 +fi + +# Generate webhook secret if not set +if [ -z "$WEBHOOK_SECRET" ]; then + WEBHOOK_SECRET=$(openssl rand -hex 20) + echo "📝 Generated webhook secret: $WEBHOOK_SECRET" + export WEBHOOK_SECRET +fi + +echo "✅ All required variables set" +echo "" + +# Build the Docker image with Overmind CLI +echo "🐳 Building Atlantis + Overmind Docker image..." +docker compose build +echo "" + +# Start ngrok in background +echo "🌐 Starting ngrok tunnel..." +ngrok http 4141 --log=stdout > /tmp/ngrok.log 2>&1 & +NGROK_PID=$! +sleep 3 + +# Get the ngrok URL +NGROK_URL=$(curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"https://[^"]*' | cut -d'"' -f4) + +if [ -z "$NGROK_URL" ]; then + echo "❌ Failed to get ngrok URL. Check /tmp/ngrok.log" + kill $NGROK_PID 2>/dev/null + exit 1 +fi + +echo "✅ ngrok tunnel: $NGROK_URL" +export ATLANTIS_URL="$NGROK_URL" +echo "" + +echo "═══════════════════════════════════════════════════════════════" +echo "📋 WEBHOOK SETUP INSTRUCTIONS" +echo "═══════════════════════════════════════════════════════════════" +echo "" +echo "Configure a GitHub Webhook for your test repository:" +echo "" +echo " Payload URL: ${NGROK_URL}/events" +echo " Content type: application/json" +echo " Secret: $WEBHOOK_SECRET" +echo "" +echo " Events to trigger:" +echo " ☑ Pull requests" +echo " ☑ Issue comments" +echo " ☑ Push" +echo "" +echo " Webhook settings URL:" +echo " https://github.com/$GITHUB_USER/atlantis-example/settings/hooks/new" +echo "" +echo "═══════════════════════════════════════════════════════════════" +echo "" +echo "Press ENTER when webhook is configured..." +read -r + +echo "" +echo "🚀 Starting Atlantis..." +echo "" +echo "Once running, you can:" +echo " 1. Create a PR with Terraform changes" +echo " 2. Comment 'atlantis plan' on the PR" +echo " 3. View the Overmind analysis in logs and dashboard" +echo " 4. Comment 'atlantis apply' to apply" +echo "" +echo "Press Ctrl+C to stop" +echo "" + +# Cleanup function +cleanup() { + echo "" + echo "🧹 Cleaning up..." + docker compose down 2>/dev/null + kill $NGROK_PID 2>/dev/null + echo "Done!" +} +trap cleanup EXIT + +# Run Atlantis with Docker Compose +docker compose up diff --git a/scripts/overmind-integration.sh b/scripts/overmind-integration.sh index 51351ef..b0a5e89 100755 --- a/scripts/overmind-integration.sh +++ b/scripts/overmind-integration.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Overmind Integration Hook for Atlantis +# This script submits Terraform plans to Overmind for blast radius analysis + set -e # Debug logging @@ -7,12 +10,11 @@ exec 2>&1 echo "=== Overmind Hook Started: $(date) ===" echo "PLANFILE: $PLANFILE" echo "PULL_REQUEST_URL: $PULL_REQUEST_URL" -echo "REPO_NAME: $REPO_NAME" +echo "BASE_REPO_NAME: $BASE_REPO_NAME" echo "WORKSPACE: $WORKSPACE" -echo "ATLANTIS_PLAN_EXIT_CODE: $ATLANTIS_PLAN_EXIT_CODE" # Only run for successful plans -if [ "$ATLANTIS_PLAN_EXIT_CODE" != "0" ]; then +if [ "${ATLANTIS_PLAN_EXIT_CODE:-0}" != "0" ]; then echo "Plan failed, skipping Overmind analysis" exit 0 fi @@ -23,51 +25,48 @@ if [ ! -f "$PLANFILE" ]; then exit 0 fi -# Convert plan to JSON -echo "Converting plan to JSON..." -terraform show -json $PLANFILE > tfplan.json - # Build tags including workspace and target info -TAGS="atlantis=true,repo=$REPO_NAME,workspace=$WORKSPACE" -if [ ! -z "$ATLANTIS_TERRAFORM_TARGET" ]; then +TAGS="atlantis=true,repo=${BASE_REPO_NAME:-$REPO_NAME},workspace=${WORKSPACE:-default}" +if [ -n "$ATLANTIS_TERRAFORM_TARGET" ]; then TAGS="$TAGS,target=$ATLANTIS_TERRAFORM_TARGET" echo "Targeted plan detected: $ATLANTIS_TERRAFORM_TARGET" fi -# Submit to Overmind +# Convert plan to JSON (CLI requires a file, not stdin) +echo "Converting plan to JSON..." +terraform show -json "$PLANFILE" > .overmind-plan.json + +# Submit to Overmind and capture output echo "Submitting plan to Overmind..." -overmind changes submit-plan tfplan.json \ +OUTPUT=$(overmind changes submit-plan .overmind-plan.json \ --ticket-link "$PULL_REQUEST_URL" \ - --tags "$TAGS" + --tags "$TAGS" \ + 2>&1) + +# Clean up temp file +rm -f .overmind-plan.json -# Retrieve and format results -echo "Retrieving Overmind analysis..." -overmind changes get-change --format markdown > overmind-results.md +# Extract the clean URL (CLI prints it on its own line starting with https://) +CHANGE_URL=$(echo "$OUTPUT" | grep '^https://' | tail -1) -# Post results based on VCS type -echo "Posting results to VCS..." -case "$VCS_TYPE" in - github) - if command -v gh &> /dev/null; then - gh pr comment $PULL_NUM --body-file overmind-results.md - echo "Posted results to GitHub PR #$PULL_NUM" - else - echo "GitHub CLI not found, skipping PR comment" - cat overmind-results.md - fi - ;; - gitlab) - echo "GitLab integration not implemented yet" - cat overmind-results.md - ;; - bitbucket) - echo "Bitbucket integration not implemented yet" - cat overmind-results.md - ;; - *) - echo "Unknown VCS type: $VCS_TYPE" - cat overmind-results.md - ;; -esac +if [ -z "$CHANGE_URL" ]; then + echo "⚠️ Warning: No URL captured from Overmind submit-plan" + echo "Output was: $OUTPUT" + exit 0 +fi + +echo "✅ Plan submitted to Overmind" +echo "View at: $CHANGE_URL" + +# Extract UUID from the URL for lifecycle tracking +CHANGE_ID=$(echo "$CHANGE_URL" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') + +if [ -n "$CHANGE_ID" ]; then + echo "Change ID: $CHANGE_ID" + echo "$CHANGE_ID" > .overmind-change-id + echo "Change ID saved for apply phase lifecycle tracking" +else + echo "⚠️ Could not extract Change ID from URL - lifecycle tracking unavailable" +fi echo "=== Overmind Hook Completed: $(date) ==="