Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a49a824
don't check export variables in function
smoors Jan 29, 2026
8d34ebd
Exclude tests from test coverage report
sondrebr Feb 4, 2026
90e115c
Improved config file handling when running pytest
sondrebr Feb 4, 2026
3164f0c
Update run_cmd and run_subprocess tests
sondrebr Feb 6, 2026
fbda75a
Add tests for tools/args.py
sondrebr Feb 6, 2026
78322d1
Add tests for tools/build_params.py
sondrebr Feb 9, 2026
55e4836
Add tests for tools/commands.py
sondrebr Feb 9, 2026
ff5bb3d
Add "Third party imports" comment for pytest
sondrebr Feb 10, 2026
44e89a0
Fix hound issues
sondrebr Feb 10, 2026
876b662
Additional tests for tools/job_metadata.py
sondrebr Feb 12, 2026
2a303e7
Add tests for tools/logging.py
sondrebr Feb 13, 2026
8314252
Add tests for tools/permissions.py
sondrebr Feb 13, 2026
13c4039
Replace tmpdir (legacy) with tmp_path
sondrebr Feb 17, 2026
92ca8a5
better parsing of scontrol output
bedroge Feb 26, 2026
f3b3fc0
update docstring
bedroge Feb 26, 2026
a57b3c1
add test for parse_scontrol_show_job_output
bedroge Feb 26, 2026
70b8f8d
shorten paths/lines
bedroge Feb 26, 2026
c6523f5
split long line
bedroge Feb 26, 2026
394677f
add explicit Slurm version to comment
bedroge Mar 3, 2026
b4777fa
rename i to idx
bedroge Mar 3, 2026
167da4a
Merge pull request #369 from bedroge/fix_scontrol_output_parsing
trz42 Mar 3, 2026
0f47252
Apply suggestion from code review
sondrebr Mar 11, 2026
cbacfa2
Update conftest.py authors
sondrebr Mar 11, 2026
def659e
Apply suggested formatting change
sondrebr Mar 12, 2026
387d4d7
Add test cases for contains_any_bot_command
sondrebr Mar 16, 2026
e0bbc93
Add test cases for get_bot_command
sondrebr Mar 16, 2026
544d34c
Merge pull request #365 from sondrebr/improve_test_coverage
trz42 Mar 17, 2026
0467862
Merge pull request #364 from smoors/export-filter
trz42 Jun 10, 2026
6885f67
release notes for v0.12.0
truib Jun 10, 2026
b8f6ba6
fix typo in release date for v0.12.0
boegel Jun 10, 2026
c66083a
Merge pull request #377 from trz42/release_notes_v0.12.0
boegel Jun 10, 2026
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
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
omit = tests/*
18 changes: 18 additions & 0 deletions RELEASE_NOTES
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
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.12.0 (11 June 2026)
--------------------------

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

Bug fixes:
* do not check export variables in `check_filters` function (#364)

Improvements:
* increase coverage by unit tests (#365)
* make parsing of `scontrol` output compatible with newer Slurm versions (#369)
* With newer Slurm versions (25.11), some values can also contain whitespaces
(e.g. for SubmitLine), making it complex to distinguish between keys and values.

Changes to 'app.cfg' settings (see README.md and app.cfg.example for details):
* none


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

Expand Down
19 changes: 17 additions & 2 deletions eessi_bot_job_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ def parse_scontrol_show_job_output(self, output):
"""
The output of 'scontrol --oneliner show job' is a list of key=value pairs
separated by whitespaces.
Note that with newer Slurm versions (25.11), some values can also contain whitespaces
(e.g. for SubmitLine), making it complex to distinguish between keys and values.
To solve this, we assume that all Slurm keys start with an uppercase letter.

Args:
output (string): the output of the scontrol command
Expand All @@ -281,8 +284,20 @@ def parse_scontrol_show_job_output(self, output):
"""
job_info = {}
stripped_output = output.strip()
for pair in stripped_output.split():
key, value = pair.split('=', 1)

# Match keys that start with uppercase and continue until '='
key_pattern = re.compile(r'([A-Z][A-Za-z0-9:/_]*)=')

keys_matches = list(key_pattern.finditer(stripped_output))

for idx, key_match in enumerate(keys_matches):
# The key is what actually got matched by the regex
key = key_match.group(1)
# The value starts where the key ends...
value_start = key_match.end()
# and it ends where the next key starts (or, if it's the last one, where the string ends)
value_end = keys_matches[idx+1].start() if (idx + 1) < len(keys_matches) else len(stripped_output)
value = stripped_output[value_start:value_end].strip()
job_info[key] = value

return job_info
Expand Down
19 changes: 19 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
# EESSI software layer, see https://github.com/EESSI/software-layer
#
# author: Thomas Roeblitz (@trz42)
# author: Sondre Bergsvaag Risanger (@sondrebr)
#
# license: GPLv2
#

import os
import shutil


def pytest_configure(config):
# register custom markers
Expand All @@ -24,3 +28,18 @@ def pytest_configure(config):
config.addinivalue_line(
"markers", "create_fails(bool): let function create_issue_comment return None"
)


def pytest_sessionstart():
# Back up app.cfg if it exists
if os.path.exists("app.cfg"):
shutil.copyfile("app.cfg", "appbackup.cfg")

# Copy needed app.cfg from tests directory
shutil.copyfile("tests/test_app.cfg", "app.cfg")


def pytest_sessionfinish():
# Restore backup if it exists
if os.path.exists("appbackup.cfg"):
shutil.copyfile("appbackup.cfg", "app.cfg")
1 change: 1 addition & 0 deletions tests/test_app.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ running_job = job `{job_id}` is running
[finished_job_comments]

[bot_control]
command_permission = user01 second_user
33 changes: 28 additions & 5 deletions tests/test_eessi_bot_job_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,10 @@
# license: GPLv2
#

import shutil

from eessi_bot_job_manager import EESSIBotSoftwareLayerJobManager


def test_determine_running_jobs():
# copy needed app.cfg from tests directory
shutil.copyfile("tests/test_app.cfg", "app.cfg")

job_manager = EESSIBotSoftwareLayerJobManager()

assert job_manager.determine_running_jobs({}) == []
Expand Down Expand Up @@ -135,3 +130,31 @@ def test_determine_finished_jobs():
assert job_manager.determine_finished_jobs(known_jobs, current_jobs_all_jobs) == []
assert job_manager.determine_finished_jobs(known_jobs, current_jobs_one_job) == ['1', '2']
assert job_manager.determine_finished_jobs(known_jobs, {}) == ['0', '1', '2']


def test_parse_scontrol_show_job_output():
# Dummy output (shortened) from Slurm 25.11.3 for "scontrol show job <jobid>"
scontrol_output = 'JobId=123 JobName=bot_test_job UserId=eessibot(12345) MCS_label=N/A EligibleTime=Unknown' \
' AllocNode:Sid=my.node.name:123456 SubmitLine=/opt/slurm/25.11.3/bin/sbatch --hold' \
' --time=10-0:0:0 --nodes=1 --exclusive --cpus-per-task=1 --job-name=bot_test_job ' \
'/home/eessibot/job.slurm WorkDir=/jobs/2026.01/pr_123/event_123-456-789/run_000/riscv64/' \
'generic/dev.eessi.io-riscv StdErr= StdIn=/dev/null StdOut=/jobs/2026.01/pr_123/' \
'event_123-456-789/run_000/riscv64/generic/dev.eessi.io-riscv/slurm-123.out TresPerTask=cpu=1'
job_manager = EESSIBotSoftwareLayerJobManager()
job_info = job_manager.parse_scontrol_show_job_output(scontrol_output)
job_info_expected = {
'JobId': '123',
'JobName': 'bot_test_job',
'UserId': 'eessibot(12345)',
'MCS_label': 'N/A',
'EligibleTime': 'Unknown',
'AllocNode:Sid': 'my.node.name:123456',
'SubmitLine': '/opt/slurm/25.11.3/bin/sbatch --hold --time=10-0:0:0 --nodes=1 --exclusive --cpus-per-task=1 '
'--job-name=bot_test_job /home/eessibot/job.slurm',
'WorkDir': '/jobs/2026.01/pr_123/event_123-456-789/run_000/riscv64/generic/dev.eessi.io-riscv',
'StdErr': '',
'StdIn': '/dev/null',
'StdOut': '/jobs/2026.01/pr_123/event_123-456-789/run_000/riscv64/generic/dev.eessi.io-riscv/slurm-123.out',
'TresPerTask': 'cpu=1',
}
assert job_info == job_info_expected
Loading
Loading