Skip to main content

Installation Options

For CI/CD pipelines, use edgit directly via npx:
# Direct edgit (recommended for CI/CD - faster, fewer dependencies)
npx @ensemble-edge/edgit <command>
For CI/CD pipelines, we recommend direct edgit (npx @ensemble-edge/edgit) for faster execution and smaller download size.

The Pattern

# .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: Auto-version changed components
        run: |
          # Discover components in changed files since last commit
          CHANGED=$(npx @ensemble-edge/edgit discover scan --changed --output simple | awk '{print $2}' | sort -u)

          # Auto-increment versions for each changed component
          for component in $CHANGED; do
            npx @ensemble-edge/edgit tag bump $component patch
            echo "✓ Bumped $component"
          done

      - name: Push tags
        run: npx @ensemble-edge/edgit push --tags

GitHub Actions

Auto-Version on Merge

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: 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=$(npx @ensemble-edge/edgit discover detect $file --name-only 2>/dev/null || true)
            if [ ! -z "$COMPONENT" ]; then
              npx @ensemble-edge/edgit tag bump $COMPONENT patch
              echo "✓ Bumped $COMPONENT"
            fi
          done

      - name: Push Tags
        run: npx @ensemble-edge/edgit push --tags

Deploy to Staging on PR Merge

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: Deploy to Staging
        run: |
          # Get all components
          COMPONENTS=$(npx @ensemble-edge/edgit components list --format json | jq -r '.[] | .name')

          # Deploy latest version of each to staging
          for component in $COMPONENTS; do
            LATEST=$(npx @ensemble-edge/edgit tag list $component --format json | jq -r '.versions[-1]')
            npx @ensemble-edge/edgit tag set $component staging $LATEST
          done

      - name: Push Deployment Tags
        run: npx @ensemble-edge/edgit push --tags --force

Promote Staging to Production

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: Promote to Production
        run: |
          if [ "${{ github.event.inputs.components }}" == "all" ]; then
            COMPONENTS=$(npx @ensemble-edge/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=$(npx @ensemble-edge/edgit tag show $component@staging --format json | jq -r '.sha')

            # Deploy to production
            npx @ensemble-edge/edgit tag set $component production $STAGING_VERSION

            echo "✓ Promoted $component to production"
          done

      - name: Push Tags
        run: npx @ensemble-edge/edgit push --tags --force

GitLab CI

# .gitlab-ci.yml
stages:
  - version
  - deploy

variables:
  GIT_DEPTH: 0  # Full history for tags

version:components:
  stage: version
  image: node:18
  only:
    - main
  script:
    - |
      # Configure git
      git config user.name "GitLab CI"
      git config user.email "[email protected]"

      # Version changed components
      CHANGED=$(git diff --name-only HEAD~1 HEAD)
      for file in $CHANGED; do
        COMPONENT=$(npx @ensemble-edge/edgit discover detect $file --name-only 2>/dev/null || true)
        if [ ! -z "$COMPONENT" ]; then
          npx @ensemble-edge/edgit tag bump $COMPONENT patch
        fi
      done

      # Push tags
      npx @ensemble-edge/edgit push --tags

deploy:staging:
  stage: deploy
  image: node:18
  only:
    - main
  script:
    - |
      # Deploy to staging
      COMPONENTS=$(npx @ensemble-edge/edgit components list --format json | jq -r '.[] | .name')
      for component in $COMPONENTS; do
        LATEST=$(npx @ensemble-edge/edgit tag list $component --format json | jq -r '.versions[-1]')
        npx @ensemble-edge/edgit tag set $component staging $LATEST
      done
      npx @ensemble-edge/edgit push --tags --force

CircleCI

# .circleci/config.yml
version: 2.1

jobs:
  version:
    docker:
      - image: cimg/node:18.0
    steps:
      - checkout
      - run:
          name: Version Components
          command: |
            git config user.name "CircleCI"
            git config user.email "[email protected]"

            CHANGED=$(git diff --name-only HEAD~1 HEAD)
            for file in $CHANGED; do
              COMPONENT=$(npx @ensemble-edge/edgit discover detect $file --name-only 2>/dev/null || true)
              if [ ! -z "$COMPONENT" ]; then
                npx @ensemble-edge/edgit tag bump $COMPONENT patch
              fi
            done
      - run:
          name: Push Tags
          command: npx @ensemble-edge/edgit push --tags

workflows:
  version-and-deploy:
    jobs:
      - version:
          filters:
            branches:
              only: main

Semantic Versioning Automation

Auto-increment based on commit messages:
#!/bin/bash
# scripts/auto-version.sh

COMPONENT=$1

# Parse commit messages since last tag
COMMITS=$(git log --format=%s $(git describe --tags --abbrev=0 2>/dev/null || echo HEAD~10)..HEAD -- components/$COMPONENT/)

if echo "$COMMITS" | grep -q "BREAKING CHANGE\|breaking:"; then
  # Major version bump
  npx @ensemble-edge/edgit tag bump $COMPONENT major
elif echo "$COMMITS" | grep -q "feat:"; then
  # Minor version bump
  npx @ensemble-edge/edgit tag bump $COMPONENT minor
else
  # Patch version bump
  npx @ensemble-edge/edgit tag bump $COMPONENT patch
fi
Use in CI:
- name: Auto Version
  run: |
    # Discover changed components using Edgit's built-in --changed flag
    CHANGED=$(npx @ensemble-edge/edgit discover scan --changed --output simple | awk '{print $2}' | sort -u)
    for component in $CHANGED; do
      ./scripts/auto-version.sh $component
    done

Deploy Version Data to Cloudflare KV

Make versions available at the edge:
name: Deploy to Cloudflare

on:
  push:
    tags:
      - 'components/**'
      - 'logic/**'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4

      - name: Export Version Data
        run: |
          # Export all component versions to JSON
          npx @ensemble-edge/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
Now Conductor can read versions from KV at runtime:
// 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

on:
  push:
    branches: [main]  # Only version after merge

2. Use Conventional Commits

feat: add new extraction logic      # Minor bump
fix: correct validation bug         # Patch bump
feat!: change API interface         # Major bump

3. Test Before Promoting

jobs:
  test:
    # Run tests

  version:
    needs: [test]  # Only version if tests pass

4. Protect Production Deploys

deploy:production:
  environment:
    name: production
    protection_rules:
      required_approvals: 2  # Require approvals

Next Steps