Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 31 additions & 94 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,30 @@
name: CI Tests
# =============================================================================
# .github/workflows/ci.yml — Continuous Integration
# =============================================================================
# Runs on every push and PR to main/develop.
# Jobs: tests (pytest + coverage), code quality (black, isort, ruff).
# =============================================================================

name: CI

on:
push:
branches:
- main
- develop
branches: [main, develop]
pull_request:
branches:
- main
- develop
branches: [main, develop]

# Principle of Least Privilege: Base permissions are read-only
permissions: read-all

# Cancel stale runs when a new push arrives on the same branch or PR.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
reuse:
name: REUSE Compliance
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5.2.2

- name: Run reuse lint
run: |
uv tool run reuse lint

test:
name: Test on Python ${{ matrix.python-version }}
name: Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write

strategy:
fail-fast: false
Expand All @@ -50,31 +33,30 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Set up uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5.2.2
uses: astral-sh/setup-uv@v5

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
run: uv pip install --system -e ".[dev]"

- name: Run pytest
run: |
uv run pytest tests/ -v -n auto --tb=short --cov=src/spotoptim --cov-branch --cov-report=xml --cov-report=term
uv run pytest tests/ -v -n auto --tb=short \
--cov=src/spotoptim --cov-branch \
--cov-report=xml --cov-report=term

- name: Upload results to Codecov
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3
- name: Upload coverage to Codecov
if: always()
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: sequential-parameter-optimization/spotoptim
files: ./coverage.xml
fail_ci_if_error: false

Expand All @@ -84,72 +66,27 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Set up uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5.2.2
uses: astral-sh/setup-uv@v5

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
run: uv pip install --system -e ".[dev]"

- name: Check formatting with black
run: |
black --check src/ tests/
- name: Check formatting (black)
run: black --check src/ tests/
continue-on-error: true

- name: Check imports with isort
run: |
isort --check-only src/ tests/
- name: Check imports (isort)
run: isort --check-only src/ tests/
continue-on-error: true

- name: Lint with ruff
run: |
ruff check src/ tests/
continue-on-error: true

security:
name: Security Scan
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"

- name: Set up uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5.2.2

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"

- name: Check dependencies with safety
run: |
safety check --json
continue-on-error: true

- name: Security scan with bandit
run: |
bandit -r src/spotoptim/ -f sarif -o bandit-report.sarif
continue-on-error: true

- name: Upload bandit report to security tab
if: always()
uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
with:
sarif_file: bandit-report.sarif
category: bandit
- name: Lint (ruff)
run: ruff check src/ tests/
continue-on-error: true
54 changes: 13 additions & 41 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -1,42 +1,22 @@
# SPDX-FileCopyrightText: 2026 bartzbeielstein
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# =============================================================================
# .github/workflows/docs.yml — Documentation Build & Deploy
# .github/workflows/docs.yml — Manual Documentation Rebuild
# =============================================================================
# Pipeline:
# 1. Checkout
# 2. Set up Python + uv
# 3. Install Python dependencies
# 4. Install Quarto CLI (PINNED)
# 5. Generate API reference with quartodoc
# 6. Render Quarto site & publish to rh-pages
# Use workflow_dispatch to manually rebuild docs without a release.
# Normal doc deployment happens automatically inside release.yml.
# =============================================================================

name: Documentation

on:
push:
branches:
- main # Production docs only; develop pushes are not deployed.
paths:
- '**/*.qmd'
- '_quarto.yml'
- 'src/spotoptim/**'
- 'pyproject.toml'
workflow_dispatch:

permissions: read-all

# Prevent concurrent deployments from overwriting each other on gh-pages.
# A docs build can take several minutes; let it finish rather than cancel.
concurrency:
group: docs-deploy
cancel-in-progress: false

env:
# ⚠️ Pinned to match production safety standards.
QUARTO_VERSION: "1.8.27"
PYTHON_VERSION: "3.13"

Expand All @@ -45,51 +25,43 @@ jobs:
name: Build & Deploy Documentation
runs-on: ubuntu-latest
permissions:
contents: write # push access via gh-pages
contents: write

steps:
- name: Checkout (full history)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history ensures cross-referencing interlinks work safely
fetch-depth: 0

- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v5.3.0
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Set up uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5.2.2
uses: astral-sh/setup-uv@v5

- name: Install Python dependencies
run: |
# Use pyproject.toml [dev] and docs extras to install quartodoc safely
uv sync --group dev --extra docs
- name: Install dependencies
run: uv pip install --system -e ".[dev,docs]"

- name: Install Quarto CLI ${{ env.QUARTO_VERSION }}
uses: quarto-dev/quarto-actions/setup@8a96df13519ee81fd526f2dfca5962811136661b # v2.1.2
uses: quarto-dev/quarto-actions/setup@v2
with:
version: ${{ env.QUARTO_VERSION }}

- name: Verify Quarto installation
run: quarto check

- name: Generate API reference with quartodoc
# Rebuild dynamically instead of keeping autogenerated `.qmd` tracked into git
run: |
uv run python docs/quartodoc_build.py
uv run quartodoc interlinks



- name: Render Quarto site
run: uv run quarto render --no-cache

- name: Deploy to GitHub Pages
uses: quarto-dev/quarto-actions/publish@8a96df13519ee81fd526f2dfca5962811136661b # v2.1.2
uses: quarto-dev/quarto-actions/publish@v2
with:
target: gh-pages
path: _site
render: "false" # Handled in prior step
render: "false"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Loading
Loading