Files
magnus919_agent-skills/.github/workflows/validate.yml
T
Magnus Hedemarkandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> 0dc4b6c5dc fix(ci): pin epub test deps and surface epublib skip
Pin the epub skill's test-only dependencies (EbookLib, beautifulsoup4) with
exact versions in requirements-epub-test.txt and install from that file in
CI, instead of unpinned package names. The file is test-only and notes that
EbookLib is AGPL; requirements-dev.txt is untouched.

Also surface the epublib skip in epub/scripts/test_epub_skill.sh: when
epublib is not importable (it requires Python 3.13+), epub-edit and
epub-convert now print an explicit SKIPPED line and count as SKIP in the
summary instead of silently passing.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-08-14 23:42:25 -04:00

134 lines
5.9 KiB
YAML

name: Validate skills
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
- name: Install Python validator dependencies
run: python3 -m pip install -r requirements-dev.txt
- name: Lint Python (ruff)
run: python3 -m ruff check scripts/ eval_runner/
- name: Check Python formatting (ruff)
run: python3 -m ruff format --check scripts/ eval_runner/
- name: Type check (mypy)
run: python3 -m mypy scripts/ eval_runner/
- name: Complexity check (radon)
run: python3 -m radon cc scripts/ eval_runner/ --min B --total-average
- name: Unused dependency check (deptry)
run: python3 -m deptry .
- name: Check for large files
run: |
large_files=$(git ls-files -- ':(glob)**' | while read -r f; do
if [ -f "$f" ]; then
size=$(stat -c%s "$f" 2>/dev/null || echo 0)
if [ "$size" -gt 5242880 ]; then
echo "$f ($((size / 1024)) KB)"
fi
fi
done)
if [ -n "$large_files" ]; then
echo "Files exceeding 5 MB:"
echo "$large_files"
exit 1
fi
echo "No large files detected."
- name: Scan technical debt markers
run: python3 scripts/scan-tech-debt.py
- name: Duplicate code detection (jscpd)
run: npx jscpd --config .jscpd.json .
- name: Security review (bandit)
run: python3 -m bandit -r scripts/ -f txt --severity-level high
- name: Check dependency release age (supply chain)
run: python3 scripts/check-dependency-age.py
- name: Validate skill format and links
run: ruby scripts/validate-skills.rb
- name: Run reference-scan validator tests
run: ruby scripts/test-validate-skills.rb
- name: Test eval manifest validation
run: python3 scripts/test-eval-validation.py
- name: Validate eval manifests
run: python3 scripts/validate-evals.py
- name: Test life-coach capability validation
run: python3 -m unittest discover -s life-coach/tests -p 'test_*.py'
- name: Run skill-local script tests
run: |
set -euo pipefail
while IFS= read -r dir; do
echo "=== $dir ==="
python3 -m pytest "$dir" -o "addopts=-ra --strict-markers --tb=short" -o "python_files=test_*.py" -v --durations=10
done < <(git ls-files | grep -E '/scripts/test_[^/]*\.py$' | sed 's#/[^/]*$##' | sort -u)
- name: Install epub skill test deps (EbookLib is AGPL; test-only)
run: python3 -m pip install -r requirements-epub-test.txt
- name: Run skill-local shell test scripts
run: python3 scripts/check-skill-tests.py --run
- name: Check skill test coverage
run: python3 scripts/check-skill-tests.py --check
- name: Run core test suite with coverage
run: python3 -m pytest scripts/test-eval-validation.py scripts/test-eval-coverage.py scripts/test_check_skill_tests.py eval_runner/tests/ -v --durations=10 --cov=scripts --cov=eval_runner --cov-fail-under=60 --cov-report=term-missing
- name: Run tests in parallel (isolation check)
run: python3 -m pytest scripts/test-eval-validation.py scripts/test-eval-coverage.py scripts/test_check_skill_tests.py eval_runner/tests/ -n auto -v --durations=10
- name: Validate AGENTS.md consistency
run: python3 scripts/validate-agents-md.py
- name: Run integration tests
run: python3 -m pytest tests/integration/ -v --durations=10 -o "addopts=-ra --strict-markers --tb=short --durations=10"
- name: Test changed-skill quality validation
run: ruby scripts/test-validate-skill-quality.rb
- name: Validate changed skill quality
env:
SKILL_QUALITY_BASE: ${{ github.event.pull_request.base.sha || github.event.before }}
run: ruby scripts/validate-skill-quality.rb --base "$SKILL_QUALITY_BASE"
- name: Check tracked repository artifacts
run: python3 scripts/check-artifacts.py
- name: Validate Claude Code marketplace
run: ruby scripts/gen-claude-marketplace.rb
- name: Validate Codex plugin packaging
run: ruby scripts/gen-codex-plugin.rb
- name: Test eval coverage ratchet
run: python3 scripts/test-eval-coverage.py
- name: Report eval coverage
run: python3 scripts/eval-coverage.py
- name: Enforce eval coverage ratchet
env:
EVAL_RATCHET_BASE: ${{ github.event.pull_request.base.sha || github.event.before }}
run: python3 scripts/eval-coverage.py --modified-from "$EVAL_RATCHET_BASE"
- name: Test llms.txt generator
run: ruby scripts/test-gen-llms-txt.rb
- name: Validate llms.txt catalog
run: ruby scripts/gen-llms-txt.rb
- name: Validate bundle manifests
run: ruby scripts/validate-bundles.rb
- name: Test bundle manifest validation
run: ruby scripts/test-validate-bundles.rb
- name: Validate lifecycle capability matrix catalog
run: ruby scripts/gen-lifecycle-matrix.rb
- name: Validate lifecycle capability matrix
run: ruby scripts/validate-lifecycle-matrix.rb
- name: Build tracked Python packages
run: |
wheel_dir=$(mktemp -d)
while IFS= read -r pyproject; do
# Skip root pyproject.toml (not a distributable package)
[ "$pyproject" = "pyproject.toml" ] && continue
python3 -m pip wheel --no-deps "./$(dirname "$pyproject")" --wheel-dir "$wheel_dir"
done < <(git ls-files -- ':(glob)**/pyproject.toml')