Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
8dcac9f
Initial commit with some start on test directory restructuring
timlichtenberg Dec 31, 2025
a45c633
Refactor CI workflow for improved testing and compatibility across Py…
timlichtenberg Dec 31, 2025
8bd6722
Update CI workflow to trigger on pushes/PRs to dev branch for improve…
timlichtenberg Dec 31, 2025
804acb7
Add test branch to CI workflow triggers for testing
timlichtenberg Dec 31, 2025
1081f77
Trigger CI after MORS and aragog NumPy 2.0 fixes
timlichtenberg Dec 31, 2025
86339ef
Install local MORS and aragog in CI to test NumPy 2.0 fixes
timlichtenberg Dec 31, 2025
c048960
Clone MORS and aragog repos explicitly in CI
timlichtenberg Dec 31, 2025
48be087
Test Aragog fix branch tl/deprecation_fixes_line138 in CI
timlichtenberg Dec 31, 2025
7782f14
Trigger CI: test aragog output.py fix
timlichtenberg Jan 2, 2026
9a78f58
Trigger CI: test comprehensive aragog NumPy 2.0 fixes
timlichtenberg Jan 2, 2026
a1f5441
Fix NumPy 2.0 compatibility in PROTEUS: convert numpy scalar to float…
timlichtenberg Jan 2, 2026
25f932e
Fix NumPy 2.0 logging conversions in interior wrapper
timlichtenberg Jan 2, 2026
52de500
CI: temporarily run only Ubuntu Python 3.13 (commented macOS/3.12)
timlichtenberg Jan 2, 2026
41fafbd
Fix NumPy 2.0: convert array outputs to scalars in interior wrapper
timlichtenberg Jan 2, 2026
1b0544f
Fix coverage: align pytest --cov path with package name
timlichtenberg Jan 2, 2026
71ba172
fix: Remove pytest-cov options conflicting with coverage run command
timlichtenberg Jan 2, 2026
d016472
ci: Update aragog clone to use main branch
timlichtenberg Jan 2, 2026
a89f94b
perf: Add caching for SOCRATES binaries and AGNI Julia depot
timlichtenberg Jan 2, 2026
ee81d7c
fix: Correct cache restore/save order for SOCRATES and AGNI
timlichtenberg Jan 2, 2026
6aa423f
test: Trigger CI to test cache restoration
timlichtenberg Jan 2, 2026
7e3aeb8
fix: Implement hash-based cache invalidation for SOCRATES and AGNI
timlichtenberg Jan 2, 2026
9597e32
feat: Conditional free disk space step (Option A optimization)
timlichtenberg Jan 2, 2026
cfadff8
fix: Clone SOCRATES and AGNI before cache restore for hash-based keys
timlichtenberg Jan 2, 2026
315c6c2
docs: Update testing infrastructure with ecosystem deployment guide a…
timlichtenberg Jan 2, 2026
ac0d3ce
docs: Add CALLIOPE Phase 2 improvements to testing infrastructure guide
timlichtenberg Jan 2, 2026
491a0c3
feat: Add coverage ratcheting mechanism and rename workflow/docs files
timlichtenberg Jan 2, 2026
5d11f05
ci: Run full matrix nightly at 2am
timlichtenberg Jan 2, 2026
47edb82
ci: fix workflow run commands
timlichtenberg Jan 2, 2026
431e708
ci: gate macOS job to schedule
timlichtenberg Jan 2, 2026
c8fc8c9
feat: Add PROTEUS Copilot guidelines for testing standards, code qual…
timlichtenberg Jan 3, 2026
67f6703
refactor: Update Copilot guidelines to improve test infrastructure or…
timlichtenberg Jan 3, 2026
4eef3eb
docs: Enhance PROTEUS Ecosystem Copilot Guidelines with installation …
timlichtenberg Jan 3, 2026
3137ce9
Changed to C lang
timlichtenberg Jan 3, 2026
8e9b013
refactor: Update coverage requirements and testing documentation for …
timlichtenberg Jan 3, 2026
c0b97a2
docs: Update coverage recommendations in test quality gate and infras…
timlichtenberg Jan 3, 2026
a22b84f
change directory for copilot-instructions.md
timlichtenberg Jan 3, 2026
0f571e9
ci: finalize test infra fixes
timlichtenberg Jan 3, 2026
3a1f2d1
ci: Implement second round of Copilot review fixes
timlichtenberg Jan 3, 2026
8155e59
ci: Implement third round of Copilot review fixes (15 issues)
timlichtenberg Jan 3, 2026
0e0fdfa
ci: Fix long line lengths in ci_tests.yml cache keys (lines 152, 397)
timlichtenberg Jan 3, 2026
dbfb9ae
ci: Fix long AGNI cache key lines (lines 171, 236, 429, 493)
timlichtenberg Jan 3, 2026
1dae6ab
fix: Implement all Copilot review feedback (Priority 1, 2, 3)
timlichtenberg Jan 3, 2026
7c66722
docs: Update tools/README.md with comprehensive descriptions of all a…
timlichtenberg Jan 3, 2026
6ff875e
docs: Update testing documentation for accurate pytest-cov vs coverag…
timlichtenberg Jan 3, 2026
922eb67
ci: build socrates and init agni
timlichtenberg Jan 3, 2026
c7d728a
ci: generate socrates julia wrappers
timlichtenberg Jan 3, 2026
ac029f3
Switch CI to Python 3.12 and developer install pathway
timlichtenberg Jan 3, 2026
b459136
ci: Add test_infrastructure.md compliance enhancements
timlichtenberg Jan 3, 2026
1c6ad5b
fix: Resolve critical workflow issues for CI test execution
timlichtenberg Jan 3, 2026
8f797d8
fix: Remove Unicode emoji from validation script for CI compatibility
timlichtenberg Jan 3, 2026
ae85486
CI: fast-fail test structure
timlichtenberg Jan 3, 2026
9a3df89
Fix: Skip integration tests in validation (orphaned test dir)
timlichtenberg Jan 3, 2026
e65d9d2
Fix: Use arithmetic expansion instead of (( )) for set -e compatibility
timlichtenberg Jan 3, 2026
8b59e65
Fix: Address Copilot review comments - YAML cache key formatting & TO…
timlichtenberg Jan 3, 2026
c734bcd
feat: Implement Docker-based CI/CD architecture for fast testing
timlichtenberg Jan 4, 2026
a1bcea5
Fix Dockerfile: Install Julia 1.11 and configure git HTTPS
timlichtenberg Jan 4, 2026
896ba38
Add docker-build.log to .gitignore
timlichtenberg Jan 4, 2026
25c7b61
Add workflow_dispatch for manual testing of Docker CI/CD
timlichtenberg Jan 4, 2026
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
58 changes: 58 additions & 0 deletions .github/ISSUE_TEMPLATE/test_coverage_improvement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: Test Coverage Improvement
about: Track test coverage improvements for specific folders
title: 'Improve test coverage for [FOLDER]'
labels: 'testing, enhancement'
assignees: ''
---

