diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..d21e991 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,80 @@ +--- +# ci-sync: 2026-05-30T01:29:53Z +# Homelab CI — Python lane (git-ci-01) + secret scan (git-ci-02) +# Skip: @skipci in branch name or commit message +name: CI + +on: + push: + branches: [master, main] + pull_request: + types: [opened, synchronize, reopened] + +jobs: + skip-ci-check: + runs-on: [homelab, self-hosted, linux] + container: + image: node:20-bookworm + outputs: + should-skip: ${{ steps.check.outputs.skip }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + - id: check + run: | + SKIP=0 + BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" + MSG="${GITHUB_EVENT_HEAD_COMMIT_MESSAGE:-$(git log -1 --pretty=%B 2>/dev/null || true)}" + echo "$BRANCH" "$MSG" | grep -qi '@skipci' && SKIP=1 + echo "skip=$SKIP" >> $GITHUB_OUTPUT + + python-ci: + needs: skip-ci-check + if: needs.skip-ci-check.outputs.should-skip != '1' + runs-on: [homelab, self-hosted, linux, python] + container: + # node image: actions/checkout@v4 needs Node; install python3 in-job + image: node:20-bookworm + steps: + - uses: actions/checkout@v4 + + - name: Install Python tooling + run: | + apt-get update -qq + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3 python3-pip python3-venv + python3 -m pip install --upgrade pip --break-system-packages + if [ -f requirements.txt ]; then pip install -r requirements.txt --break-system-packages; fi + if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt --break-system-packages; fi + pip install bandit pip-audit ruff --break-system-packages + + - name: Ruff lint + run: ruff check . || true + + - name: Bandit (advisory) + run: bandit -r . -q || true + + - name: pip-audit (advisory) + run: pip-audit -r requirements.txt 2>/dev/null || pip-audit 2>/dev/null || true + + - name: Pytest + run: | + if [ -d tests ] || ls test_*.py *_test.py 2>/dev/null; then + pip install pytest --break-system-packages + pytest -q || true + else + echo "No tests found — skip" + fi + + secret-scan: + needs: skip-ci-check + if: needs.skip-ci-check.outputs.should-skip != '1' + runs-on: [homelab, self-hosted, linux, heavy] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Gitleaks + run: | + docker run --rm -v "$PWD:/repo" ghcr.io/gitleaks/gitleaks:latest \ + detect --source /repo --no-banner --redact