Move the check-changelog-entries pre-commit local hook to tools.

Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
This commit is contained in:
Pedro Algarvio 2023-02-15 07:17:13 +00:00 committed by Pedro Algarvio
parent 3a04e21f70
commit d0630ae7af
3 changed files with 125 additions and 133 deletions

View file

@ -46,8 +46,19 @@ repos:
)$ )$
- repo: https://github.com/s0undt3ch/python-tools-scripts - repo: https://github.com/s0undt3ch/python-tools-scripts
rev: "0.10.2" rev: "0.10.4"
hooks: hooks:
- id: tools
alias: check-changelog-entries
name: Check Changelog Entries
args:
- changelog
- pre-commit-checks
additional_dependencies:
- boto3==1.21.46
- pyyaml==6.0
- jinja2==3.1.2
- packaging==23.0
- id: tools - id: tools
alias: generate-workflows alias: generate-workflows
name: Generate GitHub Workflow Templates name: Generate GitHub Workflow Templates
@ -1080,15 +1091,6 @@ repos:
- requirements/static/ci/tools.in - requirements/static/ci/tools.in
# <---- Tools ----------------------------------------------------------------------------------------------------- # <---- Tools -----------------------------------------------------------------------------------------------------
# ----- Local Hooks ----------------------------------------------------------------------------------------------->
- repo: local
hooks:
- id: check-changelog-entries
name: Check Changelog Entries
entry: .pre-commit-hooks/check-changelog-entries.py
language: script
# <---- Local Hooks ------------------------------------------------------------------------------------------------
# ----- Code Formatting -------------------------------------------------------------------------------------------> # ----- Code Formatting ------------------------------------------------------------------------------------------->
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.37.2 rev: v2.37.2

View file

@ -1,123 +0,0 @@
#!/usr/bin/env python3
# pylint: skip-file
import pathlib
import re
import sys
CODE_ROOT = pathlib.Path(__file__).resolve().parent.parent
DOCS_PATH = CODE_ROOT / "doc"
TESTS_INTEGRATION_FILES_PATH = CODE_ROOT / "tests" / "integration" / "files"
CHANGELOG_ENTRIES_PATH = CODE_ROOT / "changelog"
CHANGELOG_LIKE_RE = re.compile(r"([\d]+)\.([a-z]+)$")
CHANGELOG_EXTENSIONS = (
"removed",
"deprecated",
"changed",
"fixed",
"added",
"security",
)
CHANGELOG_ENTRY_RE = re.compile(
r"([\d]+|(CVE|cve)-[\d]{{4}}-[\d]+)\.({})(\.md)?$".format(
"|".join(CHANGELOG_EXTENSIONS)
)
)
def check_changelog_entries(files):
exitcode = 0
for entry in files:
path = pathlib.Path(entry).resolve()
# Is it under changelog/
try:
path.relative_to(CHANGELOG_ENTRIES_PATH)
if path.name == ".keep":
# This is the file we use so git doesn't delete the changelog/ directory
continue
# Is it named properly
if not CHANGELOG_ENTRY_RE.match(path.name):
print(
"The changelog entry '{}' should have one of the following extensions: {}.".format(
path.relative_to(CODE_ROOT),
", ".join(f"{ext}.md" for ext in CHANGELOG_EXTENSIONS),
),
file=sys.stderr,
flush=True,
)
exitcode = 1
continue
if not path.suffix == ".md":
print(
f"Please rename '{path.relative_to(CODE_ROOT)}' to "
f"'{path.relative_to(CODE_ROOT)}.md'",
file=sys.stderr,
flush=True,
)
exitcode = 1
continue
except ValueError:
# No, carry on
pass
# Does it look like a changelog entry
if CHANGELOG_LIKE_RE.match(path.name) and not CHANGELOG_ENTRY_RE.match(
path.name
):
try:
# Is this under doc/
path.relative_to(DOCS_PATH)
# Yes, carry on
continue
except ValueError:
# No, resume the check
pass
try:
# Is this under tests/integration/files
path.relative_to(TESTS_INTEGRATION_FILES_PATH)
# Yes, carry on
continue
except ValueError:
# No, resume the check
pass
print(
"The changelog entry '{}' should have one of the following extensions: {}.".format(
path.relative_to(CODE_ROOT),
", ".join(f"{ext}.md" for ext in CHANGELOG_EXTENSIONS),
),
file=sys.stderr,
flush=True,
)
exitcode = 1
continue
# Is it a changelog entry
if not CHANGELOG_ENTRY_RE.match(path.name):
# No? Carry on
continue
# Is the changelog entry in the right path?
try:
path.relative_to(CHANGELOG_ENTRIES_PATH)
except ValueError:
exitcode = 1
print(
"The changelog entry '{}' should be placed under '{}/', not '{}'".format(
path.name,
CHANGELOG_ENTRIES_PATH.relative_to(CODE_ROOT),
path.relative_to(CODE_ROOT).parent,
),
file=sys.stderr,
flush=True,
)
if not path.suffix == ".md":
print(
f"Please rename '{path.relative_to(CODE_ROOT)}' to "
f"'{path.relative_to(CODE_ROOT)}.md'",
file=sys.stderr,
flush=True,
)
exitcode = 1
sys.exit(exitcode)
if __name__ == "__main__":
check_changelog_entries(sys.argv[1:])

