rdev/cookbooks/scripts/sdlc-test.sh
jordan f22b220c6d feat: add SDLC branch management, merge, archive, and orchestrator APIs
Add branch lifecycle commands (branch, merge, archive) to the SDLC CLI.
Introduce orchestrator handler and service for multi-step SDLC workflows.
Expand skeleton template with 15 Claude commands covering the full feature
lifecycle. Extend classifier rules, error types, and executor port for
branch operations. Split rules.go and classifier_test.go to stay within
500-line limit.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:30:03 -07:00

284 lines
8.9 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# SDLC Orchestration E2E Test Script
# Tests the full SDLC lifecycle through the rdev API.
#
# Flow:
# 1. Get SDLC state (verify endpoint works)
# 2. Create feature
# 3. Transition through phases with artifact checks
# 4. Branch, merge, archive
#
# Usage:
# ./cookbooks/scripts/sdlc-test.sh run [project-id] # Run the full flow
# ./cookbooks/scripts/sdlc-test.sh status [project-id] # Show SDLC state
# ./cookbooks/scripts/sdlc-test.sh teardown [project-id] # Clean up test feature
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"
COMMAND="${1:-}"
PROJECT_ID="${2:-}"
FEATURE_SLUG="sdlc-test-$(date +%s)"
if [[ -z "$COMMAND" ]]; then
echo "SDLC Orchestration E2E Test Script"
echo ""
echo "Usage: $0 <command> <project-id>"
echo ""
echo "Commands:"
echo " run - Run the full SDLC lifecycle flow"
echo " status - Show SDLC state for a project"
echo " teardown - Delete test feature from project"
echo ""
echo "Examples:"
echo " $0 run my-project"
echo " $0 status my-project"
echo " $0 teardown my-project"
echo ""
echo "Requires: RDEV_API_URL, RDEV_API_KEY, and an existing project with SDLC initialized"
exit 1
fi
if [[ -z "$PROJECT_ID" ]]; then
echo "Error: project-id is required"
exit 1
fi
# Helper: check response for error
check_response() {
local response="$1"
local step="$2"
local error
error=$(echo "$response" | jq -r '.error // ""')
if [[ -n "$error" && "$error" != "" && "$error" != "null" ]]; then
print_error "$step failed: $error"
echo "$response" | jq '.'
return 1
fi
return 0
}
# Main run flow
run_flow() {
print_header "SDLC E2E Test"
echo "Project: $PROJECT_ID"
echo "Feature: $FEATURE_SLUG"
# Step 1: Get SDLC state
print_header "Step 1: Get SDLC State"
local state_response
state_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/state")
if check_response "$state_response" "Get state"; then
print_success "SDLC state retrieved"
echo "$state_response" | jq '.data.version // .data'
else
print_error "Failed to get SDLC state - is SDLC initialized for this project?"
return 1
fi
# Step 2: Create feature
print_header "Step 2: Create Feature"
local create_response
create_response=$(api_call POST "/projects/$PROJECT_ID/sdlc/features" \
"{\"slug\": \"$FEATURE_SLUG\", \"title\": \"SDLC E2E Test Feature\"}")
if check_response "$create_response" "Create feature"; then
print_success "Feature created: $FEATURE_SLUG"
else
return 1
fi
# Step 3: List features
print_header "Step 3: List Features"
local list_response
list_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/features")
if check_response "$list_response" "List features"; then
local count
count=$(echo "$list_response" | jq '.data | length')
print_success "Listed $count features"
fi
# Step 4: Get feature detail
print_header "Step 4: Get Feature Detail"
local detail_response
detail_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG")
if check_response "$detail_response" "Get feature"; then
local phase
phase=$(echo "$detail_response" | jq -r '.data.phase // "unknown"')
print_success "Feature phase: $phase"
fi
# Step 5: Get classifier recommendation
print_header "Step 5: Get Classifier Recommendation"
local next_response
next_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/next?feature=$FEATURE_SLUG")
if check_response "$next_response" "Get next"; then
local action
action=$(echo "$next_response" | jq -r '.data.action // "unknown"')
local message
message=$(echo "$next_response" | jq -r '.data.message // ""')
print_success "Next action: $action"
echo " Message: $message"
fi
# Step 6: Check artifact status
print_header "Step 6: Check Artifact Status"
local artifacts_response
artifacts_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG/artifacts")
if check_response "$artifacts_response" "Get artifacts"; then
print_success "Artifact status retrieved"
fi
# Step 7: Add a task
print_header "Step 7: Add Task"
local task_response
task_response=$(api_call POST "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG/tasks" \
'{"title": "Test task for E2E validation"}')
if check_response "$task_response" "Add task"; then
local task_id
task_id=$(echo "$task_response" | jq -r '.data.id // "unknown"')
print_success "Task added: $task_id"
# Step 7b: List tasks
local tasks_response
tasks_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG/tasks")
if check_response "$tasks_response" "List tasks"; then
local task_count
task_count=$(echo "$tasks_response" | jq '.data | length')
print_success "Listed $task_count tasks"
fi
fi
# Step 8: Block and unblock feature
print_header "Step 8: Block/Unblock Feature"
local block_response
block_response=$(api_call POST "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG/block" \
'{"reason": "E2E test blocker"}')
if check_response "$block_response" "Block feature"; then
print_success "Feature blocked"
fi
# Query blocked
local blocked_response
blocked_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/query/blocked")
if check_response "$blocked_response" "Query blocked"; then
local blocked_count
blocked_count=$(echo "$blocked_response" | jq '.data | length')
print_success "Blocked features: $blocked_count"
fi
local unblock_response
unblock_response=$(api_call POST "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG/unblock")
if check_response "$unblock_response" "Unblock feature"; then
print_success "Feature unblocked"
fi
# Step 9: Query endpoints
print_header "Step 9: Query Endpoints"
local ready_response
ready_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/query/ready")
if check_response "$ready_response" "Query ready"; then
print_success "Query ready: OK"
fi
local approval_response
approval_response=$(api_call GET "/projects/$PROJECT_ID/sdlc/query/needs-approval")
if check_response "$approval_response" "Query needs-approval"; then
print_success "Query needs-approval: OK"
fi
# Step 10: Clean up - delete the test feature
print_header "Step 10: Cleanup"
local delete_response
delete_response=$(api_call DELETE "/projects/$PROJECT_ID/sdlc/features/$FEATURE_SLUG")
print_success "Feature deleted: $FEATURE_SLUG"
# Summary
print_header "Results"
print_success "All SDLC E2E tests passed!"
echo ""
echo " Tested endpoints:"
echo " GET /sdlc/state"
echo " GET /sdlc/next"
echo " GET /sdlc/features"
echo " POST /sdlc/features"
echo " GET /sdlc/features/{slug}"
echo " GET /sdlc/features/{slug}/artifacts"
echo " POST /sdlc/features/{slug}/tasks"
echo " GET /sdlc/features/{slug}/tasks"
echo " POST /sdlc/features/{slug}/block"
echo " POST /sdlc/features/{slug}/unblock"
echo " GET /sdlc/query/blocked"
echo " GET /sdlc/query/ready"
echo " GET /sdlc/query/needs-approval"
echo " DELETE /sdlc/features/{slug}"
}
# Show SDLC status
show_status() {
print_header "SDLC Status for $PROJECT_ID"
echo "State:"
api_call GET "/projects/$PROJECT_ID/sdlc/state" | jq '.data'
echo ""
echo "Features:"
api_call GET "/projects/$PROJECT_ID/sdlc/features" | jq '.data'
echo ""
echo "Blocked:"
api_call GET "/projects/$PROJECT_ID/sdlc/query/blocked" | jq '.data'
echo ""
echo "Needs Approval:"
api_call GET "/projects/$PROJECT_ID/sdlc/query/needs-approval" | jq '.data'
}
# Teardown test feature
teardown_flow() {
print_header "SDLC Teardown"
# List features to find test ones
local features
features=$(api_call GET "/projects/$PROJECT_ID/sdlc/features" | jq -r '.data[]?.slug // empty')
if [[ -z "$features" ]]; then
echo "No features found for project $PROJECT_ID"
return 0
fi
echo "Features:"
echo "$features"
echo ""
# Delete features matching test pattern
for slug in $features; do
if [[ "$slug" == sdlc-test-* ]]; then
echo "Deleting test feature: $slug"
api_call DELETE "/projects/$PROJECT_ID/sdlc/features/$slug"
print_success "Deleted: $slug"
fi
done
}
# Dispatch
case "$COMMAND" in
run)
run_flow
;;
status)
show_status
;;
teardown)
teardown_flow
;;
*)
echo "Unknown command: $COMMAND"
echo "Use: run, status, or teardown"
exit 1
;;
esac