cleanup #3
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: [ master, develop ] | |
| pull_request: | |
| branches: [ master ] | |
| schedule: | |
| # Run daily at 3 AM UTC to catch dependency issues | |
| - cron: '0 3 * * *' | |
| workflow_dispatch: # Manual trigger option | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| pages: write # For GitHub Pages deployment | |
| id-token: write # For GitHub Pages deployment | |
| jobs: | |
| # Quick quality checks that should pass before running expensive tests | |
| pre-check: | |
| name: Pre-checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check commit message | |
| if: github.event_name == 'pull_request' | |
| uses: wagoid/commitlint-github-action@v5 | |
| continue-on-error: true # Don't fail on commit message | |
| - name: Check for large files | |
| uses: ActionsDesk/lfs-warning@v2.0 | |
| with: | |
| filesizelimit: 10485760 # 10MB | |
| # Code quality and linting | |
| quality: | |
| name: Code Quality | |
| runs-on: ubuntu-latest | |
| needs: pre-check | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Cache pip packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e ".[dev]" | |
| - name: Run Black | |
| run: black --check --diff . | |
| - name: Run isort | |
| run: isort --check-only --diff . | |
| - name: Run Ruff | |
| run: ruff check . | |
| - name: Run mypy | |
| run: mypy tenets --strict | |
| continue-on-error: true # Strict typing is aspirational | |
| - name: Run Bandit security linting | |
| run: bandit -r tenets -ll | |
| - name: Check dependencies with Safety | |
| run: safety check | |
| continue-on-error: true # Don't fail on advisories | |
| # Run tests across multiple Python versions and OS | |
| test: | |
| name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: pre-check | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| python-version: ['3.9', '3.10', '3.11', '3.12'] | |
| exclude: | |
| # macOS runners are expensive, only test min/max Python | |
| - os: macos-latest | |
| python-version: '3.10' | |
| - os: macos-latest | |
| python-version: '3.11' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('pyproject.toml') }} | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e ".[dev,test]" | |
| - name: Run pytest with coverage | |
| run: | | |
| pytest -v --cov=tenets --cov-report=xml --cov-report=term | |
| - name: Upload coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| file: ./coverage.xml | |
| fail_ci_if_error: false | |
| verbose: true | |
| # Test with optional dependencies | |
| test-optional: | |
| name: Test with optional dependencies | |
| runs-on: ubuntu-latest | |
| needs: pre-check | |
| strategy: | |
| matrix: | |
| extras: ['ml', 'viz', 'all'] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install with extras | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e ".[${{ matrix.extras }},test]" | |
| - name: Run tests | |
| run: pytest -v -m "not slow" | |
| # Build and test installation | |
| build: | |
| name: Build distribution | |
| runs-on: ubuntu-latest | |
| needs: [quality, test] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install build twine | |
| - name: Build package | |
| run: python -m build | |
| - name: Check package | |
| run: twine check --strict dist/* | |
| - name: Test installation | |
| run: | | |
| pip install dist/*.whl | |
| tenets --version | |
| tenets --help | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: dist | |
| path: dist/ | |
| # Build and validate documentation | |
| docs-build: | |
| name: Build documentation | |
| runs-on: ubuntu-latest | |
| needs: pre-check | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Cache pip packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-docs-${{ hashFiles('pyproject.toml') }} | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install mkdocs mkdocs-material mkdocs-material-extensions | |
| pip install pymdown-extensions mkdocs-minify-plugin | |
| pip install -e . | |
| - name: Build docs | |
| run: | | |
| mkdocs build --strict --verbose | |
| - name: Upload docs artifacts | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: docs-site | |
| path: site/ | |
| - name: Check for broken links (PR only) | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| pip install linkchecker | |
| linkchecker site/ --ignore-url=https://github.com/jddunn/tenets | |
| continue-on-error: true | |
| # Deploy documentation to GitHub Pages (master branch only) | |
| docs-deploy: | |
| name: Deploy documentation | |
| runs-on: ubuntu-latest | |
| needs: [docs-build, test, quality] | |
| # Only deploy from master branch on push events (not PRs or schedule) | |
| if: github.ref == 'refs/heads/master' && github.event_name == 'push' | |
| permissions: | |
| contents: write | |
| pages: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Need full history for git info | |
| - name: Configure git | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Cache pip packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-docs-${{ hashFiles('pyproject.toml') }} | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install mkdocs mkdocs-material mkdocs-material-extensions | |
| pip install pymdown-extensions mkdocs-minify-plugin | |
| pip install mike | |
| pip install -e . | |
| - name: Deploy to GitHub Pages | |
| run: | | |
| # Deploy master as both 'dev' and 'latest' | |
| mike deploy --push --update-aliases dev latest | |
| mike set-default --push latest | |
| # Docker build test | |
| docker: | |
| name: Docker build | |
| runs-on: ubuntu-latest | |
| needs: pre-check | |
| if: github.event_name != 'schedule' # Skip Docker on daily runs | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: false | |
| tags: tenets:test | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Test Docker image | |
| run: | | |
| docker run --rm tenets:test --version | |
| docker run --rm tenets:test --help | |
| # All tests passed - REQUIRED for branch protection | |
| all-checks: | |
| name: All checks passed | |
| runs-on: ubuntu-latest | |
| needs: [quality, test, test-optional, build, docs-build] | |
| if: always() | |
| steps: | |
| - name: Verify all checks passed | |
| if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') | |
| run: | | |
| echo "One or more required checks failed" | |
| exit 1 | |
| - name: All checks passed | |
| run: echo "✅ All checks passed successfully!" | |
| - name: Comment on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v6 | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: '✅ All CI checks passed! Ready for review.' | |
| }) | |
| continue-on-error: true |