diff --git a/.gitea/workflows/post-merge.yml b/.gitea/workflows/post-merge.yml index 8290bdc..7cace75 100644 --- a/.gitea/workflows/post-merge.yml +++ b/.gitea/workflows/post-merge.yml @@ -39,6 +39,24 @@ jobs: id: check run: python3 scripts/ci/detect_release_commit.py + validate-commit-msg: + needs: [detect-type] + if: needs.detect-type.outputs.is-release == 'false' + runs-on: docker + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Install dependencies + run: python3 -m pip install --break-system-packages click python-dotenv + - name: Validate latest commit message + env: + PYTHONPATH: .:src + run: | + git log -1 --format=%B > /tmp/commit-msg.txt + python3 scripts/ci/validate_commit_msg.py /tmp/commit-msg.txt --branch master + release: needs: [detect-type] if: needs.detect-type.outputs.is-release == 'false' diff --git a/scripts/ci/auto_merge.py b/scripts/ci/auto_merge.py index 88b41ea..7e5f2c0 100644 --- a/scripts/ci/auto_merge.py +++ b/scripts/ci/auto_merge.py @@ -294,7 +294,7 @@ def main(branch: str, pr_title: str, repo: str, pr_number: str, label_name: str) conv_msg = extract_conventional_msg(commits) if not conv_msg: raise click.ClickException(_("Could not extract conventional commit message from PR commits.")) - merge_title = f"{task_id} {conv_msg}" + merge_title = f"{task_id}: {conv_msg}" try: client.merge_pr(pr_number, merge_title) diff --git a/scripts/ci/validate_commit_msg.py b/scripts/ci/validate_commit_msg.py index 2fd84b3..660e91a 100644 --- a/scripts/ci/validate_commit_msg.py +++ b/scripts/ci/validate_commit_msg.py @@ -37,11 +37,13 @@ def get_branch() -> str: @click.command() @click.argument("commit_msg_file") -def main(commit_msg_file: str) -> None: +@click.option("--branch", default=None, help="Override branch detection (for CI use).") +def main(commit_msg_file: str, branch: str | None) -> None: with open(commit_msg_file) as f: msg = f.read().strip() - branch = get_branch() + if branch is None: + branch = get_branch() subject = first_line(msg) if branch == "master": diff --git a/src/gitea_runner_manager/config.py b/src/gitea_runner_manager/config.py index 47eaf07..f8d5b56 100644 --- a/src/gitea_runner_manager/config.py +++ b/src/gitea_runner_manager/config.py @@ -25,9 +25,9 @@ BRANCH_PROTECTION_CONFIG: dict[str, object] = { "enable_status_check": True, "status_check_contexts": [ "CI / quality (pull_request)", - "CI / molecule-tests (0) (pull_request)", "CI / molecule-tests (1) (pull_request)", "CI / molecule-tests (2) (pull_request)", + "CI / molecule-tests (3) (pull_request)", ], "required_approvals": 0, "dismiss_stale_approvals": True, diff --git a/tests/unit/test_auto_merge.py b/tests/unit/test_auto_merge.py index 8f7e97d..33ae696 100644 --- a/tests/unit/test_auto_merge.py +++ b/tests/unit/test_auto_merge.py @@ -383,7 +383,7 @@ class TestMain: ) assert result.exit_code == 0 assert "squash-merged" in result.output - mock_client.merge_pr.assert_called_once_with("7", "GRM-19 fix: resolve timeout") + mock_client.merge_pr.assert_called_once_with("7", "GRM-19: fix: resolve timeout") @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) @patch("scripts.ci.auto_merge.validate_pr_title_matches_vikunja") @@ -406,7 +406,7 @@ class TestMain: ) assert result.exit_code == 0 assert "squash-merged" in result.output - mock_client.merge_pr.assert_called_once_with("7", "GRM-19 fix: resolve timeout") + mock_client.merge_pr.assert_called_once_with("7", "GRM-19: fix: resolve timeout") @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) @patch("scripts.ci.auto_merge.validate_pr_title_matches_vikunja") diff --git a/tests/unit/test_validate_commit_msg.py b/tests/unit/test_validate_commit_msg.py index 2f38651..70fc9da 100644 --- a/tests/unit/test_validate_commit_msg.py +++ b/tests/unit/test_validate_commit_msg.py @@ -128,6 +128,29 @@ class TestMain: result = runner.invoke(main, []) assert result.exit_code == 2 + def test_branch_override_accepts_master_commit(self) -> None: + """--branch master overrides branch detection (for CI use).""" + msg_path = self._write_msg("GRM-19: feat: add feature") + runner = CliRunner() + result = runner.invoke(main, [msg_path, "--branch", "master"]) + assert result.exit_code == 0 + + def test_branch_override_rejects_missing_task_id(self) -> None: + """--branch master still enforces GRM-N: prefix.""" + msg_path = self._write_msg("feat: add feature") + runner = CliRunner() + result = runner.invoke(main, [msg_path, "--branch", "master"]) + assert result.exit_code == 1 + assert "task ID" in result.output + + def test_branch_override_feature_accepts_conventional(self) -> None: + """--branch feature still rejects GRM-N prefix.""" + msg_path = self._write_msg("GRM-19: feat: add feature") + runner = CliRunner() + result = runner.invoke(main, [msg_path, "--branch", "feature"]) + assert result.exit_code == 1 + assert "task ID" in result.output + def test_main_module_block() -> None: import tempfile