# formulas/release.toml — Release formula
#
# Defines the release workflow: tag Forgejo main, push to mirrors, build
# and tag the agents Docker image, and restart agents.
#
# Triggered by vault PR approval (human creates vault PR, approves it, then
# runner executes via `disinto run <id>`).
#
# Example vault item:
#   id = "release-v1.2.0"
#   formula = "release"
#   context = "Tag v1.2.0 — includes vault redesign, .profile system, architect agent"
#   secrets = []
#
# Steps: preflight → tag-main → push-mirrors → build-image → tag-image → restart-agents → commit-result

name        = "release"
description = "Tag Forgejo main, push to mirrors, build and tag agents image, restart agents"
version     = 1

[context]
files = ["docker-compose.yml"]

# ─────────────────────────────────────────────────────────────────────────────────
# Step 1: preflight
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "preflight"
title = "Validate release prerequisites"
description = """
Validate release prerequisites before proceeding.

1. Check that RELEASE_VERSION is set:
   - Must be in format: v1.2.3 (semver with 'v' prefix)
   - Validate with regex: ^v[0-9]+\\.[0-9]+\\.[0-9]+$
   - If not set, exit with error

2. Check that FORGE_TOKEN and FORGE_URL are set:
   - Required for Forgejo API calls

3. Check that DOCKER_HOST is accessible:
   - Test with: docker info
   - Required for image build

4. Check current branch is main:
   - git rev-parse --abbrev-ref HEAD
   - Must be 'main' or 'master'

5. Pull latest code:
   - git fetch origin "$PRIMARY_BRANCH"
   - git reset --hard origin/"$PRIMARY_BRANCH"
   - Ensure working directory is clean

6. Check if tag already exists locally:
   - git tag -l "$RELEASE_VERSION"
   - If exists, exit with error

7. Check if tag already exists on Forgejo:
   - curl -sf -H "Authorization: token $FORGE_TOKEN" \
   -   "$FORGE_URL/api/v1/repos/$FORGE_REPO/git/tags/$RELEASE_VERSION"
   - If exists, exit with error

8. Export RELEASE_VERSION for subsequent steps:
   - export RELEASE_VERSION (already set from vault action)
"""

# ─────────────────────────────────────────────────────────────────────────────────
# Step 2: tag-main
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "tag-main"
title = "Create tag on Forgejo main via API"
description = """
Create the release tag on Forgejo main via the Forgejo API.

1. Get current HEAD SHA of main:
   - curl -sf -H "Authorization: token $FORGE_TOKEN" \
   -   "$FORGE_URL/api/v1/repos/$FORGE_REPO/branches/$PRIMARY_BRANCH"
   - Parse sha field from response

2. Create tag via Forgejo API:
   - curl -sf -X POST \
   -   -H "Authorization: token $FORGE_TOKEN" \
   -   -H "Content-Type: application/json" \
   -   "$FORGE_URL/api/v1/repos/$FORGE_REPO/tags" \
   -   -d "{\"tag\":\"$RELEASE_VERSION\",\"target\":\"$HEAD_SHA\",\"message\":\"Release $RELEASE_VERSION\"}"
   - Parse response for success

3. Log the tag creation:
   - echo "Created tag $RELEASE_VERSION on Forgejo (SHA: $HEAD_SHA)"

4. Store HEAD SHA for later verification:
   - echo "$HEAD_SHA" > /tmp/release-head-sha
"""

