name: PR Checks on: pull_request: branches: [main] concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: test: runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@v4 - name: Use system Python run: | echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies (with dev) env: UV_NO_PROGRESS: "1" run: uv sync --group dev - name: Run tests with coverage run: | uv run pytest tests/unit/ \ -v \ --tb=short \ --cov=src/kwork_api \ --cov-report=term-missing \ --cov-report=html:coverage-html \ --html=test-results/report.html \ --self-contained-html - name: Check coverage threshold (90%) run: | COVERAGE=$(uv run coverage report | grep TOTAL | awk '{print $NF}' | tr -d '%') echo "Coverage: ${COVERAGE}%" if (( $(echo "$COVERAGE < 90" | bc -l) )); then echo "❌ Coverage ${COVERAGE}% is below 90% threshold" exit 1 fi echo "✅ Coverage ${COVERAGE}% meets 90% threshold" - name: Upload test results uses: actions/upload-artifact@v3 if: always() with: name: test-results path: test-results/ retention-days: 7 - name: Upload coverage report uses: actions/upload-artifact@v3 if: always() with: name: coverage-report path: coverage-html/ retention-days: 7 - name: Run linting run: uv run ruff check src/kwork_api tests/ - name: Run formatter check run: uv run ruff format --check src/kwork_api tests/ security: runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v4 - name: Use system Python run: | echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: uv sync --group dev - name: Run safety check env: UV_NO_PROGRESS: "1" run: | echo "Running pip-audit on production dependencies..." # Audit only production dependencies (exclude dev) uv pip compile pyproject.toml --no-dev -o requirements-prod.txt uv run pip-audit --format json --output audit-results.json -r requirements-prod.txt || true # Check if vulnerabilities found if [ -s audit-results.json ] && [ "$(cat audit-results.json)" != "[]" ]; then echo "❌ Found vulnerabilities in production dependencies" echo "📄 Audit log uploaded as artifact 'security-audit'" exit 1 else echo "✅ No vulnerabilities in production dependencies" rm -f audit-results.json fi - name: Upload audit log uses: actions/upload-artifact@v3 if: failure() with: name: security-audit path: audit-results.json retention-days: 7 - name: Check for secrets run: | if grep -r "password\s*=" --include="*.py" src/; then echo "❌ Found hardcoded passwords in src/" exit 1 fi if grep -r "token\s*=" --include="*.py" src/; then echo "❌ Found hardcoded tokens in src/" exit 1 fi echo "✅ No hardcoded secrets found"