disinto/formulas/release.toml
Agent a7ad6eb32a
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
fix: feat: versioned releases — vault-gated tag, image build, and deploy (#112)
2026-04-01 14:03:49 +00:00

245 lines
9.8 KiB
TOML

# 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/johba/disinto/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/johba/disinto/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/johba/disinto/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:johba/disinto.git
- GitHub: git remote add github git@github.com:disinto/disinto.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/disinto/tags/$RELEASE_VERSION"
- curl -sf -H "Authorization: token $FORGE_TOKEN" \
- "$FORGE_URL/api/v1/repos/johba/disinto/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/johba/disinto/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
"""