rdev/cookbooks/trees/slackpath-5-full-lifecycle.yaml
jordan adcea2fc1f
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix(templates): upgrade Go to 1.25 and fix Woodpecker syntax
## Template Version Alignment
- Go: 1.23 → 1.25 across all templates (go.work, go.mod, Dockerfiles, CI)
- Alpine: latest → 3.19 (explicit version pinning)
- Woodpecker: failure:retry → failure:ignore (invalid syntax fix)

## SDLC Tree Fixes (slackpath-5-full-lifecycle)
Fixed merge failures by correcting lifecycle flow:

1. **Branch Creation**: Added missing create-branch step (planned → ready)
   - Bug: Merge command requires feature.Branch field to be set
   - Fix: POST /projects/{id}/sdlc/features/{slug}/branch

2. **Artifact Status**: Changed approval to pass for execution artifacts
   - Bug: Review/audit/QA need status="passed" not "approved"
   - Fix: /artifacts/{type}/approve → /artifacts/{type}/pass
   - Added: pass-qa step after wait-qa

3. **Phase Transition Order**: Reordered merge phase transition
   - Bug: Merge command checks if phase == "merge" first
   - Fix: transition-to-merge BEFORE merge-feature (not after)

## GCS Provisioner Fix
- Replaced deprecated option.WithCredentialsFile with env var approach
- Now uses GOOGLE_APPLICATION_CREDENTIALS for ADC (Application Default Credentials)
- Avoids security risk from deprecated credential options
- Fixed test: Added ComponentTypeGCS to ValidComponentTypes test

## Critical Rules Added
- Version alignment: All template versions must stay in sync
- When updating versions, grep entire templates/ tree

## Files Changed
- 27 template files: Go version + Woodpecker syntax
- 1 tree file: SDLC lifecycle flow corrections
- 1 CLAUDE.md: Version alignment rule
- 1 GCS provisioner: Deprecated API fix
- 1 test file: Added missing component type

Root cause: Skeleton templates lagged behind Go 1.25 release and had
invalid Woodpecker syntax. SDLC tree skipped required branch creation
and used wrong artifact approval endpoints.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 23:57:38 -07:00

554 lines
18 KiB
YAML

name: full-lifecycle
description: "Slack Path 5: The Full Lifecycle. Tests all 10 SDLC phases with explicit artifact approvals."
version: 1
vars:
project_name: ""
feature_slug: "user-preferences"
feature_title: "User Preferences API"
steps:
# ============================================================
# INFRASTRUCTURE
# ============================================================
create-project:
action: api
method: POST
endpoint: /project
body:
name: "{{ .vars.project_name }}"
description: "Slack Path 5: Full SDLC Lifecycle"
outputs:
- project_id: .data.name
- domain: .data.domain
add-db:
description: Add database for preferences storage
depends_on: [create-project]
on_error: continue
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/components"
body:
type: postgres
name: "main-db"
add-service:
description: Add API service
depends_on: [add-db]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/components"
body:
type: service
name: "preferences-api"
wait-init:
description: Wait for initial deploy (docs builds may be slow)
depends_on: [add-service]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
on_error: continue
# ============================================================
# PHASE 1: DRAFT
# Create feature (starts in draft phase)
# ============================================================
create-feature:
description: "Create feature in draft phase"
depends_on: [wait-init]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features"
body:
slug: "{{ .vars.feature_slug }}"
title: "{{ .vars.feature_title }}"
outputs:
- feature_phase: .data.phase
verify-draft:
description: "Verify feature is in draft phase"
depends_on: [create-feature]
action: shell
command: |
PHASE="{{ .outputs.create-feature.feature_phase }}"
if [ "$PHASE" == "draft" ]; then
echo "Feature created in draft phase"
exit 0
else
echo "Expected draft, got $PHASE"
exit 1
fi
# ============================================================
# PHASE 2: DRAFT → SPECIFIED
# Agent writes spec, API approves, transition
# ============================================================
write-spec:
description: "Agent writes the spec artifact"
depends_on: [verify-draft]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/spec-feature {{ .vars.feature_slug }} --requirements 'CRUD API for user preferences. GET/PUT /preferences/{user_id}. Preferences are key-value pairs stored in DB. Support theme, language, notifications settings.'"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-spec:
depends_on: [write-spec]
action: wait_build
build_id: "{{ .outputs.write-spec.build_id }}"
max_attempts: 720
poll_interval: 5
approve-spec:
description: "API approves the spec artifact"
depends_on: [wait-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/spec/approve"
body:
comment: "Spec approved by automation"
transition-to-specified:
description: "Transition from draft to specified"
depends_on: [approve-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "specified"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 3: SPECIFIED → PLANNED
# Agent writes design, tasks, qa_plan. API approves each.
# ============================================================
write-design:
description: "Agent writes the design artifact"
depends_on: [transition-to-specified]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/design-feature {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-design:
depends_on: [write-design]
action: wait_build
build_id: "{{ .outputs.write-design.build_id }}"
max_attempts: 720
poll_interval: 5
approve-design:
description: "API approves the design artifact"
depends_on: [wait-design]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/design/approve"
body:
comment: "Design approved by automation"
write-tasks:
description: "Agent breaks down into tasks"
depends_on: [approve-design]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/breakdown-feature {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-tasks:
depends_on: [write-tasks]
action: wait_build
build_id: "{{ .outputs.write-tasks.build_id }}"
max_attempts: 720
poll_interval: 5
approve-tasks:
description: "API approves the tasks artifact"
depends_on: [wait-tasks]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/tasks/approve"
body:
comment: "Tasks approved by automation"
write-qa-plan:
description: "Agent writes QA plan"
depends_on: [approve-tasks]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/create-qa-plan {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-qa-plan:
depends_on: [write-qa-plan]
action: wait_build
build_id: "{{ .outputs.write-qa-plan.build_id }}"
max_attempts: 720
poll_interval: 5
approve-qa-plan:
description: "API approves the QA plan artifact"
depends_on: [wait-qa-plan]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/qa_plan/approve"
body:
comment: "QA plan approved by automation"
transition-to-planned:
description: "Transition from specified to planned"
depends_on: [approve-qa-plan]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "planned"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 4: PLANNED → READY
# Create git branch, then transition
# ============================================================
create-branch:
description: "Create feature branch"
depends_on: [transition-to-planned]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/branch"
outputs:
- branch_name: .data.name
transition-to-ready:
description: "Transition from planned to ready"
depends_on: [create-branch]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "ready"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 5: READY → IMPLEMENTATION
# Agent implements all tasks
# ============================================================
implement-feature:
description: "Agent implements all tasks for the feature"
depends_on: [transition-to-ready]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/implement-feature {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-implement:
depends_on: [implement-feature]
action: wait_build
build_id: "{{ .outputs.implement-feature.build_id }}"
max_attempts: 720
poll_interval: 5
wait-deploy-impl:
description: "Wait for implementation to deploy"
depends_on: [wait-implement]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
transition-to-implementation:
description: "Transition to implementation phase (marks code complete)"
depends_on: [wait-deploy-impl]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "implementation"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 6: IMPLEMENTATION → REVIEW
# Agent writes code review
# ============================================================
write-review:
description: "Agent writes code review"
depends_on: [transition-to-implementation]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/review-feature {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-review:
depends_on: [write-review]
action: wait_build
build_id: "{{ .outputs.write-review.build_id }}"
max_attempts: 720
poll_interval: 5
pass-review:
description: "Mark review as passed"
depends_on: [wait-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/review/pass"
transition-to-review:
description: "Transition to review phase"
depends_on: [pass-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "review"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 7: REVIEW → AUDIT
# Agent writes security/architecture audit
# ============================================================
write-audit:
description: "Agent writes security audit"
depends_on: [transition-to-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/audit-feature {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-audit:
depends_on: [write-audit]
action: wait_build
build_id: "{{ .outputs.write-audit.build_id }}"
max_attempts: 720
poll_interval: 5
pass-audit:
description: "Mark audit as passed"
depends_on: [wait-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/audit/pass"
transition-to-audit:
description: "Transition to audit phase"
depends_on: [pass-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "audit"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 8: AUDIT → QA
# Agent runs QA tests
# ============================================================
run-qa:
description: "Agent runs QA plan"
depends_on: [transition-to-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/run-qa {{ .vars.feature_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git"
outputs:
- build_id: .data.task_id
wait-qa:
depends_on: [run-qa]
action: wait_build
build_id: "{{ .outputs.run-qa.build_id }}"
max_attempts: 720
poll_interval: 5
pass-qa:
description: "Mark QA as passed"
depends_on: [wait-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/artifacts/qa_results/pass"
transition-to-qa:
description: "Transition to QA phase"
depends_on: [pass-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "qa"
outputs:
- new_phase: .data.phase
# ============================================================
# PHASE 9: QA → MERGE
# Transition to merge phase, then merge feature branch to main
# ============================================================
transition-to-merge:
description: "Transition to merge phase"
depends_on: [transition-to-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "merge"
outputs:
- new_phase: .data.phase
merge-feature:
description: "Merge feature branch to main"
depends_on: [transition-to-merge]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/merge"
body:
strategy: "squash"
outputs:
- merge_commit: .data.commit_sha
# ============================================================
# PHASE 10: MERGE → RELEASED
# Archive the feature
# ============================================================
wait-final-deploy:
description: "Wait for merged code to deploy"
depends_on: [merge-feature]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
archive-feature:
description: "Archive the completed feature"
depends_on: [wait-final-deploy]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/archive"
transition-to-released:
description: "Transition to released phase"
depends_on: [archive-feature]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_slug }}/transition"
body:
phase: "released"
outputs:
- final_phase: .data.phase
# ============================================================
# VERIFICATION
# ============================================================
verify-service-running:
description: "Verify the preferences API is running"
depends_on: [transition-to-released]
action: shell
command: |
DOMAIN="{{ .outputs.create-project.domain }}"
HEALTH=$(curl -s "https://$DOMAIN/api/preferences-api/health" | jq -r '.data.status // empty')
if [ "$HEALTH" == "healthy" ]; then
echo "Service healthy"
exit 0
else
echo "Service not healthy: $HEALTH"
exit 1
fi
verify-preferences-api:
description: "Test CRUD operations on preferences"
depends_on: [verify-service-running]
on_error: continue
action: shell
command: |
DOMAIN="{{ .outputs.create-project.domain }}"
BASE_URL="https://$DOMAIN/api/preferences-api"
USER_ID="test-user-123"
# PUT preferences
echo "Setting preferences..."
PUT_RESP=$(curl -s -X PUT "$BASE_URL/preferences/$USER_ID" \
-H "Content-Type: application/json" \
-d '{"theme":"dark","language":"en","notifications":true}')
echo "PUT response: $PUT_RESP"
# GET preferences
echo "Getting preferences..."
GET_RESP=$(curl -s "$BASE_URL/preferences/$USER_ID")
echo "GET response: $GET_RESP"
# Verify theme is dark
THEME=$(echo "$GET_RESP" | jq -r '.theme // .data.theme // empty')
if [ "$THEME" == "dark" ]; then
echo "Preferences API working correctly"
exit 0
else
echo "Expected theme=dark, got: $THEME"
exit 1
fi
verify-lifecycle-complete:
description: "Verify feature reached released phase"
depends_on: [verify-preferences-api]
action: shell
command: |
FINAL_PHASE="{{ .outputs.transition-to-released.final_phase }}"
if [ "$FINAL_PHASE" == "released" ]; then
echo "SUCCESS: Feature completed full lifecycle (draft → released)"
echo "All 10 phases traversed with explicit approvals"
exit 0
else
echo "FAIL: Expected released, got $FINAL_PHASE"
exit 1
fi
teardown:
- action: api
method: DELETE
endpoint: "/project/{{ .outputs.create-project.project_id }}"