Skip to content

Commit 6c5ffbf

Browse files
committed
adds docs fixes
1 parent f850b33 commit 6c5ffbf

5 files changed

Lines changed: 356 additions & 5 deletions

File tree

.github/workflows/README.md

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
# CI/CD Workflow Overview
2+
3+
This document provides a comprehensive overview of all GitHub Actions workflows in the ccBitTorrent project.
4+
5+
## Table of Contents
6+
7+
- [Testing & Quality Assurance](#testing--quality-assurance)
8+
- [Build & Packaging](#build--packaging)
9+
- [Release & Deployment](#release--deployment)
10+
11+
---
12+
13+
## Testing & Quality Assurance
14+
15+
### Test Workflow (test.yml)
16+
- **Triggers**: Push/PR to `dev` branch, `workflow_dispatch`
17+
- **Purpose**: Run full test suite with coverage across multiple platforms and Python versions
18+
- **Runs**:
19+
- All tests except compatibility tests (excluded with `-m "not compatibility"`)
20+
- Coverage reporting (XML, HTML, terminal)
21+
- Test matrix: Ubuntu, Windows, macOS × Python 3.8-3.12 (reduced matrix for Windows/macOS)
22+
- **Rationale**:
23+
- Tests run on `dev` branch (development branch), avoiding duplicate runs when merging to main
24+
- Excludes compatibility tests which run separately on schedule/manual trigger
25+
- Windows tests use `shell: bash` to handle line continuation correctly
26+
27+
### CI/CD Pipeline (ci.yml)
28+
- **Triggers**: Push/PR to `main` and `dev` branches
29+
- **Purpose**: Code quality checks (linting and type checking)
30+
- **Runs**:
31+
- **Lint job**: Ruff linting with auto-fix and formatting checks
32+
- **Type-check job**: Ty type checking with concise output
33+
- **Rationale**:
34+
- Ensures code quality before merging
35+
- Runs on both main and dev to catch issues early
36+
- Fast feedback loop for developers
37+
38+
### Compatibility Workflow (compatibility.yml)
39+
- **Triggers**:
40+
- Push to `main` branch
41+
- `workflow_dispatch` (manual)
42+
- **Purpose**: Test compatibility across different environments and Python versions
43+
- **Runs**:
44+
- **docker-test job**: Tests in Docker containers across Python 3.8-3.12 and OS variants (Ubuntu, Debian, Alpine)
45+
- **live-deployment-test job**: Builds package from wheel, tests installation, runs smoke tests (main branch only)
46+
- **compatibility-tests job**: Runs compatibility test suite (network tests, may be flaky)
47+
- **Rationale**:
48+
- Ensures compatibility across different OS environments
49+
- Tests package installation and basic functionality
50+
- Compatibility tests are marked `continue-on-error: true` due to potential network flakiness
51+
52+
### Benchmark Workflow (benchmark.yml)
53+
- **Triggers**:
54+
- Push to `main` branch (when code or performance tests change)
55+
- `workflow_dispatch` (manual)
56+
- **Purpose**: Performance benchmarking and trend tracking
57+
- **Runs**:
58+
- Hash verification benchmark
59+
- Disk I/O benchmark
60+
- Piece assembly benchmark
61+
- Loopback throughput benchmark
62+
- Encryption benchmark
63+
- **Rationale**:
64+
- Tracks performance trends over time
65+
- Runs in `--quick` mode for CI speed
66+
- Automatically commits benchmark results to repository (main branch only)
67+
- Results stored in `docs/reports/benchmarks/`
68+
69+
### Security Workflow (security.yml)
70+
- **Triggers**:
71+
- Push/PR to `main` branch
72+
- Weekly schedule
73+
- `workflow_dispatch` (manual)
74+
- **Purpose**: Security scanning and vulnerability detection
75+
- **Runs**:
76+
- Bandit security scanning (medium severity threshold)
77+
- Safety dependency vulnerability checking
78+
- **Rationale**:
79+
- Regular security audits
80+
- Detects known vulnerabilities in dependencies
81+
- Weekly schedule ensures ongoing security monitoring
82+
83+
---
84+
85+
## Build & Packaging
86+
87+
### Build Workflow (build.yml)
88+
- **Triggers**:
89+
- Push/PR to `main` branch
90+
- Tag push (`v*`)
91+
- `workflow_dispatch` (manual)
92+
- **Purpose**: Build packages and executables
93+
- **Runs**:
94+
- **build-package job**: Builds wheel and source distribution across Ubuntu, Windows, macOS
95+
- **build-windows-exe job**: Builds Windows executable (`bitonic.exe`) using PyInstaller (main branch or tags only)
96+
- **Rationale**:
97+
- Validates package builds on all platforms
98+
- Creates distributable artifacts
99+
- Windows executable only built for releases (main branch or version tags)
100+
101+
### Documentation Workflow (build-documentation.yml)
102+
- **Triggers**: `workflow_dispatch` (manual only)
103+
- **Purpose**: Build documentation for testing and verification
104+
- **Runs**:
105+
- Generate coverage report (for docs embedding)
106+
- Generate Bandit security report (for docs embedding)
107+
- Build documentation using patched build script
108+
- Upload documentation artifacts
109+
- **Rationale**:
110+
- Manual trigger allows testing documentation builds from any branch
111+
- Documentation is automatically published to Read the Docs when changes are pushed
112+
- Coverage and Bandit reports are embedded in documentation
113+
- No GitHub Pages deployment (Read the Docs handles publishing)
114+
115+
---
116+
117+
## Release & Deployment
118+
119+
### Pre-Release Workflow (pre-release.yml)
120+
- **Triggers**:
121+
- Pull request to `main` branch (when version files or CHANGELOG change)
122+
- `workflow_dispatch` (manual)
123+
- **Purpose**: Pre-release validation and checklist reminders
124+
- **Runs**:
125+
- **version-check job**: Verifies version consistency between `pyproject.toml` and `ccbt/__init__.py`
126+
- **release-checklist-reminder job**: Posts release checklist reminder in PR comments
127+
- **Rationale**:
128+
- Catches version inconsistencies before merging
129+
- Ensures CHANGELOG is updated
130+
- Reminds maintainers of release checklist items
131+
132+
### Version Check Workflow (version-check.yml)
133+
- **Triggers**:
134+
- Pull request to `main` branch only (when version files change) - **NOT on PRs to dev**
135+
- Push to `main` or `dev` branches (when version files change)
136+
- Merge group events on `dev` branch
137+
- **Purpose**: Continuous version consistency validation
138+
- **Runs**:
139+
- Extracts version from `pyproject.toml` and `ccbt/__init__.py`
140+
- Verifies version consistency
141+
- Validates semantic versioning format
142+
- Validates branch-specific version rules:
143+
- `main` branch: version must be >= 0.1.0
144+
- `dev` branch: version must be > 0.0.0
145+
- Validates changelog
146+
- **Rationale**:
147+
- Prevents version mismatches from being merged
148+
- Enforces semantic versioning standards
149+
- Branch-specific rules ensure proper versioning strategy
150+
151+
### Release to Main Workflow (release-to-main.yml)
152+
- **Triggers**: `workflow_dispatch` (manual only)
153+
- **Purpose**: Automated release process from dev to main branch
154+
- **Runs**:
155+
- Accepts source branch input (default: `dev`)
156+
- Calculates new version (increments minor version, resets patch to 0)
157+
- Updates version in `pyproject.toml` and `ccbt/__init__.py`
158+
- Verifies version consistency
159+
- Commits version bump to main branch
160+
- Creates and pushes git tag (`v*`)
161+
- **Rationale**:
162+
- Automates the release process
163+
- Ensures version consistency
164+
- Creates tags that trigger release workflow
165+
- Requires `contents: write` permission
166+
167+
### Release Workflow (release.yml)
168+
- **Triggers**:
169+
- Tag push (`v*`)
170+
- `workflow_dispatch` (manual, requires version input)
171+
- **Purpose**: Comprehensive pre-release validation and release creation
172+
- **Runs**:
173+
- **pre-release-checks job**: Version validation, full test suite, linting, type checking, security scans
174+
- **build-docs job**: Documentation build validation
175+
- **create-release job**: Creates GitHub Release with automated release notes
176+
- **Rationale**:
177+
- Ensures all quality gates pass before release
178+
- Comprehensive validation prevents broken releases
179+
- Automated release notes generation
180+
181+
### Publish Dev Branch to PyPI (publish-pypi-dev.yml)
182+
- **Triggers**:
183+
- Push to `dev` branch (when code or version files change)
184+
- `workflow_dispatch` (manual)
185+
- **Purpose**: Publish dev branch versions to PyPI as nightly builds
186+
- **Runs**:
187+
- Validates version for dev branch (must be > 0.0.0)
188+
- Builds package
189+
- Publishes to PyPI using `uv publish`
190+
- Requires `PYPI_API_TOKEN` secret
191+
- **Rationale**:
192+
- Allows users to test latest dev branch features
193+
- Nightly builds for continuous integration testing
194+
- Dev branch versions are marked as pre-release/nightly
195+
196+
### Publish to PyPI (publish-pypi.yml)
197+
- **Triggers**:
198+
- Tag push (`v*`)
199+
- `workflow_dispatch` (manual, requires version input)
200+
- **Purpose**: Publish stable releases to PyPI
201+
- **Runs**:
202+
- Validates version for main branch (must be >= 0.1.0)
203+
- Builds package
204+
- Publishes to PyPI using `uv publish`
205+
- Verifies publication
206+
- Requires `PYPI_API_TOKEN` secret
207+
- **Rationale**:
208+
- Publishes stable releases to PyPI
209+
- Only versions >= 0.1.0 are published (dev versions use separate workflow)
210+
- Verification step ensures package is available
211+
212+
### Deploy Workflow (deploy.yml)
213+
- **Triggers**:
214+
- Release creation (GitHub release)
215+
- `workflow_dispatch` (manual, requires version input)
216+
- **Purpose**: Production deployment to PyPI and GitHub Releases
217+
- **Runs**:
218+
- **deploy-pypi job**:
219+
- Builds package
220+
- Publishes to PyPI using trusted publishing (OIDC)
221+
- Runs in `production` environment
222+
- **create-release-assets job**:
223+
- Downloads Windows executable artifact
224+
- Uploads package files and executable to GitHub Release
225+
- **Rationale**:
226+
- Production deployment with trusted publishing (no tokens needed)
227+
- Creates complete release with all assets
228+
- Environment protection ensures only authorized deployments
229+
230+
---
231+
232+
## Workflow Dependencies
233+
234+
### Typical Release Flow
235+
236+
1. **Development** → Code changes on `dev` branch
237+
2. **Testing**`test.yml` runs on `dev` branch
238+
3. **Version Check**`version-check.yml` validates version consistency
239+
4. **Release to Main**`release-to-main.yml` bumps version and creates tag
240+
5. **Release Validation**`release.yml` runs comprehensive checks
241+
6. **Build**`build.yml` creates packages and executables
242+
7. **Deploy**`deploy.yml` publishes to PyPI and creates GitHub Release
243+
244+
### Documentation Flow
245+
246+
1. **Code Changes** → Documentation source files updated
247+
2. **Manual Build**`build-documentation.yml` can be triggered for testing
248+
3. **Automatic Publish** → Read the Docs automatically builds and publishes when changes are pushed
249+
250+
### Continuous Quality
251+
252+
- **CI Pipeline** (`ci.yml`) runs on every push/PR for fast feedback
253+
- **Version Check** (`version-check.yml`) ensures version consistency
254+
- **Security** (`security.yml`) runs weekly and on main branch changes
255+
- **Compatibility** (`compatibility.yml`) runs weekly and on main branch changes
256+
- **Benchmarks** (`benchmark.yml`) track performance trends
257+
258+
---
259+
260+
## Workflow Permissions
261+
262+
All workflows now use explicit `permissions` blocks following the principle of least privilege. This ensures workflows only have the minimum permissions required.
263+
264+
### Workflows with Write Permissions
265+
266+
- **benchmark.yml**: `contents: write` (to commit benchmark results to repository)
267+
- **release-to-main.yml**: `contents: write` (to commit version bumps and create tags)
268+
- **release.yml** (create-release job): `contents: write` (to create GitHub releases)
269+
- **deploy.yml**:
270+
- `deploy-pypi` job: `id-token: write` (for PyPI trusted publishing via OIDC), `production` environment
271+
- `create-release-assets` job: `contents: write` (to upload release assets)
272+
273+
### Workflows with Read-Only Permissions
274+
275+
All other workflows use read-only permissions:
276+
- `contents: read` - Read repository contents
277+
- `actions: read` - Read workflow run information
278+
- `pull-requests: read` - Read pull request information (for PR-triggered workflows)
279+
280+
This includes: `test.yml`, `ci.yml`, `compatibility.yml`, `build.yml`, `build-documentation.yml`, `security.yml`, `pre-release.yml`, `version-check.yml`, `publish-pypi-dev.yml`, `publish-pypi.yml`
281+
282+
## Secrets Required
283+
284+
- **PYPI_API_TOKEN**: Required for `publish-pypi-dev.yml` and `publish-pypi.yml` (dev branch publishing)
285+
- **Note**: `deploy.yml` uses trusted publishing (OIDC) and does not require PyPI token

.github/workflows/build-documentation.yml

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,66 @@ jobs:
8686
echo "Port conflict check complete"
8787
continue-on-error: true
8888

89+
- name: Ensure report directories exist
90+
run: |
91+
mkdir -p site/reports/htmlcov
92+
mkdir -p docs/reports/bandit
93+
mkdir -p docs/en/reports/bandit
94+
8995
- name: Generate coverage report
9096
run: |
91-
uv run pytest -c dev/pytest.ini tests/ --cov=ccbt --cov-report=html:site/reports/htmlcov
97+
uv run pytest -c dev/pytest.ini tests/ --cov=ccbt --cov-report=html:site/reports/htmlcov || echo "⚠️ Coverage report generation failed, continuing..."
9298
continue-on-error: true
9399

94-
- name: Generate Bandit report
100+
- name: Generate Bandit reports
95101
run: |
96102
uv run python tests/scripts/ensure_bandit_dir.py
97-
uv run bandit -r ccbt/ -f json -o docs/reports/bandit/bandit-report.json --severity-level medium -x tests,benchmarks,dev,dist,docs,htmlcov,site,.venv,.pre-commit-cache,.pre-commit-home,.pytest_cache,.ruff_cache,.hypothesis,.github,.ccbt,.cursor,.benchmarks
103+
# Generate main bandit report
104+
uv run bandit -r ccbt/ -f json -o docs/reports/bandit/bandit-report.json --severity-level medium -x tests,benchmarks,dev,dist,docs,htmlcov,site,.venv,.pre-commit-cache,.pre-commit-home,.pytest_cache,.ruff_cache,.hypothesis,.github,.ccbt,.cursor,.benchmarks || echo "⚠️ Bandit report generation failed"
105+
# Generate all severity levels report
106+
uv run bandit -r ccbt/ -f json -o docs/reports/bandit/bandit-report-all.json --severity-level all -x tests,benchmarks,dev,dist,docs,htmlcov,site,.venv,.pre-commit-cache,.pre-commit-home,.pytest_cache,.ruff_cache,.hypothesis,.github,.ccbt,.cursor,.benchmarks || echo "⚠️ Bandit all report generation failed"
98107
continue-on-error: true
99108

109+
- name: Ensure report files exist in documentation location
110+
run: |
111+
# Ensure coverage directory has at least an index file (even if empty)
112+
mkdir -p site/reports/htmlcov
113+
if [ ! -f site/reports/htmlcov/index.html ]; then
114+
echo '<html><body><h1>Coverage Report</h1><p>Coverage report not available. Run tests to generate coverage data.</p></body></html>' > site/reports/htmlcov/index.html
115+
fi
116+
117+
# Ensure bandit reports exist in documentation location (docs/en/reports/bandit/)
118+
mkdir -p docs/en/reports/bandit
119+
120+
# Copy or create bandit-report.json
121+
if [ -f docs/reports/bandit/bandit-report.json ]; then
122+
cp docs/reports/bandit/bandit-report.json docs/en/reports/bandit/bandit-report.json
123+
else
124+
echo '{"generated_at": "N/A", "metrics": {}, "results": []}' > docs/en/reports/bandit/bandit-report.json
125+
fi
126+
127+
# Copy or create bandit-report-all.json
128+
if [ -f docs/reports/bandit/bandit-report-all.json ]; then
129+
cp docs/reports/bandit/bandit-report-all.json docs/en/reports/bandit/bandit-report-all.json
130+
else
131+
echo '{"generated_at": "N/A", "metrics": {}, "results": []}' > docs/en/reports/bandit/bandit-report-all.json
132+
fi
133+
134+
# Create placeholder for upnp-check if it doesn't exist
135+
if [ ! -f docs/en/reports/bandit/bandit-upnp-check.json ]; then
136+
echo '{"generated_at": "N/A", "metrics": {}, "results": []}' > docs/en/reports/bandit/bandit-upnp-check.json
137+
fi
138+
139+
echo "✅ All report files ensured in documentation location"
140+
100141
- name: Build documentation
101142
run: |
102143
# Use the patched build script which includes all necessary patches:
103144
# - i18n plugin fixes (alternates attribute, Locale validation for 'arc')
104145
# - git-revision-date-localized plugin fix for 'arc' locale
105146
# - All patches are applied before mkdocs is imported
106147
# Set MKDOCS_STRICT=true to enable strict mode in CI
148+
# Reports are ensured to exist in previous step to avoid warnings
107149
MKDOCS_STRICT=true uv run python dev/build_docs_patched_clean.py
108150
109151
- name: Upload documentation artifact

dev/build_docs_patched_clean.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,31 @@ def patched_reconfigure_files(self, files, mkdocs_config):
138138
# Now import and run mkdocs in the same process
139139
if __name__ == '__main__':
140140
import sys
141+
import os
142+
import logging
141143
from mkdocs.__main__ import cli
142144

145+
# Patch mkdocs logger to filter out autorefs warnings about multiple primary URLs
146+
# These are expected with i18n plugin when same objects are documented in multiple languages
147+
class AutorefsWarningFilter(logging.Filter):
148+
"""Filter out autorefs warnings about multiple primary URLs (expected with i18n)."""
149+
def filter(self, record):
150+
# Filter out warnings about multiple primary URLs from mkdocs-autorefs
151+
if 'Multiple primary URLs found' in record.getMessage():
152+
return False
153+
return True
154+
155+
# Apply filter to mkdocs logger
156+
mkdocs_logger = logging.getLogger('mkdocs')
157+
autorefs_filter = AutorefsWarningFilter()
158+
mkdocs_logger.addFilter(autorefs_filter)
159+
160+
# Also filter mkdocs_autorefs logger if it exists
161+
autorefs_logger = logging.getLogger('mkdocs_autorefs')
162+
autorefs_logger.addFilter(autorefs_filter)
163+
143164
# Use --strict only if explicitly requested via environment variable
144165
# Otherwise, respect strict: false in mkdocs.yml
145-
import os
146166
strict_flag = ['--strict'] if os.getenv('MKDOCS_STRICT', '').lower() == 'true' else []
147167
sys.argv = ['mkdocs', 'build'] + strict_flag + ['-f', 'dev/mkdocs.yml']
148168
cli()

dev/mkdocs.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ plugins:
112112
# Note: 'arc' is ISO-639-2 (three-letter), not ISO-639-1. The build script patches
113113
# Locale.run_validation to allow 'arc' as a special case. Also patches
114114
# git-revision-date-localized plugin to fall back to 'en' for date formatting.
115+
- autorefs:
116+
# Note: Multiple primary URLs warnings are expected with i18n plugin
117+
# The same Python objects are documented in multiple languages (en, es, etc.)
118+
# Warnings are suppressed via logger filter in build_docs_patched_clean.py
115119
- mkdocstrings:
116120
handlers:
117121
python:

0 commit comments

Comments
 (0)