Skip to content

Commit

Permalink
Enhance find_unreleased_changelog_items action to check for merged PRs (
Browse files Browse the repository at this point in the history
#74)

* build: Update license identifier for this repo

* feat: Add an additional check for merged PRs to the action that finds unreleased changelog items.

Also, Update the cron for releasing a package to once per month, instead of once per week.

* chore: Update contributor_setup.py to quote paths to avoid shell splitting
  • Loading branch information
nfelt14 authored Sep 9, 2024
1 parent 55821c1 commit 8902300
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 19 deletions.
5 changes: 3 additions & 2 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
"packageRules": [
{
"additionalBranchPrefix": "{{#if (equals manager 'github-actions')}}gh-actions{{else}}{{categories}}{{/if}}-deps/",
"description": "Set the branch prefix for all updates",
"description": "Set the branch prefix and minimum release age for all updates",
"matchPackageNames": [
"*"
]
],
"minimumReleaseAge": "5 days"
},
{
"addLabels": [
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/_reusable-sbom-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
with:
python-version-file: pyproject.toml
- name: Create lockfile
- name: Create lockfile and install dependencies
run: |
pip install poetry
poetry lock
poetry install
- name: Create SBOM
uses: anchore/sbom-action@61119d458adab75f756bc0b9e4bde25725f86a7a # v0.17.2
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/package-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
major for non-backward compatible changes.
options: [patch, minor, major]
schedule:
- cron: 0 16 * * 2
- cron: 0 16 1-7 * 2 # Run at 16:00 UTC on the first Tuesday of each month
concurrency:
group: pypi
jobs:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
fi
test-find_unreleased_changelog_items:
runs-on: ubuntu-latest
env:
UNIT_TESTING_FIND_UNRELEASED_CHANGELOG_ITEMS_ACTION: true
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Overwrite CHANGELOG.md with dummy data
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Things to be included in the next release go here.
- Changed the `_reusable-update-python-and-pre-commit-dependencies.yml` workflow to no longer only work on PRs from Dependabot, users will now need to apply any conditional login in the calling workflow.
- Updated the `_reusable-update-python-and-pre-commit-dependencies.yml` workflow to allow using [`renovate`](https://docs.renovatebot.com/) instead of Dependabot to update dependencies.
- Updated the `_reusable-package-release.yml` workflow to not show as failed if the `bump-release` deployment is rejected by a reviewer.
- Updated the `find_unreleased_changelog_items` action to check for merged PRs since the last release and fail if none are found.

---

Expand Down
20 changes: 12 additions & 8 deletions actions/find_unreleased_changelog_items/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def main() -> None:
# Set the filepaths for the template files
template_changelog_filepath = pathlib.Path(filepath_for_previous_changelog)
template_release_notes_filepath = pathlib.Path(filepath_for_previous_release_notes)
root_dir = pathlib.Path.cwd()

release_notes_content = ""
found_entries = False
Expand Down Expand Up @@ -109,6 +110,17 @@ def main() -> None:
msg = f"No unreleased entries were found in {CHANGELOG_FILE}."
raise SystemExit(msg)

# Check for merged PRs since the last release
run_cmd_in_subprocess(
f'git config --global --add safe.directory "{root_dir.resolve().as_posix()}"'
)
commit_messages = get_commit_messages(since_tag=get_latest_tag())
pr_regex = re.compile(r"\(#\d+\)$")
pr_descriptions = "\n".join([f"- {msg}" for msg in commit_messages if pr_regex.search(msg)])
if not pr_descriptions and not os.getenv("UNIT_TESTING_FIND_UNRELEASED_CHANGELOG_ITEMS_ACTION"):
msg = "No PRs have been merged since the last release."
raise SystemExit(msg)

# Copy the files to the correct location
shutil.copy(CHANGELOG_FILE, template_changelog_filepath)
with template_release_notes_filepath.open("w", encoding="utf-8") as template_release_notes:
Expand All @@ -117,14 +129,6 @@ def main() -> None:
# If running in GitHub Actions, and the release_level is set, send the release level and
# incoming changes to the GitHub Summary
if release_level:
root_dir = pathlib.Path.cwd()
run_cmd_in_subprocess(
f'git config --global --add safe.directory "{root_dir.resolve().as_posix()}"'
)
commit_messages = get_commit_messages(since_tag=get_latest_tag())

pr_regex = re.compile(r"\(#\d+\)$")
pr_descriptions = "\n".join([f"- {msg}" for msg in commit_messages if pr_regex.search(msg)])
summary_contents = (
f"## Workflow Inputs\n- release-level: {release_level}\n"
f"## PRs Merged Since Last Release\n{pr_descriptions}\n"
Expand Down
9 changes: 7 additions & 2 deletions actions/find_unreleased_changelog_items/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

This action will parse the repository's `CHANGELOG.md` file to determine if
there are any unreleased items. It will fail if it cannot find any unreleased
items, as this means that the package is not ready for a new release.
items, as this means that the package is not ready for a new release. This action will also
fail if it cannot find any merged PRs since the last release, as this also means that the
package is not ready for a new release.

This action will populate two files in the
[`python-semantic-release` templates directory](https://python-semantic-release.readthedocs.io/en/latest/configuration.html#config-changelog-template-dir).
Expand All @@ -13,7 +15,7 @@ will be used to fill in the GitHub Release Notes.

> [!IMPORTANT]
> This action requires that the `pyproject.toml` and `CHANGELOG.md` files exist in the
> current working directory.
> current working directory and that all tags are fetched from the remote repository.
> [!IMPORTANT]
> This action requires the `CHANGELOG.md` file to be in a format that is based on
Expand Down Expand Up @@ -48,6 +50,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
fetch-tags: true
- uses: tektronix/python-package-ci-cd/actions/[email protected]
with:
release-level: ${{ inputs.release-level }} # optional
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ wrap-descriptions = 100
wrap-summaries = 0

[tool.poetry]
license = "Apache-2.0"
package-mode = false
version = "1.2.0"

Expand Down
10 changes: 6 additions & 4 deletions scripts/contributor_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def create_virtual_environment(virtual_env_dir: str | os.PathLike[str]) -> None:
virtual_env_dir: The directory where the virtual environment should be created
"""
print(f"\nCreating virtualenv located at '{virtual_env_dir}'")
_run_cmd_in_subprocess(f"{sys.executable} -m venv {virtual_env_dir} --clear")
_run_cmd_in_subprocess(f'"{sys.executable}" -m venv "{virtual_env_dir}" --clear')


def _run_cmd_in_subprocess(command: str) -> None:
Expand Down Expand Up @@ -78,9 +78,11 @@ def main() -> None:
)
python_executable = files[0]
commands_to_send = (
f"{python_executable} -m pip install -U pip wheel poetry",
f"{python_executable} -m poetry install",
f"{python_executable} -m pre_commit install --install-hooks",
f'"{python_executable}" -m pip install -U pip wheel poetry',
f'"{python_executable}" -m poetry install',
f'"{python_executable}" -m nodeenv --python-virtualenv --clean-src',
f'"{python_executable}" -m pre_commit install --install-hooks',
f'"{python_executable}" -m tox -e tests',
)
for command in commands_to_send:
_run_cmd_in_subprocess(command)
Expand Down
25 changes: 25 additions & 0 deletions tests/test_find_unreleased_changelog_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,31 @@ def test_main_no_unreleased_entries(
main()


def test_main_with_no_merged_prs(
mock_env_vars: None, # noqa: ARG001
mock_changelog_file: Path, # noqa: ARG001
fake_process: FakeProcess,
) -> None:
"""Test the main function when unreleased entries are found.
Args:
mock_env_vars: Mock the environment variables.
mock_changelog_file: Mock the changelog file.
fake_process: The fake_process fixture, used to register commands that will be mocked.
"""
fake_process.register( # pyright: ignore[reportUnknownMemberType]
shlex.split("git log v1.0.0..HEAD --pretty=format:%s"),
stdout=b"Initial commit\n",
)
with fake_process.context() as nested_process:
nested_process.register( # pyright: ignore[reportUnknownMemberType]
shlex.split("git log v1.0.0..HEAD --pretty=format:%s"),
stdout=b"Initial commit\n",
)
with pytest.raises(SystemExit, match="No PRs have been merged since the last release\\."):
main()


def test_main_with_unreleased_entries(
mock_env_vars: None, # noqa: ARG001
mock_changelog_file: Path,
Expand Down

0 comments on commit 8902300

Please sign in to comment.