diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bbfc78e --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2026 The Snakemake team + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/docs/intro.md b/docs/intro.md index bfffa0d..dea84ba 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -1,4 +1,4 @@ - A Snakemake logger plugin that reports to the Github commit status. - The plugin assumes that it is used in combination with working directories that are controlled by git and associated to a Github repository. - It then reports logging events to the Github status API, such that Github displays the status of workflow runs attached to the current commit. - Github's status markers (running, success, failed) are thereby used to represent the state of the workflow execution, while the status messages are used to report on the number of completed and failed jobs. \ No newline at end of file +A Snakemake logger plugin that reports to the Github commit status. +The plugin assumes that it is used in combination with working directories that are controlled by git and associated to a Github repository. +It then reports logging events to the Github status API, such that Github displays the status of workflow runs attached to the current commit. +Github's status markers (running, success, failed) are thereby used to represent the state of the workflow execution, while the status messages are used to report on the number of completed and failed jobs. \ No newline at end of file diff --git a/src/snakemake_logger_plugin_github_status/__init__.py b/src/snakemake_logger_plugin_github_status/__init__.py index 4227d12..26659f5 100644 --- a/src/snakemake_logger_plugin_github_status/__init__.py +++ b/src/snakemake_logger_plugin_github_status/__init__.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass, field import time from typing import Dict from typing import Optional @@ -12,6 +13,18 @@ from snakemake_interface_logger_plugins.base import LogHandlerBase from snakemake_interface_logger_plugins.common import LogEvent from snakemake_interface_common.exceptions import WorkflowError +from snakemake_interface_logger_plugins.settings import LogHandlerSettingsBase + + +@dataclass +class LogHandlerSettings(LogHandlerSettingsBase): + run_name: Optional[str] = field( + default=None, + metadata={ + "help": "Name for the current workflow run. " + "This is used to identify the workflow run in the GitHub status.", + }, + ) class LogHandler(LogHandlerBase): @@ -31,15 +44,11 @@ def __post_init__(self) -> None: self._github_repo_name = "/".join( self._repo.remotes.origin.url.rstrip(".git").split(":")[1].split("/")[-2:] ) - self._repo.remotes.origin.fetch() - branch = self._repo.active_branch - tracking_branch = branch.tracking_branch() - if tracking_branch is None: - raise WorkflowError( - f"No tracking branch of current git branch {branch}. Make sure that your local repo is pushed." - ) - self._github_sha = tracking_branch.commit.hexsha + # Use the currently checked-out commit. This works in normal branches and in + # GitHub Actions where the checkout is often in detached HEAD state. + self._github_sha = self._repo.head.commit.hexsha + self._errors: Dict[str, int] = defaultdict(int) self._progress_done: int = 0 self._progress_total: Optional[int] = None @@ -140,6 +149,10 @@ def emit(self, record: LogRecord) -> None: # Exception: we always emit on "success" return + context = "snakemake" + if self.settings.run_name: + context += f": {self.settings.run_name}" + self._last_emit_timestamp = time.time() res = requests.post( f"https://api.github.com/repos/{self._github_repo_name}/statuses/{self._github_sha}", @@ -150,7 +163,7 @@ def emit(self, record: LogRecord) -> None: }, json={ "state": self.state, - "context": "snakemake", + "context": context, "description": description, }, ) diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 118b9f9..f8c3ab6 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1,16 +1,18 @@ +from snakemake_logger_plugin_github_status import LogHandlerSettings from snakemake_logger_plugin_github_status import LogHandler from snakemake_interface_logger_plugins.tests import TestLogHandlerBase class TestPlugin(TestLogHandlerBase): - """Concrete test using the actual rich plugin to verify the abstract test class works.""" - __test__ = True def get_log_handler_cls(self): - """Return the log handler class.""" return LogHandler def get_log_handler_settings(self): - """Return the settings with default values for testing.""" - return None + return LogHandlerSettings() + + +class TestPluginWithRunName(TestPlugin): + def get_log_handler_settings(self): + return LogHandlerSettings(run_name="test_run")