Files
ECC/.github/workflows/ci.yml
T
1db5c8ab4a fix(install): harden ECC installer lifecycle
Make Antigravity 2.0 installs native and safely migrate legacy state. Ensure doctor, repair, status projection, repeat installs, legacy Codex sync, and uninstall converge without losing user files. Exclude Python bytecode and harden repo-scan bootstrap guidance.

Gate publishing and pull-request merges on one exact packed artifact completing install, repeat, drift, repair, status, and uninstall across Linux, macOS, and Windows.

Co-authored-by: lorencifernando-coder <lorenci.fernando@gmail.com>

Co-authored-by: Suliman Abdulrazzaq <suliman9000a@gmail.com>

Co-authored-by: Wu Shuwen <mikewushuwen@outlook.com>
2026-08-13 16:42:51 -04:00

349 lines
11 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 }})
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: ['18.x', '20.x', '22.x']
pm: [npm, pnpm, yarn, bun]
exclude:
# Bun has limited Windows support
- os: windows-latest
pm: bun
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js ${{ matrix.node }}
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}
# Package manager setup
- name: Setup pnpm
if: matrix.pm == 'pnpm' && matrix.node != '18.x'
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
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
- name: Run tests
run: node tests/run-all.js
env:
CLAUDE_CODE_PACKAGE_MANAGER: ${{ matrix.pm }}
# Upload test artifacts on failure
- name: Upload test artifacts
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: test-results-${{ matrix.os }}-node${{ matrix.node }}-${{ matrix.pm }}
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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '20.x'
- name: Download exact installer artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.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 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
python-tests:
name: Python Lint, Type Check & Test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.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"
security:
name: Security Scan
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.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: 10
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '20.x'
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run coverage
run: npm run coverage
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-ubuntu-node20-npm
path: coverage/
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '20.x'
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run lint
run: npm run lint