docs: soften persona language in public-facing surfaces #68
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| # Each job detects Python locally to handle multi-runner setups | |
| FIND_PY: | | |
| for candidate in python3.12 python3.13 python3; do | |
| if command -v "$candidate" >/dev/null 2>&1; then | |
| version=$("$candidate" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") | |
| major=$(echo "$version" | cut -d. -f1) | |
| minor=$(echo "$version" | cut -d. -f2) | |
| if [ "$major" -ge 3 ] && [ "$minor" -ge 12 ]; then | |
| PY="$candidate" | |
| echo "PY=$candidate" >> "$GITHUB_ENV" | |
| echo "Found $candidate ($version)" | |
| break | |
| fi | |
| fi | |
| done | |
| if [ -z "${PY:-}" ]; then | |
| echo "::error::No Python 3.12+ found on this runner" | |
| exit 1 | |
| fi | |
| jobs: | |
| lint: | |
| runs-on: [self-hosted, Linux] | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Detect Python 3.12+ | |
| run: eval "$FIND_PY" | |
| - name: Lint with ruff | |
| run: $PY -m ruff check src/ tests/ | |
| - name: Check formatting | |
| run: $PY -m ruff format --check src/ tests/ | |
| test: | |
| runs-on: [self-hosted, Linux] | |
| needs: lint | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Detect Python 3.12+ | |
| run: eval "$FIND_PY" | |
| - name: Install and test | |
| run: | | |
| $PY -m venv .venv | |
| .venv/bin/pip install --upgrade pip | |
| .venv/bin/pip install -e ".[test]" | |
| .venv/bin/python -m pytest tests/ -v --tb=short --cov=project_forge --cov-fail-under=40 --cov-report=term-missing | |
| build: | |
| runs-on: [self-hosted, Linux] | |
| needs: test | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Detect Python 3.12+ | |
| run: eval "$FIND_PY" | |
| - name: Build and verify wheel | |
| run: | | |
| $PY -m venv .build-venv | |
| .build-venv/bin/pip install --upgrade pip | |
| .build-venv/bin/pip install build | |
| .build-venv/bin/python -m build --outdir dist/ | |
| WHEEL=$(ls dist/*.whl) | |
| echo "Built: $WHEEL ($(stat -c%s "$WHEEL") bytes)" | |
| $PY -c " | |
| import zipfile, sys | |
| with zipfile.ZipFile('$WHEEL') as zf: | |
| names = zf.namelist() | |
| required = ['project_forge/models.py', 'project_forge/web/', 'templates/', 'static/'] | |
| for r in required: | |
| if not any(r in n for n in names): | |
| print(f'MISSING: {r}'); sys.exit(1) | |
| print(f'FOUND: {r}') | |
| print(f'Wheel OK: {len(names)} files') | |
| " | |
| - name: Test install in clean venv | |
| run: | | |
| $PY -m venv /tmp/forge-install-test | |
| /tmp/forge-install-test/bin/pip install --upgrade pip | |
| /tmp/forge-install-test/bin/pip install dist/*.whl | |
| /tmp/forge-install-test/bin/python -c "import project_forge; print('OK:', project_forge.__file__)" | |
| test -f /tmp/forge-install-test/bin/forge-generate && echo "PASS: forge-generate" | |
| test -f /tmp/forge-install-test/bin/forge-serve && echo "PASS: forge-serve" | |
| test -f /tmp/forge-install-test/bin/forge-self-improve && echo "PASS: forge-self-improve" | |
| rm -rf /tmp/forge-install-test | |
| security: | |
| runs-on: [self-hosted, Linux] | |
| needs: lint | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Detect Python 3.12+ | |
| run: eval "$FIND_PY" | |
| - name: Security lint | |
| run: $PY -m ruff check src/ --select S --ignore S101,S311,S314,S603,S607,S701 | |
| - name: Dependency audit (pip-audit) | |
| run: | | |
| $PY -m venv .audit-venv | |
| .audit-venv/bin/pip install --upgrade pip | |
| .audit-venv/bin/pip install -e ".[dev]" | |
| .audit-venv/bin/pip-audit --strict --progress-spinner=off || echo "::warning::pip-audit found vulnerabilities" | |
| rm -rf .audit-venv | |
| issue-test-ratio: | |
| runs-on: [self-hosted, Linux] | |
| needs: test | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Detect Python 3.12+ | |
| run: eval "$FIND_PY" | |
| - name: Check issue-to-test ratio | |
| env: | |
| GH_REPO: rayketcham-lab/project-forge | |
| run: | | |
| ISSUE_COUNT=$(gh issue list -R "$GH_REPO" --state all --label feature --json number -q 'length' 2>/dev/null || echo 0) | |
| TEST_COUNT=$($PY -m pytest tests/ --collect-only -q 2>/dev/null | tail -1 | grep -oP '\d+(?= test)' || echo 0) | |
| echo "Feature issues: $ISSUE_COUNT, Tests: $TEST_COUNT" | |
| if [ "$TEST_COUNT" -lt "$ISSUE_COUNT" ]; then | |
| echo "::warning::Test count ($TEST_COUNT) is below feature issue count ($ISSUE_COUNT)" | |
| fi | |
| - name: Detect untested source modules | |
| run: | | |
| echo "=== Gap Detection: checking for untested source modules ===" | |
| UNTESTED="" | |
| for src in $(find src/project_forge -name '*.py' ! -name '__init__.py' ! -path '*/templates/*' ! -path '*/static/*'); do | |
| MODULE=$(basename "$src" .py) | |
| if ! find tests/ -name "*.py" -exec grep -l "$MODULE" {} + >/dev/null 2>&1; then | |
| UNTESTED="$UNTESTED $MODULE" | |
| echo "::warning::No test file references module: $MODULE ($src)" | |
| fi | |
| done | |
| if [ -n "$UNTESTED" ]; then | |
| echo "Untested modules:$UNTESTED" | |
| else | |
| echo "All source modules have corresponding test coverage." | |
| fi | |
| self-improvement-queue: | |
| runs-on: [self-hosted, Linux] | |
| needs: [test] | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Check for open ci-queue items | |
| env: | |
| GH_REPO: rayketcham-lab/project-forge | |
| run: | | |
| set -euo pipefail | |
| QUEUE=$(gh issue list -R "$GH_REPO" --state open --label ci-queue --json number,title -q '.[] | "#\(.number) \(.title)"' 2>/dev/null || true) | |
| COUNT=$(echo "$QUEUE" | grep -c '^#' || true) | |
| echo "Open ci-queue items: $COUNT" | |
| if [ "$COUNT" -gt 0 ]; then | |
| echo "" | |
| echo "=== Self-improvement items awaiting action ===" | |
| echo "$QUEUE" | |
| echo "" | |
| echo "::warning::$COUNT open self-improvement item(s) in the ci-queue." | |
| else | |
| echo "No pending self-improvement items. Queue is clear." | |
| fi |