From e6f21166ffc1b0be8d45cfceac63b8e545abd90b Mon Sep 17 00:00:00 2001 From: GitInno <86991526+gitnnolabs@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:33:23 -0300 Subject: [PATCH 1/5] [AUTO-112] chore: teste do hook de commit From 922b6fdb85268eb9a9c194cd528e2f063abe377b Mon Sep 17 00:00:00 2001 From: GitInno <86991526+gitnnolabs@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:35:31 -0300 Subject: [PATCH 2/5] [AUTO-112] chore: teste do hook de commit From ee1f205121dbafb04e3c8b8b1235701c8a15aaa0 Mon Sep 17 00:00:00 2001 From: GitInno <86991526+gitnnolabs@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:39:49 -0300 Subject: [PATCH 3/5] [MarkAPI-112] chore: teste do hook de commit From 80b3c9919331d7815e0e18950dff213e901ffa64 Mon Sep 17 00:00:00 2001 From: GitInno <86991526+gitnnolabs@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:44:46 -0300 Subject: [PATCH 4/5] [MarkAPI-112] feature: Adiciona um hook para padronizar os commits e o nomes dos branchs. --- .git-hook-commit-msg | 126 +++++++++++++++++++++++++++++++++++++++++++ Makefile | 4 ++ 2 files changed, 130 insertions(+) create mode 100755 .git-hook-commit-msg diff --git a/.git-hook-commit-msg b/.git-hook-commit-msg new file mode 100755 index 0000000..4b0efdd --- /dev/null +++ b/.git-hook-commit-msg @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +"""Git commit-msg hook. + +Reads the activity (MarkAPI-NNNN) from the branch name -- anywhere in the +name -- and: + + 1. validates the message format: (): + allowed types: feature, fix, chore, unittest + 2. injects the activity prefix into the first line: [MarkAPI-NNNN] ... + +Automatic Git commits (merge/revert/squash) are skipped. +Uses the standard library only for portability across Linux and macOS. +""" + +import re +import subprocess +import sys + +ALLOWED_TYPES = ("feature", "fix", "chore", "unittest") + +BRANCH_ACTIVITY_RE = re.compile(r"MarkupAPI-(\d+)", re.IGNORECASE) +EXISTING_PREFIX_RE = re.compile(r"^\s*\[MarkupAPI-\d+\]\s*", re.IGNORECASE) +MESSAGE_FORMAT_RE = re.compile( + r"^(?:%s)(?:\([a-z0-9-]+\))?: .+" % "|".join(ALLOWED_TYPES) +) + +# Automatic commits generated by Git that should pass without validation. +MarkAPI_COMMIT_PREFIXES = ( + "Merge branch ", + "Merge pull request ", + "Merge remote-tracking ", + 'Revert "', +) +SQUASH_MERGE_RE = re.compile(r"^Merge .+ into ") + + +def fail(message): + print(message, file=sys.stderr) + sys.exit(1) + + +def is_auto_commit(first_line): + if first_line.startswith(MarkAPI_COMMIT_PREFIXES): + return True + return bool(SQUASH_MERGE_RE.match(first_line)) + + +def current_branch(): + # symbolic-ref works even on the first commit (branch with no commits), + # where rev-parse --abbrev-ref HEAD fails. On a detached HEAD, + # symbolic-ref returns a non-zero code and we fall back to rev-parse + # (which returns "HEAD"). + for cmd in ( + ["git", "symbolic-ref", "--short", "HEAD"], + ["git", "rev-parse", "--abbrev-ref", "HEAD"], + ): + try: + result = subprocess.run(cmd, capture_output=True, text=True) + except OSError: + return None + if result.returncode == 0: + branch = result.stdout.strip() + if branch: + return branch + return None + + +def main(): + if len(sys.argv) < 2: + fail("❌ commit-msg hook: message file path not provided.") + + msg_path = sys.argv[1] + with open(msg_path, "r", encoding="utf-8") as handle: + lines = handle.read().splitlines() + + if not lines: + fail("❌ Empty commit message.") + + first_line = lines[0].rstrip("\r") + + # Let automatic Git commits pass through. + if is_auto_commit(first_line): + sys.exit(0) + + branch = current_branch() + if not branch or branch == "HEAD": + fail( + "❌ Could not determine the current branch (detached HEAD?).\n" + "The branch must contain the activity MarkAPI-NNNN." + ) + + match = BRANCH_ACTIVITY_RE.search(branch) + if not match: + fail( + "❌ Branch without an activity.\n" + "The branch name must contain MarkAPI-NNNN " + "(e.g. feature/MarkAPI-1234/my-feature).\n" + "Current branch: %s" % branch + ) + + activity = "MarkAPI-%s" % match.group(1) + + # Strip an existing prefix to avoid duplication (amend/rebase/reword). + body = EXISTING_PREFIX_RE.sub("", first_line).strip() + + if not MESSAGE_FORMAT_RE.match(body): + fail( + "❌ Invalid commit message.\n" + "Expected format: (): \n" + "Allowed types: %s\n" + "Examples:\n" + " chore: format readme\n" + " fix(auth): fix authentication when token is invalid" + % ", ".join(ALLOWED_TYPES) + ) + + lines[0] = "[%s] %s" % (activity, body) + + with open(msg_path, "w", encoding="utf-8") as handle: + handle.write("\n".join(lines) + "\n") + + sys.exit(0) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Makefile b/Makefile index 3023b82..589fd6d 100755 --- a/Makefile +++ b/Makefile @@ -31,6 +31,10 @@ latest_commit: ## Show last commit ref build_date: ## Show build date @echo "Build date: " $(SCMS_BUILD_DATE) +configure_git_hooks: ## Configure git hooks + cp -fa .git-hook-commit-msg .git/hooks/commit-msg + ln -sf ../../.git-hook-commit-msg .git/hooks/commit-msg + ############################################ ## atalhos docker compose desenvolvimento ## ############################################ From a4ded03f5fc10084343ee7d392fc39d15fc715ab Mon Sep 17 00:00:00 2001 From: GitInno <86991526+gitnnolabs@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:46:13 -0300 Subject: [PATCH 5/5] =?UTF-8?q?[MarkAPI-112]=20chore:=20reorganiza=20o=20m?= =?UTF-8?q?enu=20na=20=C3=A1rea=20administrativa.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/menu.py | 2 +- core/wagtail_hooks.py | 2 +- markup_doc/wagtail_hooks.py | 12 ++++++------ reference/wagtail_hooks.py | 8 ++++++-- xml_manager/wagtail_hooks.py | 12 +++--------- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/config/menu.py b/config/menu.py index 04b4fda..e759aa6 100644 --- a/config/menu.py +++ b/config/menu.py @@ -1,6 +1,6 @@ WAGTAIL_MENU_APPS_ORDER = [ - "sps_package_validation", "markup_doc", + "reference", "scielo", "tracker", "model_ai", diff --git a/core/wagtail_hooks.py b/core/wagtail_hooks.py index df63ea1..d502c9d 100644 --- a/core/wagtail_hooks.py +++ b/core/wagtail_hooks.py @@ -51,7 +51,7 @@ def group_wagtail_cms_menu_items(request, menu_items): ) menu_items.append( SubmenuMenuItem( - _("Wagtail CMS"), + _("Content Manager"), cms_menu, icon_name="folder-open-inverse", name="wagtail_cms", diff --git a/markup_doc/wagtail_hooks.py b/markup_doc/wagtail_hooks.py index 4eb729b..c292a62 100644 --- a/markup_doc/wagtail_hooks.py +++ b/markup_doc/wagtail_hooks.py @@ -27,8 +27,8 @@ ) from markup_doc.sync_api import sync_collection_from_api from markup_doc.tasks import get_labels, task_sync_journals_from_api, update_xml -from reference.wagtail_hooks import ReferenceModelViewSet from xml_manager.wagtail_hooks import ( + SPSPackageValidationSnippetViewSet, XMLDocumentHTMLSnippetViewSet, XMLDocumentPDFSnippetViewSet, ) @@ -100,7 +100,7 @@ def form_valid(self, form): class UploadDocxViewSet(SnippetViewSet): model = UploadDocx add_view_class = ArticleDocxCreateView - menu_label = _("Carregar DOCX") + menu_label = _("DOCX") menu_icon = "upload" add_to_admin_menu = False exclude_from_explorer = False @@ -114,7 +114,7 @@ class MarkupXMLViewSet(SnippetViewSet): model = MarkupXML add_view_class = ArticleDocxMarkupCreateView edit_view_class = ArticleDocxEditView - menu_label = _("XML SPS marcado") + menu_label = _("XML SPS") menu_icon = "code" add_to_admin_menu = False exclude_from_explorer = False @@ -138,7 +138,7 @@ def form_valid(self, form): class CollectionModelViewSet(SnippetViewSet): model = CollectionModel add_view_class = CollectionModelCreateView - menu_label = _("Coleções SciELO") + menu_label = _("Coleção") menu_icon = "folder-inverse" add_to_admin_menu = False exclude_from_explorer = False @@ -190,15 +190,15 @@ class XMLSPSSnippetViewSetGroup(SnippetViewSetGroup): menu_icon = "code" items = ( MarkupXMLViewSet, + SPSPackageValidationSnippetViewSet, XMLDocumentPDFSnippetViewSet, XMLDocumentHTMLSnippetViewSet, - ReferenceModelViewSet, ) class ScieloSnippetViewSetGroup(SnippetViewSetGroup): menu_name = "scielo" - menu_label = _("SciELO") + menu_label = _("Journal Manager") menu_icon = "folder-open-inverse" menu_order = get_menu_order("scielo") items = ( diff --git a/reference/wagtail_hooks.py b/reference/wagtail_hooks.py index 872c34f..4a50aef 100644 --- a/reference/wagtail_hooks.py +++ b/reference/wagtail_hooks.py @@ -1,6 +1,7 @@ # Third-party imports from django.http import HttpResponseRedirect from django.utils.translation import gettext_lazy as _ +from wagtail.snippets.models import register_snippet from wagtail.snippets.views.snippets import CreateView, SnippetViewSet # Local application imports @@ -35,9 +36,12 @@ class ReferenceModelViewSet(SnippetViewSet): model = Reference add_view_class = ReferenceCreateView menu_name = "reference" - menu_label = _("Referências bibliográficas") + menu_label = _("Referências") menu_icon = "openquote" menu_order = get_menu_order("reference") exclude_from_explorer = False list_per_page = 20 - add_to_admin_menu = False + add_to_admin_menu = True + + +register_snippet(ReferenceModelViewSet) diff --git a/xml_manager/wagtail_hooks.py b/xml_manager/wagtail_hooks.py index cc484f0..a47deb8 100644 --- a/xml_manager/wagtail_hooks.py +++ b/xml_manager/wagtail_hooks.py @@ -12,8 +12,6 @@ from wagtail.snippets.models import register_snippet from wagtail.snippets.views.snippets import CreateView, EditView, SnippetViewSet -from config.menu import get_menu_order - from . import urls from .forms import SPSPackageValidationForm from .models import ( @@ -156,7 +154,7 @@ class XMLDocumentPDFSnippetViewSet(SnippetViewSet): verbose_name_plural = _("XML Document PDFs") icon = "doc-full" menu_name = "xml_manager" - menu_label = _("PDFs derivados") + menu_label = _("PDFs") menu_icon = "doc-full" add_to_admin_menu = False @@ -177,7 +175,7 @@ class XMLDocumentHTMLSnippetViewSet(SnippetViewSet): verbose_name_plural = _("XML Document HTMLs") icon = "doc-full" menu_name = "xml_manager" - menu_label = _("HTMLs derivados") + menu_label = _("HTMLs") menu_icon = "doc-full-inverse" add_to_admin_menu = False @@ -202,8 +200,7 @@ class SPSPackageValidationSnippetViewSet(SnippetViewSet): menu_name = "sps_package_validation" menu_label = _("Validar SPS") menu_icon = "sps-package-validation" - add_to_admin_menu = True - menu_order = get_menu_order("sps_package_validation") + add_to_admin_menu = False list_display = ( "__str__", @@ -220,9 +217,6 @@ class SPSPackageValidationSnippetViewSet(SnippetViewSet): search_fields = ("package_document__title",) -register_snippet(SPSPackageValidationSnippetViewSet) - - @hooks.register("register_icons") def register_xml_manager_icons(icons): return icons + ["wagtailadmin/icons/sps-package-validation.svg"]