|
1 | 1 | # Contributing to TimeRun |
2 | 2 |
|
3 | | -Thank you for your interest in contributing to TimeRun! This document provides guidelines for contributing to the project. |
| 3 | +Thank you for considering contributing to TimeRun. This guide explains how to set up your environment, run tests, and submit changes. |
4 | 4 |
|
5 | | -## Getting Started |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +- [Code of Conduct](#code-of-conduct) |
| 8 | +- [How You Can Help](#how-you-can-help) |
| 9 | +- [Development Setup](#development-setup) |
| 10 | +- [Testing](#testing) |
| 11 | +- [Code Style and Quality](#code-style-and-quality) |
| 12 | +- [Project Structure](#project-structure) |
| 13 | +- [Pull Request Process](#pull-request-process) |
| 14 | +- [Reporting Bugs](#reporting-bugs) |
| 15 | +- [License](#license) |
| 16 | + |
| 17 | +## Code of Conduct |
| 18 | + |
| 19 | +Please be respectful and constructive. By participating, you agree to uphold a welcoming environment for everyone. |
| 20 | + |
| 21 | +## How You Can Help |
| 22 | + |
| 23 | +- **Report bugs** — Open an issue with clear steps to reproduce. |
| 24 | +- **Suggest features** — Open an issue describing the use case and desired behavior. |
| 25 | +- **Submit code** — Fix bugs or add features via pull requests (see [Pull Request Process](#pull-request-process)). |
| 26 | +- **Improve docs** — Fix typos, clarify README or docstrings, or add examples. |
| 27 | + |
| 28 | +## Development Setup |
6 | 29 |
|
7 | 30 | ### Prerequisites |
8 | 31 |
|
9 | | -- Python 3.9 or higher |
10 | | -- Git |
| 32 | +- **Python 3.10+** |
| 33 | +- **Git** |
11 | 34 |
|
12 | | -### Development Setup |
| 35 | +### One-time setup |
| 36 | + |
| 37 | +1. **Fork** the repository on GitHub, then clone your fork: |
13 | 38 |
|
14 | | -1. Fork the repository on GitHub |
15 | | -2. Clone your fork locally: |
16 | 39 | ```bash |
17 | 40 | git clone https://github.com/YOUR_USERNAME/timerun.git |
18 | 41 | cd timerun |
19 | 42 | ``` |
20 | 43 |
|
21 | | -3. Set up the development environment: |
| 44 | +2. **Create and activate a virtual environment** (recommended): |
| 45 | + |
22 | 46 | ```bash |
23 | | - make init |
| 47 | + python3 -m venv .venv |
| 48 | + source .venv/bin/activate # Windows: .venv\Scripts\activate |
24 | 49 | ``` |
25 | 50 |
|
26 | | -4. Activate the virtual environment: |
| 51 | +3. **Install the project in editable mode with dev dependencies**: |
| 52 | + |
27 | 53 | ```bash |
28 | | - source .venv/bin/activate |
| 54 | + pip install -e ".[dev]" |
29 | 55 | ``` |
30 | 56 |
|
31 | | -## Development Workflow |
| 57 | +4. **Install and enable pre-commit hooks** (optional but recommended): |
32 | 58 |
|
33 | | -### Running Tests |
| 59 | + ```bash |
| 60 | + pip install pre-commit |
| 61 | + pre-commit install |
| 62 | + ``` |
| 63 | + |
| 64 | + Or use the convenience target: |
| 65 | + |
| 66 | + ```bash |
| 67 | + make init |
| 68 | + ``` |
| 69 | + |
| 70 | + Then activate the venv: `source .venv/bin/activate`. |
| 71 | + |
| 72 | +### Verify setup |
| 73 | + |
| 74 | +Run the test suite: |
34 | 75 |
|
35 | | -Run the test suite with coverage: |
36 | 76 | ```bash |
37 | 77 | make test |
38 | 78 | ``` |
39 | 79 |
|
40 | | -### Code Style |
| 80 | +You should see the BDD scenarios run and a coverage report. |
| 81 | + |
| 82 | +## Testing |
| 83 | + |
| 84 | +TimeRun uses **behavior-driven development (BDD)** with [behave](https://behave.readthedocs.io/). All tests are written in Gherkin and live under `features/`. |
| 85 | + |
| 86 | +### Run tests |
| 87 | + |
| 88 | +| Command | Description | |
| 89 | +|--------------------|----------------------------------------------------------------| |
| 90 | +| `make test` | Run BDD suite with progress + summary + coverage (default) | |
| 91 | +| `make test-summary`| Summary and coverage only (minimal output) | |
| 92 | +| `make test-verbose`| Full scenario/step output (use when debugging failures) | |
| 93 | +| `behave` | Run BDD suite only (no coverage) | |
| 94 | + |
| 95 | +### Run coverage manually |
| 96 | + |
| 97 | +```bash |
| 98 | +coverage run --source=timerun -m behave # full output |
| 99 | +coverage run --source=timerun -m behave -f progress # progress + summary |
| 100 | +coverage run --source=timerun -m behave -f null # summary only |
| 101 | +coverage report --show-missing |
| 102 | +``` |
| 103 | + |
| 104 | +### Adding or changing tests |
41 | 105 |
|
42 | | -This project follows these code style guidelines: |
43 | | -- **Black** for code formatting (line length: 79 characters) |
44 | | -- **isort** for import sorting |
| 106 | +- **Feature files** — Add or edit `.feature` files in `features/` (e.g. `features/version.feature`). Use standard Gherkin: `Feature`, `Scenario`, `Given`, `When`, `Then`. |
| 107 | +- **Step definitions** — Implement steps in Python under `features/steps/`, typically in a `*_steps.py` file. Use `@given`, `@when`, `@then` from `behave`; step functions receive a `context` argument. |
| 108 | +- Keep scenarios focused and steps reusable. Add or extend scenarios for new behavior rather than skipping BDD. |
| 109 | + |
| 110 | +## Code Style and Quality |
| 111 | + |
| 112 | +Style and linting are enforced via **pre-commit** (Ruff, mypy, Pylint, and other hooks). After `pre-commit install`, these run automatically on each commit. |
| 113 | + |
| 114 | +### Run checks manually |
45 | 115 |
|
46 | | -Pre-commit hooks are installed automatically with `make init` and will run on every commit. You can also run them manually: |
47 | 116 | ```bash |
48 | 117 | pre-commit run --all-files |
49 | 118 | ``` |
50 | 119 |
|
51 | | -### Making Changes |
| 120 | +### What we expect |
52 | 121 |
|
53 | | -1. Create a new branch for your feature or bugfix: |
54 | | - ```bash |
55 | | - git checkout -b feature/your-feature-name |
56 | | - ``` |
| 122 | +- **Formatting** — Ruff format (run via pre-commit or `ruff format`). |
| 123 | +- **Linting** — Ruff check, Pylint, and other hooks must pass. |
| 124 | +- **Types** — Use type hints for public APIs; mypy must pass. |
| 125 | +- **Docstrings** — Public functions, classes, and modules should have docstrings. |
| 126 | +- **Security** — Bandit and Semgrep run in pre-commit; address any reported issues. |
57 | 127 |
|
58 | | -2. Make your changes following the project conventions |
59 | | -3. Add or update tests as needed |
60 | | -4. Ensure all tests pass: `make test` |
61 | | -5. Commit your changes with a clear message |
| 128 | +Fixing pre-commit failures before pushing keeps the history clean and CI green. |
62 | 129 |
|
63 | | -### Submitting Changes |
| 130 | +## Project Structure |
64 | 131 |
|
65 | | -1. Push your branch to your fork: |
66 | | - ```bash |
67 | | - git push origin feature/your-feature-name |
68 | | - ``` |
| 132 | +``` |
| 133 | +timerun/ |
| 134 | +├── timerun.py # Library (single-file by design) |
| 135 | +├── features/ # BDD feature files (Gherkin) — behave convention |
| 136 | +│ ├── __init__.py # Makes features a package for imports |
| 137 | +│ ├── *.feature |
| 138 | +│ ├── environment.py # Optional: hooks (before/after scenario, etc.) |
| 139 | +│ └── steps/ # Step definitions (flat; all .py files loaded) |
| 140 | +│ ├── __init__.py |
| 141 | +│ ├── utils.py # Shared constants and helpers (no step decorators) |
| 142 | +│ ├── common_steps.py # Shared steps used by multiple features |
| 143 | +│ └── *_steps.py # Feature-specific step files |
| 144 | +├── pyproject.toml # Project metadata and config |
| 145 | +├── Makefile # Commands: init, test, clean, help |
| 146 | +├── README.md |
| 147 | +├── CONTRIBUTING.md |
| 148 | +└── LICENSE |
| 149 | +``` |
69 | 150 |
|
70 | | -2. Create a pull request on GitHub with: |
71 | | - - Clear description of the changes |
72 | | - - Reference to any related issues |
73 | | - - Test coverage for new functionality |
| 151 | +- **`timerun.py`** — The only library module; keep it a single file by design. |
| 152 | +- **`features/`** — All executable specs; no separate unit test directory. Layout follows [behave](https://behave.readthedocs.io/) convention: step definitions live under `features/steps/` (flat; subdirectories are not searched). Shared logic lives in `features/steps/utils.py`; shared steps (e.g. metadata, wall-time buffer, exception propagation) in `common_steps.py`. Run behave from the project root so `from features.steps.utils import ...` works. |
74 | 153 |
|
75 | | -## Project Structure |
| 154 | +## Pull Request Process |
76 | 155 |
|
77 | | -- `timerun.py` - Main library code (single file module) |
78 | | -- `tests/` - Test suite |
79 | | -- `pyproject.toml` - Project configuration and dependencies |
80 | | -- `Makefile` - Development commands |
| 156 | +1. **Create a branch** from `main`: |
81 | 157 |
|
82 | | -## Guidelines |
| 158 | + ```bash |
| 159 | + git checkout main |
| 160 | + git pull origin main |
| 161 | + git checkout -b feature/short-description # or fix/short-description |
| 162 | + ``` |
83 | 163 |
|
84 | | -### Code Quality |
| 164 | +2. **Make your changes** — Follow [Code Style and Quality](#code-style-and-quality) and add or update BDD scenarios in `features/` for new or changed behavior. |
85 | 165 |
|
86 | | -- Maintain 100% test coverage for new code |
87 | | -- Follow existing code patterns and conventions |
88 | | -- Add docstrings for all public functions and classes |
89 | | -- Use type hints consistently |
| 166 | +3. **Run the suite and pre-commit**: |
90 | 167 |
|
91 | | -### Testing |
| 168 | + ```bash |
| 169 | + make test |
| 170 | + pre-commit run --all-files |
| 171 | + ``` |
92 | 172 |
|
93 | | -- Write tests for all new functionality |
94 | | -- Use descriptive test names |
95 | | -- Test both success and error cases |
96 | | -- Keep tests focused and independent |
| 173 | +4. **Commit** with clear, concise messages. Optionally use conventional style (e.g. `feat: add X`, `fix: correct Y`). |
97 | 174 |
|
98 | | -### Documentation |
| 175 | +5. **Push** to your fork and open a pull request against `main`: |
99 | 176 |
|
100 | | -- Update docstrings for any API changes |
101 | | -- Add examples for new features |
102 | | -- Update README.md if needed |
| 177 | + ```bash |
| 178 | + git push origin feature/short-description |
| 179 | + ``` |
103 | 180 |
|
104 | | -## Reporting Issues |
| 181 | +6. **Fill out the PR**: |
| 182 | + - Describe what changed and why. |
| 183 | + - Reference any related issues (e.g. "Fixes #123"). |
| 184 | + - Confirm tests pass and, for new behavior, that BDD scenarios were added or updated. |
105 | 185 |
|
106 | | -When reporting bugs or requesting features: |
| 186 | +Maintainers will review and may request changes. Once approved, your PR will be merged. |
107 | 187 |
|
108 | | -1. Check existing issues first |
109 | | -2. Use the issue templates if available |
110 | | -3. Provide clear reproduction steps for bugs |
111 | | -4. Include Python version and environment details |
| 188 | +## Reporting Bugs |
112 | 189 |
|
113 | | -## Questions? |
| 190 | +- **Search** existing issues to avoid duplicates. |
| 191 | +- **Open an issue** with: |
| 192 | + - A short, clear title. |
| 193 | + - Steps to reproduce (code or commands). |
| 194 | + - Expected vs actual behavior. |
| 195 | + - Your environment: OS, Python version (`python --version`), and how you installed TimeRun (pip, editable, etc.). |
114 | 196 |
|
115 | | -Feel free to open an issue for questions about contributing or reach out to the maintainers. |
| 197 | +For small, obvious fixes you may open a PR directly with a short explanation. |
116 | 198 |
|
117 | 199 | ## License |
118 | 200 |
|
119 | | -By contributing to TimeRun, you agree that your contributions will be licensed under the MIT License. |
| 201 | +Contributions are made under the [MIT License](LICENSE). By submitting a pull request, you agree that your contributions will be licensed under the same terms. |
0 commit comments