Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,12 @@ The example file (`app.cfg.example`) includes notes on what you have to adjust t

The section `[github]` contains information for connecting to GitHub:

```ini
api_timeout = 10
```

Time limit for requests to GitHub's REST API.

```ini
app_id = 123456
```
Expand Down Expand Up @@ -548,6 +554,12 @@ submit_command = /usr/bin/sbatch

`submit_command` is the full path to the Slurm job submission command used for submitting batch jobs. You may want to verify if `sbatch` is provided at that path or determine its actual location (using `which sbatch`).

```ini
cancel_command = /usr/bin/scancel
```

`cancel_command` is the full path to the Slurm command used for cancelling batch jobs. You may want to verify if `scancel` is provided at that path or determine its actual location (using `which scancel`).

```ini
build_permission = -NOT_ALLOWED_GH_ACCOUNT_NAME- [...]
```
Expand All @@ -560,11 +572,11 @@ name on GitHub. Thus, one could not - by accident - give build permissions to an
unknown account.

```ini
no_build_permission_comment = The `bot: build ...` command has been used by user `{build_labeler}`, but this person does not have permission to trigger builds.
no_build_permission_comment = GH account `{build_labeler}` is not authorized to trigger or cancel build jobs.
```

`no_build_permission_comment` defines a comment (template) that is used when
the account trying to trigger build jobs has no permission to do so.
the account trying to trigger or cancel build jobs has no permission to do so.