# ─────────────────────────────────────────────────────────────────────────────────
# Step 3: push-mirrors
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "push-mirrors"
title = "Push tag to mirrors (Codeberg, GitHub)"
description = """
Push the newly created tag to all configured mirrors.

1. Add mirror remotes if not already present:
   - Codeberg: git remote add codeberg git@codeberg.org:${FORGE_REPO_OWNER}/${PROJECT_NAME}.git
   - GitHub: git remote add github git@github.com:disinto/${PROJECT_NAME}.git
   - Check with: git remote -v

2. Push tag to Codeberg:
   - git push codeberg "$RELEASE_VERSION" --tags
   - Or push all tags: git push codeberg --tags

3. Push tag to GitHub:
   - git push github "$RELEASE_VERSION" --tags
   - Or push all tags: git push github --tags

4. Verify tags exist on mirrors:
   - curl -sf -H "Authorization: token $GITHUB_TOKEN" \
   -   "https://api.github.com/repos/disinto/${PROJECT_NAME}/tags/$RELEASE_VERSION"
   - curl -sf -H "Authorization: token $FORGE_TOKEN" \
   -   "$FORGE_URL/api/v1/repos/$FORGE_REPO/git/tags/$RELEASE_VERSION"

5. Log success:
   - echo "Tag $RELEASE_VERSION pushed to mirrors"
"""

# ─────────────────────────────────────────────────────────────────────────────────
# Step 4: build-image
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "build-image"
title = "Build agents Docker image"
description = """
Build the new agents Docker image with the tagged code.

1. Build image without cache to ensure fresh build:
   - docker compose build --no-cache agents

2. Verify image was created:
   - docker images | grep disinto-agents
   - Check image exists and has recent timestamp

3. Store image ID for later:
   - docker images disinto-agents --format "{{.ID}}" > /tmp/release-image-id

4. Log build completion:
   - echo "Built disinto-agents image"
"""

# ─────────────────────────────────────────────────────────────────────────────────
# Step 5: tag-image
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "tag-image"
title = "Tag Docker image with version"
description = """
Tag the newly built agents image with the release version.

1. Get the untagged image ID:
   - docker images disinto-agents --format "{{.ID}}" --no-trunc | head -1

2. Tag the image:
   - docker tag disinto-agents disinto-agents:$RELEASE_VERSION

3. Verify tag:
   - docker images disinto-agents

4. Log tag:
   - echo "Tagged disinto-agents:$RELEASE_VERSION"
"""

# ─────────────────────────────────────────────────────────────────────────────────
# Step 6: restart-agents
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "restart-agents"
title = "Restart agent containers with new image"
description = """
Restart agent containers to use the new image.

1. Pull the new image (in case it was pushed somewhere):
   - docker compose pull agents

2. Stop and remove existing agent containers:
   - docker compose down agents agents-llama 2>/dev/null || true

3. Start agents with new image:
   - docker compose up -d agents agents-llama

4. Wait for containers to be healthy:
   - for i in {1..30}; do
   -   if docker inspect --format='{{.State.Health.Status}}' agents | grep -q healthy; then
   -     echo "Agents container healthy"; break
   -   fi
   -   sleep 5
   - done

5. Verify containers are running:
   - docker compose ps agents agents-llama

6. Log restart:
   - echo "Restarted agents containers"
"""

# ─────────────────────────────────────────────────────────────────────────────────
# Step 7: commit-result
# ─────────────────────────────────────────────────────────────────────────────────

[[steps]]
id    = "commit-result"
title = "Write release result"
description = """
Write the release result to a file for tracking.

1. Get the image ID:
   - IMAGE_ID=$(cat /tmp/release-image-id)

2. Create result file:
   - cat > /tmp/release-result.json <<EOF
   - {
   -   "version": "$RELEASE_VERSION",
   -   "image_id": "$IMAGE_ID",
   -   "forgejo_tag_url": "$FORGE_URL/$FORGE_REPO/src/$RELEASE_VERSION",
   -   "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
   -   "status": "success"
   - }
   - EOF

3. Copy result to data directory:
   - mkdir -p "$PROJECT_REPO_ROOT/release"
   - cp /tmp/release-result.json "$PROJECT_REPO_ROOT/release/$RELEASE_VERSION.json"

4. Log result:
   - cat /tmp/release-result.json

5. Clean up temp files:
   - rm -f /tmp/release-head-sha /tmp/release-image-id /tmp/release-result.json
"""