## Folder
<!-- e.g., proteus.config, proteus.interior, etc. -->

## Current Coverage
<!-- Run: pytest --cov=src/proteus/[folder] --cov-report=term-missing -->
```
Current: X%
Target: Y%
```

## Uncovered Lines
<!-- From coverage report --show-missing -->
```
file.py: 10, 25-30, 45
```

## Test Strategy

### Unit Tests Needed
- [ ] Function: `function_name()` (lines X-Y)
- [ ] Function: `another_function()` (lines X-Y)
- [ ] Class: `ClassName` (lines X-Y)

### Integration Tests Needed
- [ ] Integration point: description
- [ ] Workflow: description

### Edge Cases
- [ ] Error handling for X
- [ ] Boundary conditions for Y
- [ ] Invalid input handling

## Implementation Plan

1. [ ] Create test file: `tests/[folder]/test_[feature].py`
2. [ ] Add fixtures in `conftest.py` (if needed)
3. [ ] Write unit tests
4. [ ] Write integration tests
5. [ ] Run locally: `pytest tests/[folder]/`
6. [ ] Verify coverage: `pytest --cov=src/proteus/[folder] --cov-report=html`
7. [ ] Update documentation

## Success Criteria
- [ ] Coverage increases to target %
- [ ] All new tests pass
- [ ] No regressions in existing tests
- [ ] CI pipeline passes

## Notes
<!-- Additional context, challenges, or considerations -->
74 changes: 74 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# PROTEUS Ecosystem Copilot Guidelines

You are an expert Scientific Software Engineer working on the PROTEUS ecosystem.

## Ecosystem Structure

PROTEUS is a coupled atmosphere-interior framework with a modular architecture:

