diff --git a/.ci/scripts/validate_commit_message.py b/.ci/scripts/validate_commit_message.py old mode 100755 new mode 100644 index 6f0ff23..a4dc900 --- a/.ci/scripts/validate_commit_message.py +++ b/.ci/scripts/validate_commit_message.py @@ -1,66 +1,31 @@ -# WARNING: DO NOT EDIT! -# -# This file was generated by plugin_template, and is managed by it. Please use -# './plugin-template --github pulp_npm' to update this file. -# -# For more info visit https://github.com/pulp/plugin_template +# This file is managed by the plugin template. +# Do not edit. import os import re import subprocess import sys import tomllib +import yaml from pathlib import Path from github import Github -with open("pyproject.toml", "rb") as fp: - PYPROJECT_TOML = tomllib.load(fp) -KEYWORDS = ["fixes", "closes"] -BLOCKING_REGEX = [ - r"^DRAFT", - r"^WIP", - r"^NOMERGE", - r"^DO\s*NOT\s*MERGE", - r"^EXPERIMENT", - r"^FIXUP", - r"^fixup!", # This is created by 'git commit --fixup' - r"Apply suggestions from code review", # This usually comes from GitHub -] -try: - CHANGELOG_EXTS = [ - f".{item['directory']}" for item in PYPROJECT_TOML["tool"]["towncrier"]["type"] - ] -except KeyError: - CHANGELOG_EXTS = [".feature", ".bugfix", ".doc", ".removal", ".misc"] -NOISSUE_MARKER = "[noissue]" - -sha = sys.argv[1] -message = subprocess.check_output(["git", "log", "--format=%B", "-n 1", sha]).decode("utf-8") - -if NOISSUE_MARKER in message: - sys.exit(f"Do not add '{NOISSUE_MARKER}' in the commit message.") - -blocking_matches = [m for m in (re.match(pattern, message) for pattern in BLOCKING_REGEX) if m] -if blocking_matches: - print("Found these phrases in the commit message:") - for m in blocking_matches: - print(" - " + m.group(0)) - sys.exit("This PR is not ready for consumption.") -g = Github(os.environ.get("GITHUB_TOKEN")) -repo = g.get_repo("pulp/pulp_npm") - - -def check_status(issue): +def check_status(issue, repo, cherry_pick): gi = repo.get_issue(int(issue)) if gi.pull_request: sys.exit(f"Error: issue #{issue} is a pull request.") - if gi.closed_at: + if gi.closed_at and not cherry_pick: + print("Make sure to use 'git cherry-pick -x' when backporting a change.") + print( + "If a backport of a change requires a significant amount of rewriting, " + "consider creating a new issue." + ) sys.exit(f"Error: issue #{issue} is closed.") -def check_changelog(issue): +def check_changelog(issue, CHANGELOG_EXTS): matches = list(Path("CHANGES").rglob(f"{issue}.*")) if len(matches) < 1: @@ -70,18 +35,63 @@ def check_changelog(issue): sys.exit(f"Invalid extension for changelog entry '{match}'.") -print("Checking commit message for {sha}.".format(sha=sha[0:7])) +def main() -> None: + TEMPLATE_CONFIG = yaml.safe_load(Path("template_config.yml").read_text()) + GITHUB_ORG = TEMPLATE_CONFIG["github_org"] + PLUGIN_NAME = TEMPLATE_CONFIG["plugin_name"] + + with Path("pyproject.toml").open("rb") as _fp: + PYPROJECT_TOML = tomllib.load(_fp) + KEYWORDS = ["fixes", "closes"] + BLOCKING_REGEX = [ + r"^DRAFT", + r"^WIP", + r"^NOMERGE", + r"^DO\s*NOT\s*MERGE", + r"^EXPERIMENT", + r"^FIXUP", + r"^fixup!", # This is created by 'git commit --fixup' + r"Apply suggestions from code review", # This usually comes from GitHub + ] + try: + CHANGELOG_EXTS = [ + f".{item['directory']}" for item in PYPROJECT_TOML["tool"]["towncrier"]["type"] + ] + except KeyError: + CHANGELOG_EXTS = [".feature", ".bugfix", ".doc", ".removal", ".misc"] + NOISSUE_MARKER = "[noissue]" + + sha = sys.argv[1] + message = subprocess.check_output(["git", "log", "--format=%B", "-n 1", sha]).decode("utf-8") + + if NOISSUE_MARKER in message: + sys.exit(f"Do not add '{NOISSUE_MARKER}' in the commit message.") + + blocking_matches = [m for m in (re.match(pattern, message) for pattern in BLOCKING_REGEX) if m] + if blocking_matches: + print("Found these phrases in the commit message:") + for m in blocking_matches: + print(" - " + m.group(0)) + sys.exit("This PR is not ready for consumption.") + + g = Github(os.environ.get("GITHUB_TOKEN")) + repo = g.get_repo(f"{GITHUB_ORG}/{PLUGIN_NAME}") + + print("Checking commit message for {sha}.".format(sha=sha[0:7])) + + # validate the issue attached to the commit + issue_regex = r"(?:{keywords})[\s:]+#(\d+)".format(keywords="|".join(KEYWORDS)) + issues = re.findall(issue_regex, message, re.IGNORECASE) + cherry_pick_regex = r"^\s*\(cherry picked from commit [0-9a-f]*\)\s*$" + cherry_pick = re.search(cherry_pick_regex, message, re.MULTILINE) + + if issues: + for issue in issues: + check_status(issue, repo, cherry_pick) + check_changelog(issue, CHANGELOG_EXTS) -# validate the issue attached to the commit -issue_regex = r"(?:{keywords})[\s:]+#(\d+)".format(keywords=("|").join(KEYWORDS)) -issues = re.findall(issue_regex, message, re.IGNORECASE) -cherry_pick_regex = r"^\s*\(cherry picked from commit [0-9a-f]*\)\s*$" -cherry_pick = re.search(cherry_pick_regex, message, re.MULTILINE) + print("Commit message for {sha} passed.".format(sha=sha[0:7])) -if issues: - for issue in issues: - if not cherry_pick: - check_status(issue) - check_changelog(issue) -print("Commit message for {sha} passed.".format(sha=sha[0:7])) +if __name__ == "__main__": + main() diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02bafe7..d059eba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: - name: "Install python dependencies" run: | echo ::group::PYDEPS - pip install requests pygithub + pip install requests pygithub pyyaml echo ::endgroup:: - name: "Check commit message" if: github.event_name == 'pull_request' diff --git a/.github/workflows/scripts/script.sh b/.github/workflows/scripts/script.sh index 87faf17..e02e799 100755 --- a/.github/workflows/scripts/script.sh +++ b/.github/workflows/scripts/script.sh @@ -119,7 +119,7 @@ echo "Checking for uncommitted migrations..." cmd_user_prefix bash -c "django-admin makemigrations npm --check --dry-run" # Run unit tests. -cmd_user_prefix bash -c "PULP_DATABASES__default__USER=postgres pytest -v -r sx --color=yes --suppress-no-test-exit-code -p no:pulpcore --pyargs pulp_npm.tests.unit" +cmd_user_prefix bash -c "PULP_DATABASES__default__USER=postgres pytest -v -r sx --color=yes --suppress-no-test-exit-code -p no:pulpcore --durations=20 --pyargs pulp_npm.tests.unit" # Run functional tests if [[ "$TEST" == "performance" ]]; then if [[ -z ${PERFORMANCE_TEST+x} ]]; then @@ -135,11 +135,11 @@ if [ -f "$FUNC_TEST_SCRIPT" ]; then else if [[ "$GITHUB_WORKFLOW" =~ "Nightly" ]] then - cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_npm.tests.functional -m parallel -n 8 --nightly" - cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_npm.tests.functional -m 'not parallel' --nightly" + cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --durations=20 --pyargs pulp_npm.tests.functional -m parallel -n 8 --nightly" + cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --durations=20 --pyargs pulp_npm.tests.functional -m 'not parallel' --nightly" else - cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_npm.tests.functional -m parallel -n 8" - cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_npm.tests.functional -m 'not parallel'" + cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --durations=20 --pyargs pulp_npm.tests.functional -m parallel -n 8" + cmd_user_prefix bash -c "pytest -v --timeout=300 -r sx --color=yes --suppress-no-test-exit-code --durations=20 --pyargs pulp_npm.tests.functional -m 'not parallel'" fi fi