mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-26 18:35:05 +00:00
Bumps the actions-minor-and-patch group with 3 updates in the / directory: [actions/setup-node](https://github.com/actions/setup-node), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/setup-node` from 7.0.0 to 7.1.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1) Updates `actions/upload-artifact` from 7.0.1 to 7.0.2 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/043fb46d1a93c77aae656e7c1c64a875d1fc6a0a...cf430e030ddbb5b0abf93d22962f4752f3646cd9) Updates `actions/download-artifact` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c...9000827ccba6bdab643e8b6fd33ac0654aef8333) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 8.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor-and-patch - dependency-name: actions/setup-node dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor-and-patch - dependency-name: actions/upload-artifact dependency-version: 7.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor-and-patch ... Signed-off-by: dependabot[bot] <support@github.com>
468 lines
17 KiB
YAML
468 lines
17 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, 'release/**']
|
|
tags: ['v*']
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
# Prevent duplicate runs
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
# Minimal permissions
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
test:
|
|
name: Test (${{ matrix.os }}, Node ${{ matrix.node }}, ${{ matrix.pm }}, ${{ matrix.scope }})
|
|
runs-on: ${{ matrix.os }}
|
|
# The serial Windows full lane reaches its final installer cases at about
|
|
# 30 minutes; retain a bounded completion window.
|
|
timeout-minutes: 45
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
# Two kinds of lane. `full` runs the whole suite; `pm` runs only the suites
|
|
# that read CLAUDE_CODE_PACKAGE_MANAGER, which is all the package-manager
|
|
# axis ever changed. The old 33-way cross product ran the full suite 33
|
|
# times per push, with Windows lanes at 30 to 40 minutes each.
|
|
matrix:
|
|
include:
|
|
# Full suite: Linux on every supported Node line, current LTS on Windows and macOS.
|
|
- { os: ubuntu-latest, node: '18.x', pm: npm, scope: full }
|
|
- { os: ubuntu-latest, node: '20.x', pm: npm, scope: full }
|
|
- { os: ubuntu-latest, node: '22.x', pm: npm, scope: full }
|
|
- { os: windows-latest, node: '22.x', pm: npm, scope: full }
|
|
- { os: macos-latest, node: '22.x', pm: npm, scope: full }
|
|
# Package-manager lanes on current LTS. Bun has limited Windows support.
|
|
- { os: ubuntu-latest, node: '22.x', pm: pnpm, scope: pm }
|
|
- { os: ubuntu-latest, node: '22.x', pm: yarn, scope: pm }
|
|
- { os: ubuntu-latest, node: '22.x', pm: bun, scope: pm }
|
|
- { os: windows-latest, node: '22.x', pm: pnpm, scope: pm }
|
|
- { os: windows-latest, node: '22.x', pm: yarn, scope: pm }
|
|
- { os: macos-latest, node: '22.x', pm: pnpm, scope: pm }
|
|
- { os: macos-latest, node: '22.x', pm: yarn, scope: pm }
|
|
- { os: macos-latest, node: '22.x', pm: bun, scope: pm }
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js ${{ matrix.node }}
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: ${{ matrix.node }}
|
|
|
|
- name: Install and verify ripgrep (Linux)
|
|
if: runner.os == 'Linux'
|
|
shell: bash
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install --no-install-recommends -y ripgrep
|
|
rg --version
|
|
printf 'ecc-pcre2-probe\n' | rg --pcre2 -- '^ecc-pcre2-probe$'
|
|
|
|
- name: Install and verify ripgrep (macOS)
|
|
if: runner.os == 'macOS'
|
|
shell: bash
|
|
run: |
|
|
if ! command -v rg >/dev/null 2>&1; then brew install ripgrep; fi
|
|
rg --version
|
|
printf 'ecc-pcre2-probe\n' | rg --pcre2 -- '^ecc-pcre2-probe$'
|
|
|
|
- name: Install and verify ripgrep (Windows)
|
|
if: runner.os == 'Windows'
|
|
shell: pwsh
|
|
run: |
|
|
if (-not (Get-Command rg -ErrorAction SilentlyContinue)) {
|
|
choco install ripgrep --yes --no-progress
|
|
if ($LASTEXITCODE -ne 0) { throw 'ripgrep installation failed' }
|
|
}
|
|
rg --version
|
|
if ($LASTEXITCODE -ne 0) { throw 'ripgrep executable is unavailable' }
|
|
# PowerShell writes CRLF to native stdin; retain anchored matching.
|
|
'ecc-pcre2-probe' | rg --pcre2 --crlf -- '^ecc-pcre2-probe$'
|
|
if ($LASTEXITCODE -ne 0) { throw 'ripgrep PCRE2 support is required' }
|
|
|
|
# Package manager setup
|
|
- name: Setup pnpm
|
|
if: matrix.pm == 'pnpm' && matrix.node != '18.x'
|
|
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
with:
|
|
# Keep an explicit pnpm major because this repo's packageManager is Yarn.
|
|
version: 10
|
|
|
|
- name: Setup pnpm (via Corepack)
|
|
if: matrix.pm == 'pnpm' && matrix.node == '18.x'
|
|
shell: bash
|
|
run: |
|
|
corepack enable
|
|
corepack prepare pnpm@9 --activate
|
|
|
|
- name: Setup Yarn (via Corepack)
|
|
if: matrix.pm == 'yarn'
|
|
shell: bash
|
|
run: |
|
|
corepack enable
|
|
corepack prepare yarn@stable --activate
|
|
|
|
- name: Setup Bun
|
|
if: matrix.pm == 'bun'
|
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
|
|
# Install dependencies
|
|
# COREPACK_ENABLE_STRICT=0 allows pnpm to install even though
|
|
# package.json declares "packageManager": "yarn@..."
|
|
- name: Install dependencies
|
|
shell: bash
|
|
env:
|
|
COREPACK_ENABLE_STRICT: '0'
|
|
npm_config_ignore_scripts: 'true'
|
|
YARN_ENABLE_SCRIPTS: 'false'
|
|
run: |
|
|
case "${{ matrix.pm }}" in
|
|
npm) npm ci --ignore-scripts ;;
|
|
# pnpm v10 can fail CI on ignored native build scripts
|
|
# (for example msgpackr-extract) even though this repo is Yarn-native
|
|
# and pnpm is only exercised here as a compatibility lane.
|
|
pnpm) pnpm install --ignore-scripts --config.strict-dep-builds=false --no-frozen-lockfile ;;
|
|
# Yarn Berry (v4+) removed --ignore-engines; engine checking is no longer a core feature
|
|
yarn) yarn install --mode=skip-build ;;
|
|
bun) bun install --ignore-scripts ;;
|
|
*) echo "Unsupported package manager: ${{ matrix.pm }}" && exit 1 ;;
|
|
esac
|
|
|
|
# Run tests. Full lanes run every file through a 4-process pool on Linux
|
|
# and macOS; Windows stays serial because its process spawn and temp-dir
|
|
# cleanup are the flaky part. pm lanes derive their file list from the
|
|
# suites that actually read the package-manager variable, so the lane
|
|
# cannot drift out of date as tests are added.
|
|
- name: Run tests
|
|
shell: bash
|
|
run: |
|
|
if [ "${{ matrix.scope }}" = "pm" ]; then
|
|
ECC_TEST_ONLY=$(grep -rlE --include='*.test.js' 'CLAUDE(_CODE)?_PACKAGE_MANAGER' tests | sed 's#^tests/##' | sort | paste -sd, -)
|
|
export ECC_TEST_ONLY
|
|
echo "pm lane files: $ECC_TEST_ONLY"
|
|
fi
|
|
# Suites that run scripts/build-opencode.js, or rename a checkout path
|
|
# to a .backup-<pid> copy and restore it, mutate the shared checkout;
|
|
# suites that assert a wall-clock budget cannot share cores with the
|
|
# pool. Both groups run last, one at a time.
|
|
ECC_TEST_SERIAL=$(grep -rlE --include='*.test.js' 'build-opencode|\.backup-|dist\.backup|time budget' tests | sed 's#^tests/##' | sort | paste -sd, -)
|
|
export ECC_TEST_SERIAL
|
|
echo "serial after the pool: $ECC_TEST_SERIAL"
|
|
node tests/run-all.js
|
|
env:
|
|
CLAUDE_CODE_PACKAGE_MANAGER: ${{ matrix.pm }}
|
|
ECC_TEST_JOBS: ${{ runner.os == 'Windows' && '1' || '4' }}
|
|
|
|
# Upload test artifacts on failure
|
|
- name: Upload test artifacts
|
|
if: failure()
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: test-results-${{ matrix.os }}-node${{ matrix.node }}-${{ matrix.pm }}-${{ matrix.scope }}
|
|
path: |
|
|
tests/
|
|
!tests/node_modules/
|
|
|
|
pack-installer:
|
|
name: Pack Installer Artifact
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
outputs:
|
|
package_file: ${{ steps.pack.outputs.package_file }}
|
|
package_sha256: ${{ steps.pack.outputs.package_sha256 }}
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Pack exact installer artifact
|
|
id: pack
|
|
run: |
|
|
npm pack --json > npm-pack.json
|
|
node -e "const crypto = require('crypto'); const fs = require('fs'); const data = JSON.parse(fs.readFileSync('npm-pack.json', 'utf8')); const file = data[0]?.filename; if (!/^ecc-universal-[0-9A-Za-z.+-]+\.tgz$/.test(file || '')) throw new Error('Unexpected packed filename'); const archives = fs.readdirSync('.').filter(name => name.endsWith('.tgz')); if (archives.length !== 1 || archives[0] !== file) throw new Error('Expected exactly one packed archive'); const digest = crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex'); fs.appendFileSync(process.env.GITHUB_OUTPUT, 'package_file=' + file + '\npackage_sha256=' + digest + '\n')"
|
|
|
|
- name: Upload exact installer artifact
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: ecc-ci-installer-artifact
|
|
path: ${{ steps.pack.outputs.package_file }}
|
|
if-no-files-found: error
|
|
|
|
packed-install-lifecycle:
|
|
name: Packed Install (${{ matrix.os }})
|
|
needs: pack-installer
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 15
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
|
|
steps:
|
|
- name: Checkout lifecycle test
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
- name: Download exact installer artifact
|
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
with:
|
|
name: ecc-ci-installer-artifact
|
|
path: release-artifacts
|
|
|
|
- name: Verify packed install lifecycle
|
|
env:
|
|
ECC_RELEASE_PACKAGE: release-artifacts/${{ needs.pack-installer.outputs.package_file }}
|
|
ECC_RELEASE_SHA256: ${{ needs.pack-installer.outputs.package_sha256 }}
|
|
run: node tests/ci/packed-artifact-lifecycle.js
|
|
|
|
validate:
|
|
name: Validate Components
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
- name: Install validation dependencies
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Validate agents
|
|
run: node scripts/ci/validate-agents.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate hooks
|
|
run: node scripts/ci/validate-hooks.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate commands
|
|
run: node scripts/ci/validate-commands.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate skills
|
|
run: node scripts/ci/validate-skills.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate skill host compatibility
|
|
run: node scripts/ci/validate-skill-host-compat.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate install manifests
|
|
run: node scripts/ci/validate-install-manifests.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate workflow security
|
|
run: node scripts/ci/validate-workflow-security.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate rules
|
|
run: node scripts/ci/validate-rules.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate catalog counts
|
|
run: node scripts/ci/catalog.js --text
|
|
continue-on-error: false
|
|
|
|
- name: Validate command registry
|
|
run: npm run command-registry:check
|
|
continue-on-error: false
|
|
|
|
- name: Check unicode safety
|
|
run: node scripts/ci/check-unicode-safety.js
|
|
continue-on-error: false
|
|
|
|
- name: Validate no personal paths
|
|
run: node scripts/ci/validate-no-personal-paths.js
|
|
continue-on-error: false
|
|
|
|
pi-core:
|
|
name: Pi Core Profile
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
# Rebuild runs frontmatter validation and the pi/core safety checks
|
|
# (no callable endpoints, no runtime downloads, no secrets, no absolute
|
|
# home paths, no symlinks, no duplicate skill names); the diff check
|
|
# proves the committed profile is up to date.
|
|
- name: Rebuild pi/core and verify it is up to date
|
|
run: |
|
|
node scripts/build-pi-core.js
|
|
git diff --exit-code pi/core
|
|
|
|
- name: Install Pi coding agent CLI
|
|
run: npm install --global --ignore-scripts --no-audit --no-fund @mariozechner/pi-coding-agent@0.73.1
|
|
|
|
# --extension only loads a package's pi.extensions entries; pi/core is a
|
|
# skills+prompts-only package, so the equivalent --skill/--prompt-template
|
|
# resource flags are used. The load-test script additionally asserts via
|
|
# RPC that every curated command actually loaded.
|
|
- name: Offline load test with the Pi CLI
|
|
run: |
|
|
PI_OFFLINE=1 pi --offline --mode rpc --no-session --no-context-files --no-extensions \
|
|
--skill pi/core/skills --prompt-template pi/core/commands </dev/null >/dev/null
|
|
node scripts/ci/pi-core-load-test.js
|
|
|
|
python-tests:
|
|
name: Python Lint, Type Check & Test
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Install Python dependencies
|
|
run: python -m pip install --upgrade pip && python -m pip install -e '.[dev]'
|
|
|
|
- name: Run ruff (lint)
|
|
run: python -m ruff check src tests
|
|
|
|
- name: Run mypy (type check)
|
|
run: python -m mypy src
|
|
|
|
- name: Run Python tests
|
|
run: python -m pytest tests/test_*.py -m "not integration"
|
|
|
|
- name: Test minimum supported OpenAI SDK
|
|
run: |
|
|
python -m pip install 'openai==2.34.0'
|
|
python -m pytest tests/test_provider_tools.py tests/test_atlas_provider.py tests/test_astraflow_provider.py tests/test_resolver.py
|
|
|
|
security:
|
|
name: Security Scan
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
- name: Install audit dependencies
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Run npm audit
|
|
run: |
|
|
npm audit signatures
|
|
# Runtime/package advisories are release blockers. Development-only
|
|
# lint tooling remains covered by signature and IOC verification.
|
|
npm audit --omit=dev --audit-level=high
|
|
|
|
- name: Run supply-chain IOC scan
|
|
run: npm run security:ioc-scan
|
|
|
|
coverage:
|
|
name: Coverage
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Install and verify ripgrep
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install --no-install-recommends -y ripgrep
|
|
rg --version
|
|
printf 'ecc-pcre2-probe\n' | rg --pcre2 -- '^ecc-pcre2-probe$'
|
|
|
|
- name: Run coverage
|
|
run: npm run coverage
|
|
|
|
- name: Upload coverage report
|
|
if: always()
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: coverage-ubuntu-node20-npm
|
|
path: coverage/
|
|
|
|
lint:
|
|
name: Lint
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: '20.x'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Run lint
|
|
run: npm run lint
|