CI Playbook

View Source

The SkillEx CLI is designed to drop into any CI system. This guide outlines the common patterns for running the sync, publishing the archive, and surfacing issues early.


Core Steps

Every pipeline follows the same high-level structure:

  1. Checkout repositories – SkillEx plus each source repo listed in manifest.json.
  2. Install Elixir dependenciesmix deps.get.
  3. Run testsmix test ensures aggregator logic still passes.
  4. Execute the sync script – ideally with deterministic options (--clock, --version).
  5. Inspect JSON output – fail the build if status != "ok".
  6. Publish artifacts – upload dist/skills-pack-<version>.zip, and optionally manifest.json.

The CLI output is machine-friendly JSON, so you can parse it in Bash, Elixir, or any scripting language available in your CI environment.


GitHub Actions Example

name: Skill Pack

on:
  workflow_dispatch:
  push:
    branches: [main]

jobs:
  build-pack:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          path: skill_ex

      # Checkout source repos (paths must match manifest.json)
      - uses: actions/checkout@v4
        with:
          repository: my-org/supertester
          path: supertester

      - name: Install Elixir
        uses: erlef/setup-beam@v1
        with:
          elixir-version: '1.15'
          otp-version: '26'

      - name: Install deps
        working-directory: skill_ex
        run: mix deps.get

      - name: Test aggregator
        working-directory: skill_ex
        run: mix test

      - name: Sync skills
        working-directory: skill_ex
        run: >
          elixir scripts/sync_skills.exs
          --manifest manifest.json
          --target skills
          --package-script ../supertester/scripts/package_skill.py
          --clock ${{ github.event.head_commit.timestamp }}
          --version ${{ github.run_id }}
          | tee sync_output.json

      - name: Fail if sync reported errors
        working-directory: skill_ex
        run: |
          STATUS=$(jq -r '.status' sync_output.json)
          if [ "$STATUS" != "ok" ]; then
            cat sync_output.json
            exit 1
          fi

      - name: Upload skill pack
        uses: actions/upload-artifact@v4
        with:
          name: skills-pack
          path: |
            skill_ex/dist/skills-pack-${{ github.run_id }}.zip
            skill_ex/manifest.json

Key Notes

  • --package-script can point to the packaging script in any checked-out repo.
  • --version uses the GitHub run ID for uniqueness. Substitute build numbers or tags as needed.
  • jq extracts values from the JSON output; any parser works if jq is unavailable.

Buildkite / Other CI Systems

The same recipe applies:

mix deps.get
mix test

OUTPUT=$(elixir scripts/sync_skills.exs \
  --manifest manifest.json \
  --target skills \
  --package-script ../scripts/package_skill.py \
  --clock "$CI_TIMESTAMP" \
  --version "$CI_BUILD_NUMBER")

echo "$OUTPUT"

STATUS=$(echo "$OUTPUT" | jq -r '.status')
if [ "$STATUS" != "ok" ]; then
  exit 1
fi

buildkite-agent artifact upload "dist/skills-pack-$CI_BUILD_NUMBER.zip"
buildkite-agent artifact upload "manifest.json"

Replace buildkite-agent with the equivalent command in your CI.


Tips & Best Practices

  • Cache Dependencies: Use CI caching for deps/ and _build/ to keep runs fast.
  • Freeze Clocks in Tests: When validating pipeline behaviour locally, pass --clock to produce deterministic timestamps.
  • Surface Summaries: Pipe the JSON into your chat/alerting system so teams know what changed (e.g., newly added skills).
  • Parallel Builds: If repos are large, checkout and validate skills in parallel stages before the final aggregation step.
  • Artifact Retention: Retain both the zip and manifest so you can diff checksums across builds.
  • Security: If the packaging script needs API keys, inject them via CI secrets and pass them through the CLI using environment variables.

Keeping the CI pipeline transparent ensures SkillEx does not become a mysterious black box. Adapt the snippets above to your build system, and update this playbook when you uncover better patterns.