View file

@ -7,6 +7,8 @@ from __future__ import annotations
import datetime import datetime
import logging import logging
import os import os
import pathlib
import re
import subprocess import subprocess
import sys import sys
import textwrap import textwrap
@ -15,6 +17,20 @@ from ptscripts import Context, command_group
import tools.utils import tools.utils
REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent
CHANGELOG_LIKE_RE = re.compile(r"([\d]+)\.([a-z]+)$")
CHANGELOG_TYPES = (
"removed",
"deprecated",
"changed",
"fixed",
"added",
"security",
)
CHANGELOG_ENTRY_RE = re.compile(
r"([\d]+|(CVE|cve)-[\d]{{4}}-[\d]+)\.({})(\.md)?$".format("|".join(CHANGELOG_TYPES))
)
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# Define the command group # Define the command group
@ -35,6 +51,103 @@ changelog = command_group(
) )
@changelog.command(
name="pre-commit-checks",
arguments={
"files": {
"nargs": "*",
}
},
)
def check_changelog_entries(ctx: Context, files: list[pathlib.Path]):
"""
Run pre-commit checks on changelog snippets.
"""
docs_path = REPO_ROOT / "doc"
tests_integration_files_path = REPO_ROOT / "tests" / "integration" / "files"
changelog_entries_path = REPO_ROOT / "changelog"
exitcode = 0
for entry in files:
path = pathlib.Path(entry).resolve()
# Is it under changelog/
try:
path.relative_to(changelog_entries_path)
if path.name in (".keep", ".template.jinja"):
# This is the file we use so git doesn't delete the changelog/ directory
continue
# Is it named properly
if not CHANGELOG_ENTRY_RE.match(path.name):
ctx.error(
"The changelog entry '{}' should have one of the following extensions: {}.".format(
path.relative_to(REPO_ROOT),
", ".join(f"{ext}.md" for ext in CHANGELOG_TYPES),
),
)
exitcode = 1
continue
if path.suffix != ".md":
ctx.error(
f"Please rename '{path.relative_to(REPO_ROOT)}' to "
f"'{path.relative_to(REPO_ROOT)}.md'"
)
exitcode = 1
continue
except ValueError:
# No, carry on
pass
# Does it look like a changelog entry
if CHANGELOG_LIKE_RE.match(path.name) and not CHANGELOG_ENTRY_RE.match(
path.name
):
try:
# Is this under doc/
path.relative_to(docs_path)
# Yes, carry on
continue
except ValueError:
# No, resume the check
pass
try:
# Is this under tests/integration/files
path.relative_to(tests_integration_files_path)
# Yes, carry on
continue
except ValueError:
# No, resume the check
pass
ctx.error(
"The changelog entry '{}' should have one of the following extensions: {}.".format(
path.relative_to(REPO_ROOT),
", ".join(f"{ext}.md" for ext in CHANGELOG_TYPES),
)
)
exitcode = 1
continue
# Is it a changelog entry
if not CHANGELOG_ENTRY_RE.match(path.name):
# No? Carry on
continue
# Is the changelog entry in the right path?
try:
path.relative_to(changelog_entries_path)
except ValueError:
exitcode = 1
ctx.error(
"The changelog entry '{}' should be placed under '{}/', not '{}'".format(
path.name,
changelog_entries_path.relative_to(REPO_ROOT),
path.relative_to(REPO_ROOT).parent,
)
)
if path.suffix != ".md":
ctx.error(
f"Please rename '{path.relative_to(REPO_ROOT)}' to "
f"'{path.relative_to(REPO_ROOT)}.md'"
)
exitcode = 1
ctx.exit(exitcode)
def _get_changelog_contents(ctx: Context, version: str): def _get_changelog_contents(ctx: Context, version: str):
""" """
Return the full changelog generated by towncrier. Return the full changelog generated by towncrier.