```ini
allow_update_submit_opts = false
Expand Down
22 changes: 22 additions & 0 deletions RELEASE_NOTES
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
This file contains a description of the major changes to the EESSI
build-and-deploy bot. For more detailed information, please see the git log.

v0.11.0 (28 January 2026)
--------------------------

This is a minor release of the EESSI build-and-deploy bot.

Bug fixes:
* consider all builds for `bot: status [last_build]` command (#357)
* this also replaces running `curl` by using the `requests` library for one `curl` call

Improvements:
* adds support for new command `bot: cancel jobid:[JOBID] ...` (#359)
* only the owner of a job can cancel it
* multiple jobs can be cancelled by specifying multiple `jobid:[JOBID]`
arguments separated by space

Changes to 'app.cfg' settings (see README.md and app.cfg.example for details):
* CHANGED (required) 'no_build_permission_comment' in section '[buildenv]'
Note! sites using the old value may see misleading comments added by the bot,
but the bot will work without the change.
* NEW (required) 'cancel_command' in section '[buildenv]'


v0.10.0 (13 November 2025)
--------------------------

Expand Down
8 changes: 7 additions & 1 deletion app.cfg.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
# Also see documentation at https://github.com/EESSI/eessi-bot-software-layer/blob/main/README.md#step5.5

[github]
# API timeout, time limit for requests to GitHub's REST API
api_timeout = 10

# replace '123456' with the ID of your GitHub App; see https://github.com/settings/apps
app_id = 123456

Expand Down Expand Up @@ -155,13 +158,16 @@ slurm_params = --hold
# full path to the job submission command
submit_command = /usr/bin/sbatch

# full path to the job cancellation command
cancel_command = /usr/bin/scancel

# defines which GitHub accounts have the permission to trigger
# build jobs, i.e., for which accounts the bot acts on `bot: build ...`
# commands. If the value is left empty, everyone can trigger build jobs.
build_permission = -NOT_ALLOWED_GH_ACCOUNT_NAME-

# template for comment when user who set a label has no permission to trigger build jobs
no_build_permission_comment = Label `bot:build` has been set by user `{build_labeler}`, but this person does not have permission to trigger builds
no_build_permission_comment = GH account `{build_labeler}` is not authorized to trigger or cancel build jobs.

# whether or not to allow updating the submit options via custom module det_submit_opts
# Should only be enabled (true) with care because this will result in code from the target
Expand Down
22 changes: 14 additions & 8 deletions containers/Dockerfile.smee-client
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
ARG smee_client_version=4.4.1
# ARG smee_client_version_commit=b837fa85fd05853731160e21356ffd30c8c3e791 # v4.4.1

# pinning base image to specific hash (corresponding to lts-alpine)
# pin base image to specific hash (corresponding to lts-alpine)
FROM node@sha256:f36fed0b2129a8492535e2853c64fbdbd2d29dc1219ee3217023ca48aebd3787
ARG smee_client_version
# ARG smee_client_version_commit

# Then install
RUN npm install --global smee-client@${smee_client_version}
# create app dir for locked installation
WORKDIR /app

# copy lockfile and manifest
COPY containers/package.json containers/package-lock.json ./

# install exactly what's in the lockfile (change version in package.json and update
# lockfile via 'npm install --package-lock-only')
RUN npm ci --omit=dev

# expose CLI by symlinking
RUN ln -sf /app/node_modules/.bin/smee /usr/local/bin/smee

ENTRYPOINT ["smee"]
CMD ["--help"]
62 changes: 62 additions & 0 deletions containers/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions containers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "smee-wrapper",
"private": true,
"version": "1.0.0",
"license": "GPL-2.0-only",
"dependencies": {
"smee-client": "4.4.1"
}
}
64 changes: 61 additions & 3 deletions eessi_bot_event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@

# Local application imports (anything from EESSI/eessi-bot-software-layer)
from connections import github
from tasks.build import check_build_permission, get_node_types, request_bot_build_issue_comments, \
submit_build_jobs
from tasks.build import cancel_jobs, check_build_permission, get_job_ids, get_node_types, \
get_work_dirs, request_bot_build_issue_comments, submit_build_jobs
from tasks.deploy import deploy_built_artefacts, determine_job_dirs
from tasks.clean_up import move_to_trash_bin
from tools import config
Expand All @@ -53,6 +53,7 @@
config.BUILDENV_SETTING_BUILD_JOB_SCRIPT, # required
config.BUILDENV_SETTING_BUILD_LOGS_DIR, # optional+recommended
config.BUILDENV_SETTING_BUILD_PERMISSION, # optional+recommended
config.BUILDENV_SETTING_CANCEL_COMMAND, # required
config.BUILDENV_SETTING_CONTAINER_CACHEDIR, # optional+recommended
# config.BUILDENV_SETTING_CLONE_GIT_REPO_VIA, # optional
# config.BUILDENV_SETTING_CVMFS_CUSTOMIZATIONS, # optional
Expand Down Expand Up @@ -95,13 +96,15 @@
config.SECTION_EVENT_HANDLER: [
config.EVENT_HANDLER_SETTING_LOG_PATH], # required
config.SECTION_GITHUB: [
config.GITHUB_SETTING_API_TIMEOUT, # required
config.GITHUB_SETTING_APP_ID, # required
config.GITHUB_SETTING_APP_NAME, # required
config.GITHUB_SETTING_INSTALLATION_ID, # required
config.GITHUB_SETTING_PRIVATE_KEY], # required
# the poll interval setting is required for the alternative job handover
# protocol (delayed_begin)
config.SECTION_JOB_MANAGER: [
config.JOB_MANAGER_SETTING_POLL_COMMAND, # required
config.JOB_MANAGER_SETTING_POLL_INTERVAL], # required
config.SECTION_REPO_TARGETS: [
config.REPO_TARGETS_SETTING_REPOS_CFG_DIR], # required
Expand Down Expand Up @@ -507,7 +510,7 @@ def handle_bot_command_help(self, event_info, bot_command):
help_msg += "\n - Commands must be sent with a **new** comment (edits of existing comments are ignored)."
help_msg += "\n - A comment may contain multiple commands, one per line."
help_msg += "\n - Every command begins at the start of a line and has the syntax `bot: COMMAND [ARGUMENTS]*`"
help_msg += "\n - Currently supported COMMANDs are: `help`, `build`, `show_config`, `status`"
help_msg += "\n - Currently supported COMMANDs are: `help`, `build`, `show_config`, `status`, `cancel`"
help_msg += "\n"
help_msg += "\n For more information, see https://www.eessi.io/docs/bot"
return help_msg
Expand Down Expand Up @@ -679,6 +682,61 @@ def handle_bot_command_status(self, event_info, bot_command):
else:
return "\n - failed to create status comment"

def handle_bot_command_cancel(self, event_info, bot_command):
"""
Handles bot command 'cancel' by parsing 'jobid:' arguments and
cancelling the jobs.

Args:
event_info (dict): event received by event_handler
bot_command (EESSIBotCommand): command to be handled

Returns:
comment (string): list of cancelled jobs if any, error message if not
"""
self.log("processing bot command 'cancel'")

request_body = event_info["raw_request_body"]
repo_name = request_body["repository"]["full_name"]
pr_number = request_body["issue"]["number"]
user = request_body["comment"]["user"]["login"]

gh = github.get_instance()
pr = gh.get_repo(repo_name).get_pull(pr_number)

# Jobs can only be cancelled by the user who submitted the job
# -> No need to proceed if user cannot submit jobs
if not check_build_permission(pr, event_info):
self.log(f"User '{user}' does not have build permission - skipping cancellation.")
return f"\n - User `{user}` cannot submit or cancel build jobs."

# Get valid 'jobid:' arguments
job_ids = get_job_ids(bot_command.action_filters)
if len(job_ids) == 0:
self.log("Got no valid job IDs")
return "\n - No valid job IDs were given."

# Get working directories of jobs
work_dirs = get_work_dirs(job_ids, self.cfg)
if len(work_dirs) == 0:
self.log("None of the given jobs are cancellable")
return "\n - No cancellable jobs were given."

# Log skipped jobs
for job_id in job_ids:
if job_id not in work_dirs.keys():
log(f"Skipping job {job_id} - not found")

# Cancel jobs
cancelled_jobs = cancel_jobs(work_dirs, user, pr, self.cfg)
if len(cancelled_jobs) == 0:
return "\n - No jobs were cancelled."
else:
comment = ""
for job_id in cancelled_jobs:
comment += f"\n - cancelled job `{job_id}`"
return comment

def start(self, app, port=3000):
"""
Logs startup information to shell and log file and starts the app using
Expand Down
1 change: 1 addition & 0 deletions eessi_bot_job_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
config.FINISHED_JOB_COMMENTS_SETTING_JOB_RESULT_UNKNOWN_FMT, # required
config.FINISHED_JOB_COMMENTS_SETTING_JOB_TEST_UNKNOWN_FMT], # required
config.SECTION_GITHUB: [
# config.GITHUB_SETTING_API_TIMEOUT, # unused
config.GITHUB_SETTING_APP_ID, # required
# config.GITHUB_SETTING_APP_NAME, # unused
config.GITHUB_SETTING_INSTALLATION_ID, # required
Expand Down
Loading