CI/CD Integration
Automate versioning and deployment. No manual tagging, no human error.The Pattern
Copy
# .github/workflows/version.yml
on:
push:
branches: [main]
jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for tags
- uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install Edgit
run: npm install -g @ensemble-edge/edgit
- name: Auto-version changed components
run: |
# Detect changed components
CHANGED=$(edgit discover scan --changed)
# Auto-increment versions
for component in $CHANGED; do
LATEST=$(edgit tag list $component | tail -1)
NEW_VERSION=$(edgit version bump $LATEST patch)
edgit tag create $component $NEW_VERSION
done
- name: Push tags
run: git push --tags
GitHub Actions
Auto-Version on Merge
Copy
name: Auto Version Components
on:
push:
branches: [main]
jobs:
version:
runs-on: ubuntu-latest
permissions:
contents: write # Need write for tags
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install Edgit
run: npm install -g @ensemble-edge/edgit
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Version Components
run: |
# Get changed files
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD)
# Version each changed component
for file in $CHANGED_FILES; do
COMPONENT=$(edgit discover detect $file --name-only)
if [ ! -z "$COMPONENT" ]; then
LATEST=$(edgit tag list $COMPONENT | tail -1 || echo "v0.0.0")
NEW=$(edgit version bump $LATEST patch)
edgit tag create $COMPONENT $NEW
echo " Versioned $COMPONENT: $LATEST $NEW"
fi
done
- name: Push Tags
run: git push --tags
Deploy to Staging on PR Merge
Copy
name: Deploy to Staging
on:
pull_request:
types: [closed]
branches: [main]
jobs:
deploy:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
- name: Install Edgit
run: npm install -g @ensemble-edge/edgit
- name: Deploy to Staging
run: |
# Get all components
COMPONENTS=$(edgit components list --format json | jq -r '.[] | .name')
# Deploy latest version of each to staging
for component in $COMPONENTS; do
LATEST=$(edgit tag list $component | tail -1)
edgit deploy set $component $LATEST --to staging
done
- name: Push Deployment Tags
run: git push --tags
Promote Staging to Production
Copy
name: Promote to Production
on:
workflow_dispatch: # Manual trigger
inputs:
components:
description: 'Components to promote (comma-separated, or "all")'
required: true
default: 'all'
jobs:
promote:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
- name: Install Edgit
run: npm install -g @ensemble-edge/edgit
- name: Promote to Production
run: |
if [ "${{ github.event.inputs.components }}" == "all" ]; then
COMPONENTS=$(edgit components list --format json | jq -r '.[] | .name')
else
COMPONENTS=$(echo "${{ github.event.inputs.components }}" | tr ',' ' ')
fi
for component in $COMPONENTS; do
# Get staging version
STAGING_VERSION=$(edgit deploy get $component --from staging)
# Deploy to production
edgit deploy set $component $STAGING_VERSION --to prod
echo " Promoted $component: $STAGING_VERSION prod"
done
- name: Push Tags
run: git push --tags
GitLab CI
Copy
# .gitlab-ci.yml
stages:
- version
- deploy
variables:
GIT_DEPTH: 0 # Full history for tags
version:components:
stage: version
image: node:18
only:
- main
script:
- npm install -g @ensemble-edge/edgit
- |
# Configure git
git config user.name "GitLab CI"
git config user.email "ci@gitlab.com"
# Version changed components
CHANGED=$(git diff --name-only HEAD~1 HEAD)
for file in $CHANGED; do
COMPONENT=$(edgit discover detect $file --name-only)
if [ ! -z "$COMPONENT" ]; then
LATEST=$(edgit tag list $COMPONENT | tail -1 || echo "v0.0.0")
NEW=$(edgit version bump $LATEST patch)
edgit tag create $COMPONENT $NEW
fi
done
# Push tags
git push https://oauth2:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git --tags
deploy:staging:
stage: deploy
image: node:18
only:
- main
script:
- npm install -g @ensemble-edge/edgit
- |
# Deploy to staging
COMPONENTS=$(edgit components list --format json | jq -r '.[] | .name')
for component in $COMPONENTS; do
LATEST=$(edgit tag list $component | tail -1)
edgit deploy set $component $LATEST --to staging
done
git push https://oauth2:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git --tags
CircleCI
Copy
# .circleci/config.yml
version: 2.1
jobs:
version:
docker:
- image: cimg/node:18.0
steps:
- checkout
- run:
name: Install Edgit
command: npm install -g @ensemble-edge/edgit
- run:
name: Version Components
command: |
git config user.name "CircleCI"
git config user.email "ci@circleci.com"
CHANGED=$(git diff --name-only HEAD~1 HEAD)
for file in $CHANGED; do
COMPONENT=$(edgit discover detect $file --name-only)
if [ ! -z "$COMPONENT" ]; then
LATEST=$(edgit tag list $COMPONENT | tail -1 || echo "v0.0.0")
NEW=$(edgit version bump $LATEST patch)
edgit tag create $COMPONENT $NEW
fi
done
- run:
name: Push Tags
command: git push --tags
workflows:
version-and-deploy:
jobs:
- version:
filters:
branches:
only: main
Semantic Versioning Automation
Auto-increment based on commit messages:Copy
#!/bin/bash
# scripts/auto-version.sh
COMPONENT=$1
LATEST=$(edgit tag list $COMPONENT | tail -1 || echo "v0.0.0")
# Parse commit messages since last tag
COMMITS=$(git log --format=%s $(git describe --tags --abbrev=0)..HEAD -- components/$COMPONENT/)
if echo "$COMMITS" | grep -q "BREAKING CHANGE\|breaking:"; then
# Major version bump
NEW=$(edgit version bump $LATEST major)
elif echo "$COMMITS" | grep -q "feat:"; then
# Minor version bump
NEW=$(edgit version bump $LATEST minor)
else
# Patch version bump
NEW=$(edgit version bump $LATEST patch)
fi
edgit tag create $COMPONENT $NEW
echo "Versioned $COMPONENT: $LATEST $NEW"
Copy
- name: Auto Version
run: |
CHANGED=$(edgit discover scan --changed)
for component in $CHANGED; do
./scripts/auto-version.sh $component
done
Deploy Version Data to Cloudflare KV
Make versions available at the edge:Copy
name: Deploy to Cloudflare
on:
push:
tags:
- 'components/**'
- 'agents/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
- name: Install Edgit
run: npm install -g @ensemble-edge/edgit
- name: Export Version Data
run: |
# Export all component versions to JSON
edgit components list --format json > versions.json
- name: Deploy to Cloudflare KV
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
KV_NAMESPACE_ID: ${{ secrets.KV_NAMESPACE_ID }}
run: |
# Upload versions to KV
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/storage/kv/namespaces/$KV_NAMESPACE_ID/values/component-versions" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
--data @versions.json
Copy
// Conductor reads from KV
const versions = await env.VERSIONS.get('component-versions', 'json');
const promptVersion = versions['extraction-prompt'].prod; // v1.0.0
Best Practices
1. Version on Main Branch Only
Copy
on:
push:
branches: [main] # Only version after merge
2. Use Conventional Commits
Copy
feat: add new extraction logic # Minor bump
fix: correct validation bug # Patch bump
feat!: change API interface # Major bump
3. Test Before Promoting
Copy
jobs:
test:
# Run tests
version:
needs: [test] # Only version if tests pass
4. Protect Production Deploys
Copy
deploy:production:
environment:
name: production
protection_rules:
required_approvals: 2 # Require approvals

