name: CI on: # Only main on push. A PR branch is already covered by the pull_request # event, and running both fired two identical suites concurrently — which # doubled the LLM tokens the live tests spend and tripped the proxy's # per-minute limit. push: branches: [main] pull_request: # Manual re-run, e.g. after rotating a credential or raising a budget cap. workflow_dispatch: jobs: checks: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install uv run: | curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> "$GITHUB_PATH" - name: Sync workspace run: uv sync --all-packages - name: Install sshd # The tests reach "the build VM" over real SSH, through a throwaway # sshd the test fixture starts (nisse_dev/testing.py). run: | SUDO=$(command -v sudo || true) $SUDO apt-get update -qq $SUDO apt-get install -y -qq openssh-server openssh-client > /dev/null $SUDO mkdir -p /run/sshd - name: Lint run: uv run ruff check . - name: Format check run: uv run ruff format --check . - name: Unit tests run: uv run pytest -m "not integration" - name: Push key # The sandbox's deploy key, where nisse-test.yaml expects it. env: NISSE_PUSH_KEY: ${{ secrets.NISSE_PUSH_KEY }} run: | mkdir -p /tmp/nisse-test printf '%s\n' "$NISSE_PUSH_KEY" > /tmp/nisse-test/push_key chmod 600 /tmp/nisse-test/push_key - name: Integration tests # Everything but the secrets is in tests/integration/nisse-test.yaml, # which refers to these by name. A missing secret fails the live # tests that need it; it is never quietly turned into a skip. env: NISSE_LLM_TOKEN: ${{ secrets.NISSE_LLM_TOKEN }} NISSE_MATRIX_TOKEN: ${{ secrets.NISSE_MATRIX_TOKEN }} NISSE_GITEA_TOKEN: ${{ secrets.NISSE_GITEA_TOKEN }} run: uv run pytest -m integration -rs