mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 01:30:20 +00:00
Move the check-changelog-entries pre-commit local hook to tools.
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
This commit is contained in:
parent
3a04e21f70
commit
d0630ae7af
3 changed files with 125 additions and 133 deletions
|
@ -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
|
||||||
|
|
|
@ -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:])
|
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Reference in a new issue