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
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: ci

on:
push:
branches:
- "**"
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pytest pytest-cov mypy ruff sphinx sphinx-rtd-theme pandas pyarrow folium matplotlib
- name: Lint
run: ruff check src examples tests docs
- name: Type check
run: mypy src/carp
- name: Test
run: pytest --cov=src/carp --cov-branch --cov-fail-under=100
- name: Build docs
run: sphinx-build -b html docs docs/_build/html
132 changes: 132 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: release

on:
push:
tags:
- "**"

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
validate_tag:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- id: version
name: Validate tag against package version
run: |
version=$(python - <<'PY'
import pathlib
import tomllib

project = tomllib.loads(pathlib.Path("pyproject.toml").read_text())
print(project["project"]["version"])
PY
)
tag="${GITHUB_REF_NAME}"
if [ "${tag}" != "${version}" ] && [ "${tag}" != "v${version}" ]; then
echo "Tag ${tag} does not match package version ${version}." >&2
exit 1
fi
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"

test:
needs: validate_tag
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pytest pytest-cov pandas pyarrow folium matplotlib
- name: Run tests
run: pytest --cov=src/carp --cov-branch --cov-fail-under=100

quality:
needs: validate_tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pytest pytest-cov mypy ruff sphinx sphinx-rtd-theme pandas pyarrow folium matplotlib
- name: Lint
run: ruff check src examples tests docs
- name: Type check
run: mypy src/carp
- name: Build docs
run: sphinx-build -W -b html docs docs/_build/html

build:
needs: [test, quality]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Build distributions
run: |
python -m pip install --upgrade pip
python -m pip install build twine
python -m build
python -m twine check dist/*
- uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish_pypi:
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1

publish_github:
needs: [validate_tag, publish_pypi]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Generate checksums
run: shasum -a 256 dist/* > dist/SHA256SUMS.txt
- uses: softprops/action-gh-release@v2
with:
name: Release ${{ needs.validate_tag.outputs.tag }}
tag_name: ${{ needs.validate_tag.outputs.tag }}
generate_release_notes: true
files: dist/*
32 changes: 27 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
# Changelog

All notable changes to this project will be documented in this file.
## [0.2.0] - 2026-03-26

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### Added

- New `CarpStudy` public API as the primary entrypoint for CARP study analysis
- Modular service layout under `carp.core`, `participants`, `records`, `schema`, `export`, `frames`, `types`, `plotting`, and `commandline`
- Self-contained pytest suite with committed multi-phase fixtures and optional `sleep-data` smoke coverage
- 100% line and branch coverage enforcement for `src/carp`
- Sphinx documentation site with autodoc and Napoleon support
- GitHub Actions CI for linting, type-checking, tests, and docs builds
- Tag-driven CD workflow that validates version tags, publishes to PyPI, and creates GitHub releases
- Dedicated `test` and `docs` dependency groups

### Changed

- Replaced the legacy method-heavy design with a thin `CarpStudy` composition root and focused services
- Kept the `carp` CLI command set stable while rewriting the implementation behind modular handlers
- Switched plotting defaults to `dk.cachet.carp.location`
- Made parquet filenames namespace-aware to avoid same-name type collisions
- Added Google-style docstrings and expanded type annotations across the package
- Refreshed the README, example scripts, generated type example, and notebook to use the new API
- Normalized Ruff, MyPy, coverage, and documentation build configuration in `pyproject.toml`

### Removed

## [Unreleased]
- Legacy `carp.reader` monolith
- Legacy `carp.plotting.map_viz` module
- Old `CarpDataStream`-centric example usage and stale plotting/type-generation references

## [0.1.0] - 2024-12-02
## [0.1.0]

### Added

Expand Down
Loading
Loading