- **[PROTEUS](https://github.com/FormingWorlds/PROTEUS)** (main repository): Core coupling framework and orchestration
- **[AGNI](https://github.com/nichollsh/AGNI)**: Radiative-convective atmospheric energy module (Julia)
- **[SOCRATES](https://github.com/nichollsh/SOCRATES)**: Spectral radiative transfer code (Fortran)
- **[CALLIOPE](https://github.com/FormingWorlds/CALLIOPE)**: Volatile in-/outgassing and thermodynamics module (Python)
- **[JANUS](https://github.com/FormingWorlds/JANUS)**: 1D convective atmosphere module (Python)
- **[MORS](https://github.com/FormingWorlds/MORS)**: Stellar evolution module (Python)
- **[ARAGOG](https://github.com/FormingWorlds/aragog)**: Interior thermal evolution module based on T-P formalism (Python)
- **[SPIDER](https://github.com/djbower/spider)**: Interior thermal evolution module based on T-S formalism (C)
- **[VULCAN](https://github.com/FormingWorlds/VULCAN)**: Atmospheric chemistry module (Python)
- **[ZEPHYRUS](https://github.com/FormingWorlds/ZEPHYRUS)**: Atmospheric escape module (Python)
- **[Love.jl](https://github.com/FormingWorlds/Love.jl)**: Tidal evolution module (Julia)

**Important:** Each module is maintained in its own GitHub repository but is typically cloned/installed within the PROTEUS directory structure for integrated development. When working on any module in the ecosystem, apply these guidelines consistently.

## Scope of These Guidelines

**These guidelines apply to ALL Python modules in the PROTEUS ecosystem.** Whether you are working in:
- The main PROTEUS repository
- A standalone module (CALLIOPE, JANUS, MORS, etc.)
- Tests for any ecosystem component

Follow the same standards for testing, coverage, code quality, and infrastructure.

## Installation & Dependencies

For installation instructions and dependency management across the ecosystem:
- **Main installation guide:** `docs/installation.md` - Standard user and developer installation procedures
- **Local machine setup:** `docs/local_machine_guide.md` - Platform-specific setup (macOS, Linux, Windows)
- **Cluster setup:** `docs/kapteyn_cluster_guide.md` - HPC cluster configuration (see also `habrok_cluster_guide.md`, `snellius_cluster_guide.md`)

When helping with installation or dependency issues, always reference these guides first. The `proteus install-all` command handles most submodule installations automatically. However, whenever possible, prefer the developer installation steps outlined in the installation guide for editable installs.

## 1. Test Infrastructure & Organization
- **Structure:** Tests MUST mirror the source code structure exactly. For every file in `src/<package>/`, create a corresponding `tests/<package>/test_<filename>.py`.
- **Example:** `src/proteus/config/_config.py` → `tests/config/test_config.py`
- **Discovery:** Use `pytest --collect-only` to verify test discovery before writing tests.
- **Tools:** Run `bash tools/validate_test_structure.sh` to check if tests mirror source structure.
- **Documentation:** See `docs/test_infrastructure.md` for full testing infrastructure details.

## 2. Testing Standards (pytest)
- **Framework:** Use `pytest` exclusively in the `tests/` directory.
- **Coverage Tool:** Two equivalent approaches are supported:
- Local: `pytest --cov` (uses pytest-cov plugin, convenient)
- CI/Local: `coverage run -m pytest` (matches CI exactly, compatible with ratcheting)
- Choose based on preference; both work correctly.
- **Speed:** Unit tests must run in <100ms. Aggressively mock heavy simulations, I/O, and external APIs using `unittest.mock`.
- **Integration:** Mark slow tests (full simulation loops) with `@pytest.mark.slow`.
- **Markers:** Use pytest markers: `@pytest.mark.unit` for unit tests, `@pytest.mark.integration` for integration tests.
- **Floats:** NEVER use `==` for floats. Use `pytest.approx(val, rel=1e-5)` or `np.testing.assert_allclose`.
- **Physics:** Ensure inputs are physically valid (e.g., T > 0K) unless testing error handling.

## 3. Coverage Requirements
- **Threshold:** Check `pyproject.toml` [tool.coverage.report] `fail_under` for current threshold.
- **Automatic Ratcheting:** Coverage threshold automatically increases on main branch via `tools/update_coverage_threshold.py` (never decreases). See CALLIOPE for reference implementation.
- **Reports:** Run `pytest --cov --cov-report=html` and inspect `htmlcov/index.html` for gaps.
- **Analysis:** Use `bash tools/coverage_analysis.sh` to identify low-coverage modules needing tests.
- **Quality Gate:** All PRs must pass the coverage threshold defined in CI (see `.github/workflows/proteus_test_quality_gate.yml`).

## 4. Code Quality & Style
- **Linting:** Follow `ruff` standards. Line length < 92 chars, max indentation 3 levels.
- **Type Hints:** Use standard Python type hints.
- **Docstrings:** Include brief docstrings describing the physical scenario.

## 5. Safety & Determinism
- **Randomness:** Explicitly set seeds (e.g., `np.random.seed(42)`) in tests.
- **Files:** Do not generate tests that produce large output files (unless explicitly instructed); use `tempfile` or mocks.
158 changes: 158 additions & 0 deletions .github/workflows/ci-nightly-science.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
name: CI - Nightly Science Validation

# Purpose: Deep validation of scientific accuracy using pre-built Docker image
# Runs comprehensive physics simulations to ensure correctness
# Triggers: Nightly at 03:00 UTC (1 hour after Docker build completes)

on:
schedule:
- cron: "0 3 * * *" # Nightly at 03:00 UTC
workflow_dispatch: # Allow manual trigger

permissions:
contents: read
packages: read

env:
REGISTRY: ghcr.io
IMAGE_NAME: formingworlds/proteus

jobs:
science-validation:
name: Full Science Validation (@pytest.mark.slow)
runs-on: ubuntu-latest
timeout-minutes: 240 # 4 hours for comprehensive tests
container:
image: ghcr.io/formingworlds/proteus:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --user root

steps:
- name: Checkout main branch
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0

- name: Overlay code onto container
run: |
echo "Copying code over container base..."
rsync -av --exclude='.git' --exclude='SPIDER' --exclude='socrates' --exclude='petsc' --exclude='AGNI' . /opt/proteus/
cd /opt/proteus
pip install -e ".[develop]" --no-deps

- name: Download test data if needed
run: |
cd /opt/proteus
# Uncomment if FWL_DATA needs to be populated
# proteus get stellar
# proteus get spectral --name Frostflow --bands 48

- name: Run slow integration tests
run: |
cd /opt/proteus
pytest -m slow -v --tb=long --maxfail=3 \
--cov=src \
--cov-report=term-missing \
--cov-report=xml \
--cov-report=html

- name: Upload coverage report
uses: codecov/codecov-action@v4
if: always()
with:
files: /opt/proteus/coverage.xml
flags: slow-integration-tests
name: nightly-science-coverage
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Upload HTML coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: science-coverage-html
path: /opt/proteus/htmlcov/
retention-days: 30

- name: Upload simulation outputs
uses: actions/upload-artifact@v4
if: always()
with:
name: science-validation-outputs
path: |
/opt/proteus/output/
/opt/proteus/fwl_data/
retention-days: 30

- name: Notify on failure
if: failure()
run: |
echo "::error::Nightly science validation failed. Check logs and artifacts."
echo "This indicates potential scientific correctness issues."

integration-tests:
name: Integration Tests (Multi-module)
runs-on: ubuntu-latest
timeout-minutes: 120
container:
image: ghcr.io/formingworlds/proteus:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --user root

steps:
- name: Checkout main branch
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0

- name: Overlay code onto container
run: |
echo "Copying code over container base..."
rsync -av --exclude='.git' --exclude='SPIDER' --exclude='socrates' --exclude='petsc' --exclude='AGNI' . /opt/proteus/
cd /opt/proteus
pip install -e ".[develop]" --no-deps

- name: Run integration tests
run: |
cd /opt/proteus
pytest -m integration -v --tb=long \
--cov=src \
--cov-report=term-missing \
--cov-report=xml \
--cov-report=html

- name: Upload coverage report
uses: codecov/codecov-action@v4
if: always()
with:
files: /opt/proteus/coverage.xml
flags: integration-tests
name: nightly-integration-coverage
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Upload HTML coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-coverage-html
path: /opt/proteus/htmlcov/
retention-days: 30

- name: Upload integration outputs
uses: actions/upload-artifact@v4
if: failure()
with:
name: integration-test-failures
path: |
/opt/proteus/output/
/opt/proteus/tests/**/*.log
retention-days: 14
Loading
Loading