Feat/pygithub migration and announcements by lilfetz22 · Pull Request #1436 · python-semantic-release/python-semantic-release
and others added 26 commits
November 2, 2025 14:24Removed test functions that tested requests implementation details now handled by PyGithub: - test_create_release_fails - test_should_create_release_using_token_or_netrc - test_edit_release_notes_succeeds - test_edit_release_notes_fails - test_get_release_id_by_tag - test_asset_upload_url - test_upload_release_asset_succeeds - test_upload_release_asset_fails - test_request_has_no_auth_header_if_no_token_or_netrc These behaviors are now covered by test_github_pygithub.py.
Implemented post_comment(), check_issue_state(), and add_labels_to_issue()
methods using PyGithub Issue API. Added comprehensive test coverage with
8 test cases covering success and exception paths.
- post_comment(issue_id, body): Posts comment to issue/PR, returns comment ID
- check_issue_state(issue_id): Returns issue state ('open' or 'closed')
- add_labels_to_issue(issue_id, labels): Adds labels to issue/PR
All methods:
- Use PyGithub's repo.get_issue() and Issue methods
- Have proper error handling (GithubException UnexpectedResponse)
- Include debug and info logging with @logged_function decorator
- Support both issues and pull requests (same API)
Test coverage in test_github_pygithub.py:
- TestGithubPostComment: 2 tests (success, exception)
- TestGithubCheckIssueState: 3 tests (open, closed, exception)
- TestGithubAddLabelsToIssue: 3 tests (multiple labels, single label, exception)
These methods enable release announcement functionality for closed issues
and merged PRs using the announcement templates in
src/semantic_release/data/templates/conventional/md/
- Add _post_release_announcements() helper to process linked issues/PRs - Extract linked issues from ParsedCommit.linked_issues tuple - Distinguish PRs using commit.linked_merge_request field - Render .pr_publish_announcement.md.j2 for PRs - Render .issue_resolution_announcement.md.j2 for issues - Post comments via hvcs_client.post_comment() - Add 'released' label to all announced issues/PRs - Implement deduplication to prevent duplicate comments - Use best-effort error handling (log warnings, continue processing) - Respect noop mode and only run for Github HVCS - Pass version and release_notes to announcement templates Integration point: After successful hvcs_client.create_release() in version() command, before final exception handling. This ensures announcements only happen after the release is successfully created on the VCS. Breaking Change: None - backward compatible, announcements are optional
Templates expect 'release.version' not just 'version' string. Update _post_announcement_to_issue to pass release object matching the template expectations in .pr_publish_announcement.md.j2 and .issue_resolution_announcement.md.j2
- Add type: ignore[misc, valid-type] for click.MultiCommand base class - Change runtime parameter type from CliContextObj to RuntimeContext - Change release parameter type from dict to Release TypedDict - Add proper type checking imports for Release and RuntimeContext All mypy checks now pass (58 source files checked).
…ncements - Convert issue_id string to int before calling HVCS methods - Use ReleaseNotesContext.bind_to_environment to inject required Jinja2 filters (create_release_url, etc.) into the announcement template context - Prevent template rendering errors during release - Add ValueError handling for invalid issue IDs - Remove unused release_notes parameter from announcement functions
The markdown macros file defined a macro named 'format_link' but the .release_notes.md.j2 and other templates were importing 'format_link_reference'. Renamed 'format_link' to 'format_link_reference' in macros.md.j2 to match the expected import name, aligning with the reStructuredText template pattern.
Updates to support the PyGithub client integration:
1. Enhanced post_mocker fixture in tests/e2e/conftest.py:
- Added mock for GET requests to support PyGithub's lazy-loaded
repository access when creating releases
- Created PostOnlyMocker wrapper to filter call_count and last_request
to POST-only requests, maintaining test compatibility
2. Updated test fixture in tests/fixtures/git_repo.py:
- Added PyPI Registry section to generated release notes that matches
the new template output
- Properly handles line endings to match template structure
These changes allow the e2e test to work with the PyGithub client which
requires repository metadata from the GitHub API before creating releases.
…generated config The generated config previously included both changelog.changelog_file (deprecated) and changelog.default_templates.changelog_file, causing duplicate entries and spurious deprecation warnings. Exclude changelog.changelog_file from RawConfig().model_dump output so generated defaults only include default_templates.changelog_file. No runtime behavior change; only affects generated config output.
… set Avoid printing the deprecation warning during default configuration generation by returning early when `changelog_file` is empty. The warning is still emitted when a user explicitly sets the deprecated option.
…hangelog_file Update the `raw_config_dict` fixture to exclude `changelog.changelog_file` when producing the expected model dump. This mirrors the change in `generate-config` which omits the deprecated option from generated defaults, preventing spurious deprecation warnings during test runs.
… env-clearing test - Update default TOML test to exclude deprecated `changelog.changelog_file` from the expected model dump so it matches `generate-config` output changes. - Make `test_git_remote_url_w_insteadof_alias` robust on Windows by preserving critical system environment variables (e.g., PATH, SYSTEMROOT, PATHEXT, TEMP, TMP) when clearing the rest of `os.environ`, so subprocess calls (like `git`) continue to be discoverable during the test.
…l debugging Include the full test run log to aid local debugging and CI triage; intended for developer reference only.
…d without colon) Clarify that parsers accept both Git Trailer format with a colon (e.g., 'Closes: python-semantic-release#123') and the more casual format without a colon (e.g., 'Closes python-semantic-release#123'). Added examples to illustrate both forms and various list separators. This updates the user-facing docs to reduce confusion and match common VCS behavior (GitHub/GitLab).
…e/PR announcements Previously announcement rendering always bound to the user's template environment which failed when an embedded default template (e.g., .issue_resolution_announcement.md.j2) was expected. Prefer the user-provided template if present, otherwise fall back to the embedded default conventional markdown templates. Add logic to resolve and bind the default template directory and use the existing ReleaseNotesContext environment for rendering.
Make the issue footer regex accept both 'Closes python-semantic-release#123' and 'Closes: python-semantic-release#123' by making the colon optional and allowing whitespace. This aligns Angular parser behavior with GitHub/GitLab conventions and reduces confusing failures when users omit the colon.
…dling - Merge provided env with current environment to preserve PATH and other vars - Resolve shell executable using shutil.which() and log useful debug messages - Use resolved shell_path when running subprocesses and pass merged env - Handle FileNotFoundError in �uild_distributions and raise BuildDistributionsError - Adjust default PATH to be None to better reflect missing values - Reorder and tidy imports, and improve template env binding formatting
… compat - Normalize CRLF/LF differences in assertions to avoid Windows failures - Strip trailing whitespace where appropriate to reduce platform-dependent flakes
Introduce boolean flag that will drive rendering of a PyPI registry link in the default release notes template. Default is False to preserve existing behaviour.
…notes Add new argument to the public helper and internal call site so callers can request the PyPI link block. This matches the newly-added context field. Default value remains False.
Tighten the linked issue regex to only match valid git footer syntax, requiring a colon separator after the keyword. Bare patterns without a colon were incorrectly recognized as linked issues, causing false positives.
Apply the same regex tightening as the conventional parser so scipy no longer treats bare closure keywords as linked issues. This prevents spurious matches and aligns behaviour across parsers.
…ws resource exhaustion Refactor deep_copy_commit to skip lazy-loaded attributes like tree and gpgsig which previously spawned git cat-file subprocesses. Add detailed comments explaining the WinError 1450/1455 issue and suppress OSError alongside ValueError. This mitigates failures in long Windows test runs.
Wrap the previously unconditional PyPI registry block with a Jinja2 check on include_pypi_link. This allows users to opt-in and keeps default templates compatible with existing expectations.
Provides a default 'master' worker_id so repo-building fixtures don't fail in single-process runs. pytest-xdist will override this when used.
Use PYTEST_XDIST_WORKER for worker detection so the per-repo cache lock is actually enabled during parallel test runs. Persist cached repo metadata to shared JSON files in .pytest_cache/d/psr-cached-repos/repo-data with atomic replace, allowing workers to observe cache state consistently. Hold the per-repo lock through cache copy operations and release it in a finally block to prevent mid-copy delete/rebuild races that produced FileNotFoundError and GitCommandError failures.
Implement _PostOnlyMocker.reset_mock() to clear the wrapper's internal _post_list state in addition to delegating to requests-mock behavior. Without clearing _post_list, call_count and last_request assertions can observe stale POST requests from previous CLI invocations in the same test, causing false failures.
Extend GenerateDefaultReleaseNotesFromDefFn and generate_default_release_notes_from_def() with an include_pypi_link flag defaulting to False. Only append the PyPI artifacts section when include_pypi_link is enabled, matching changelog context defaults and preventing release note expectation mismatches in e2e assertions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters