- Get Started
- Run Static Code Analysis
- Run Black Tool Locally
- Run mypy Tool Locally
- Running Unit Test
- Running Integration Tests
- Code Coverage
- Run Action Locally
- Branch Naming Convention (PID:H-1)
Clone the repository and navigate to the project directory:
git clone https://github.com/AbsaOSS/generate-release-notes.git
cd generate-release-notesInstall the dependencies:
pip install -r requirements.txt
export PYTHONPATH=<your path>/generate-release-notes/srcThis project uses the Pylint tool for static code analysis. Pylint analyzes your code without actually running it. It checks for errors, enforces coding standards, looks for code smells, etc.
Pylint displays a global evaluation score for the code, rated out of a maximum score of 10.0. We aim to keep our code quality above 9.5.
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txtThis command will also install a Pylint tool, since it is listed in the project requirements.
Run Pylint on all files currently tracked by Git in the project.
pylint --ignore-paths='^tests/.*' $(git ls-files '*.py')To run Pylint on a specific file, follow the pattern pylint <path_to_file>/<name_of_file>.py.
Example:
pylint release-notes-generator/generator.pyThis project uses the Black tool for code formatting. Black aims for consistency, generality, readability, and reducing git diffs. The coding style used can be viewed as a strict subset of PEP 8.
The project root file pyproject.toml defines the Black tool configuration.
In this project, we are accepting a line length of 120 characters.
Follow these steps to format your code with Black locally:
From the terminal in the root of the project, run the following command:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtThis command will also install a Black tool, since it is listed in the project requirements.
Run Black on all files currently tracked by Git in the project.
black $(git ls-files '*.py')To run Black on a specific file, follow the pattern black <path_to_file>/<name_of_file>.py.
Example:
black release_notes_generator/generator.pyThis is the console's expected output example after running the tool:
All done! ✨ 🍰 ✨
1 file reformatted.
This project uses the my[py] tool, a static type checker for Python.
Type checkers help ensure that you correctly use variables and functions in your code. With mypy, add type hints (PEP 484) to your Python programs, and mypy will warn you when you use those types incorrectly. my[py] configuration is in
pyproject.tomlfile.
Follow these steps to format your code with my[py] locally:
Run my[py] on all files in the project.
mypy .To run my[py] check on a specific file, follow the pattern mypy <path_to_file>/<name_of_file>.py --check-untyped-defs.
Example:
mypy living_documentation_regime/living_documentation_generator.pyUnit tests are written using pytest. To run the tests, use the following command:
pytest tests/unitThis will execute all tests located in the tests/unit directory.
The integration suite exercises the full pipeline from main.run() to final markdown output without reaching the GitHub API.
Offline tests (under tests/integration/) replace the GitHub API layer with mocks and run in CI on every PR — no token required, fully deterministic.
Live tests (under tests/integration/live/) call the real GitHub API against the AbsaOSS/generate-release-notes repository. Run these manually to verify network-dependent behaviour such as BulkSubIssueCollector, or to confirm that API changes have not broken the integration. They are skipped in CI on fork PRs where the token is unavailable.
Each test calls main.run() directly with INPUT_* environment variables. The GitHub API layer is replaced by mocks; DataMiner.mine_data() is patched to return a hand-crafted MinedData. All other pipeline components — FilterByRelease, DefaultRecordFactory, ReleaseNotesBuilder, CustomChapters, and ServiceChapters — execute as real code.
| Component | Location | Role |
|---|---|---|
| Fixture factories | conftest.py |
make_issue, make_pr, make_commit, make_repo, make_release — typed mocks with minimal required attributes |
build_mined_data() |
helpers.py |
Assembles a MinedData from fixture objects for injection into the pipeline |
capture_run() |
helpers.py |
Sets env vars, calls main.run(), parses the GitHub Actions output format back to a plain string |
| Golden snapshot | fixtures/test_full_pipeline_snapshot.md |
Byte-for-byte reference output for T-INT-01 |
Runs all integration tests except the live suite; safe to run locally and in CI.
pytest tests/integration/ --ignore=tests/integration/live -vRe-runs the full-pipeline snapshot test and overwrites fixtures/test_full_pipeline_snapshot.md with the current output. Use this after intentional output changes to update the baseline.
WRITE_SNAPSHOTS=1 pytest tests/integration/test_snapshot.py::test_full_pipeline_snapshotQueries the real GitHub API against AbsaOSS/generate-release-notes to verify BulkSubIssueCollector. Skipped in CI on fork PRs.
pytest tests/integration/live/ -vCode coverage is collected using the pytest-cov coverage tool. To run the tests and collect coverage information, use the following command:
pytest --cov=. -v tests/unit --cov-fail-under=80 # Check coverage threshold
pytest --cov=. -v tests/unit --cov-fail-under=80 --cov-report=html # Generate HTML reportThis will execute all tests in the tests directory and generate a code coverage report.
See the coverage report on the path:
open htmlcov/index.htmlCreate run_locally.sh file and place it in the project root.
#!/bin/bash
# Set environment variables based on the action inputs
export INPUT_TAG_NAME="v0.2.0"
export INPUT_CHAPTERS='[
{ title: No entry 🚫, label: duplicate },
{ title: Breaking Changes 💥, label: breaking-change },
{ title: New Features 🎉, label: enhancement },
{ title: New Features 🎉, label: feature },
{ title: Bugfixes 🛠, label: bug },
{ title: Infrastructure ⚙️, label: infrastructure },
{ title: Silent-live 🤫, label: silent-live },
{ title: Documentation 📜, label: documentation }
]'
export INPUT_WARNINGS="true"
export INPUT_PUBLISHED_AT="true"
export INPUT_SKIP_RELEASE_NOTES_LABELS="ignore-in-release"
export INPUT_PRINT_EMPTY_CHAPTERS="true"
export INPUT_VERBOSE="true"
# CI in-built variables
export GITHUB_REPOSITORY="< owner >/< repo-name >"
export INPUT_GITHUB_TOKEN=$(printenv <your-env-token-var>)
PROJECT_ROOT="$(pwd)"
export PYTHONPATH="${PYTHONPATH}:${PROJECT_ROOT}"
# Debugging statements
echo "PYTHONPATH: ${PYTHONPATH}"
echo "Current working directory: ${PROJECT_ROOT}"
# Run the Python script
python3 ./<path-to-action-project-root>/main.pyAll work branches MUST use an allowed prefix followed by a concise kebab-case descriptor (optional numeric ID): Allowed prefixes:
- feature/ : new functionality & enhancements
- fix/ : bug fixes / defect resolutions
- docs/ : documentation-only updates
- chore/ : maintenance, CI, dependency bumps, non-behavioral refactors Examples:
- feature/add-hierarchy-support
- fix/456-null-title-parsing
- docs/update-readme-quickstart
- chore/upgrade-pygithub Rules:
- Prefix mandatory; rename non-compliant branches before PR (
git branch -m feature/<new-name>etc.). - Descriptor lowercase kebab-case; hyphens only; avoid vague terms (
update,changes). - Align scope: a docs-only PR MUST use docs/ prefix, not feature/. Verification Tip:
git rev-parse --abbrev-ref HEAD | grep -E '^(feature|fix|docs|chore)/' || echo 'Branch naming violation (expected allowed prefix)'Future possible prefixes (not enforced yet): refactor/, perf/.