Skip to content

Commit 753b7e8

Browse files
authored
Merge pull request #355 from EESSI/develop
merge `develop` into `main` for releasing version v0.10.0
2 parents a552da9 + 19ec90f commit 753b7e8

File tree

10 files changed

+202
-53
lines changed

10 files changed

+202
-53
lines changed

.github/workflows/markdown-lint.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111

1212
name: Markdown Lint
13-
on: [push, pull_request]
13+
on: [push, pull_request, workflow_dispatch]
1414
# Declare default permissions as read only.
1515
permissions: read-all
1616

@@ -24,10 +24,11 @@ jobs:
2424
- name: Setup Node.js
2525
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.0
2626
with:
27-
node-version: '18'
27+
node-version: '20'
2828

2929
- name: Install markdownlint-cli
30-
run: npm install -g markdownlint-cli
30+
run: npm install -g igorshubovych/markdownlint-cli#192ad822316c3a22fb3d3cc8aa6eafa0b8488360 # v0.45.0
31+
# SHA from https://github.com/igorshubovych/markdownlint-cli/commit/192ad822316c3a22fb3d3cc8aa6eafa0b8488360
3132

3233
- name: Run markdownlint
33-
run: markdownlint "**/*.md" --ignore .git
34+
run: markdownlint "**/*.md" --ignore .git
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# NOTE, this file is used with installing packages in CI. Do not use it for running
2+
# bot components.
3+
# try to pin required versions using hashes
4+
# for some Python versions we may have to use different versions
5+
pip==25.3; python_version >= "3.9" \
6+
--hash=sha256:8d0538dbbd7babbd207f261ed969c65de439f6bc9e5dbd3b3b9a77f25d95f343
7+
8+
exceptiongroup==1.3.0 \
9+
--hash=sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88
10+
11+
iniconfig==2.1.0; python_version <= "3.9" \
12+
--hash=sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7
13+
iniconfig==2.3.0; python_version >= "3.10" \
14+
--hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730
15+
16+
packaging==25.0 \
17+
--hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
18+
19+
typing-extensions==4.15.0 \
20+
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466
21+
22+
pluggy==1.6.0 \
23+
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3
24+
25+
pygments==2.19.2 \
26+
--hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887
27+
28+
tomli==2.3.0 \
29+
--hash=sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549
30+
31+
pytest==8.4.2 \
32+
--hash=sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01
33+
34+
coverage==7.10.7; python_version <= "3.9" \
35+
--hash=sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239
36+
coverage==7.11.0; python_version >= "3.10" \
37+
--hash=sha256:167bd504ac1ca2af7ff3b81d245dfea0292c5032ebef9d66cc08a7d28c1b8050
38+
39+
pytest-cov==7.0.0 \
40+
--hash=sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1
41+
42+
mccabe==0.7.0 \
43+
--hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325
44+
45+
pycodestyle==2.14.0 \
46+
--hash=sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783
47+
48+
pyflakes==3.4.0 \
49+
--hash=sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58
50+
51+
flake8==7.3.0 \
52+
--hash=sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872

.github/workflows/scorecards.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
persist-credentials: false
4545

4646
- name: "Run analysis"
47-
uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # v2.0.6
47+
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
4848
with:
4949
results_file: results.sarif
5050
results_format: sarif

.github/workflows/tests.yaml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,29 @@ jobs:
2020
runs-on: ubuntu-24.04
2121
strategy:
2222
matrix:
23-
# for now, only test with Python 3.9+ (since we're testing in Ubuntu 24.04)
24-
#python: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11']
25-
python: ['3.9', '3.10', '3.11']
23+
# Waitress 3.0.1 does not support Python 3.8 or older
24+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
2625
fail-fast: false
2726
steps:
2827
- name: checkout
2928
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
3029

31-
- name: set up Python
30+
- name: set up Python ${{ matrix.python-version }}
3231
uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # v4.3.0
3332
with:
34-
python-version: ${{matrix.python}}
33+
python-version: ${{ matrix.python-version }}
3534

3635
- name: Install required Python packages + pytest + flake8
3736
run: |
38-
python -m pip install --upgrade pip
3937
python -m pip install -r requirements.txt
40-
python -m pip install pytest
41-
python -m pip install --upgrade flake8
38+
python -m pip install -r .github/workflows/requirements-lock.txt --require-hashes
4239
4340
- name: Run test suite (without coverage)
4441
run: |
4542
./test.sh --verbose
4643
4744
- name: Run test suite (with coverage)
4845
run: |
49-
python -m pip install pytest-cov
5046
./test.sh -q --cov=$PWD
5147
5248
- name: Run flake8 to verify PEP8-compliance of Python code

RELEASE_NOTES

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
This file contains a description of the major changes to the EESSI
22
build-and-deploy bot. For more detailed information, please see the git log.
33

4+
v0.10.0 (13 November 2025)
5+
--------------------------
6+
7+
This is a minor release of the EESSI build-and-deploy bot.
8+
9+
Bug fixes:
10+
* show builds for different repositories for `bot: status last_build` command (#345)
11+
* fix out of range error for `bot: status last_build` command (#346)
12+
* ensure tarballs with other suffixes than `.tar.gz` are correctly handled (#352, #353)
13+
14+
Improvements:
15+
* improve security aspects due to OpenSSF Scorecard report (#347, #348, #349, #350)
16+
17+
No changes to 'app.cfg' settings.
18+
19+
420
v0.9.0 (22 August 2025)
521
--------------------------
622

containers/Dockerfile.smee-client

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
ARG smee_client_version=4.2.1
1+
ARG smee_client_version=4.4.1
2+
# ARG smee_client_version_commit=b837fa85fd05853731160e21356ffd30c8c3e791 # v4.4.1
23

3-
FROM node:lts-alpine
4+
# pinning base image to specific hash (corresponding to lts-alpine)
5+
FROM node@sha256:f36fed0b2129a8492535e2853c64fbdbd2d29dc1219ee3217023ca48aebd3787
46
ARG smee_client_version
7+
# ARG smee_client_version_commit
8+
9+
# Then install
510
RUN npm install --global smee-client@${smee_client_version}
611
ENTRYPOINT ["smee"]
712
CMD ["--help"]

eessi_bot_event_handler.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ def handle_bot_command_status(self, event_info, bot_command):
591591
repo_name = event_info['raw_request_body']['repository']['full_name']
592592
pr_number = event_info['raw_request_body']['issue']['number']
593593
status_table = request_bot_build_issue_comments(repo_name, pr_number)
594+
self.log(f"Retrieved status table from issue comments: {status_table}")
594595

595596
if 'last_build' in bot_command.general_args:
596597
# If the bot command is something like 'bot:status =last_build', then only retain the last build for each
@@ -603,10 +604,17 @@ def handle_bot_command_status(self, event_info, bot_command):
603604
# copied, we ignore it, since - as a result of the sorting - the second entry is always older than the
604605
# first
605606
dates = status_table['date']
607+
status = status_table['status']
606608
timestamps = []
607-
for date in dates:
608-
date_object = datetime.strptime(date, "%b %d %X %Z %Y")
609-
timestamps.append(int(date_object.timestamp()))
609+
for date, state in zip(dates, status):
610+
if state == 'finished':
611+
date_object = datetime.strptime(date, "%b %d %X %Z %Y")
612+
timestamps.append(int(date_object.timestamp()))
613+
else:
614+
# Add the oldest date possible, so that ongoing builds only show up if there was no other
615+
# completed build yet
616+
timestamps.append(0)
617+
610618
status_table['timestamp'] = timestamps
611619

612620
# Figure out the sorting indices, so that things are sorted first by the 'for arch', and then by 'date'
@@ -625,7 +633,17 @@ def handle_bot_command_status(self, event_info, bot_command):
625633
'on arch': [], 'for arch': [], 'for repo': [], 'date': [], 'status': [], 'url': [], 'result': []
626634
}
627635
for x in range(0, len(sorted_table['date'])):
628-
if sorted_table['for arch'][x] not in status_table_last['for arch']:
636+
# Check if the current 'for arch' AND 'for repo' are already in the status_table_last. If not, add it
637+
already_present = False
638+
for y in range(0, len(status_table_last['for arch'])):
639+
if (
640+
sorted_table['for arch'][x] == status_table_last['for arch'][y]
641+
and sorted_table['for repo'][x] == status_table_last['for repo'][y]
642+
):
643+
already_present = True
644+
# One match is enough, we don't append in this case, no need to look further
645+
break
646+
if not already_present:
629647
self.log(f"arch: {sorted_table['for arch'][x]} not yet in status_table_last")
630648
for key in status_table_last:
631649
self.log(f"Adding to '{key}' and the value {sorted_table[key][x]}")

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# license: GPLv2
1212
#
1313
PyGithub
14-
Waitress
15-
cryptography
14+
Waitress>=3.0.1 # required to fix vulnerabilities detected by scorecards
15+
cryptography>=44.0.1 # required to fix vulnerabilities detected by scorecards
1616
PyGHee>=0.0.3
1717
retry

tasks/build.py

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,11 +1225,20 @@ def request_bot_build_issue_comments(repo_name, pr_number):
12251225
# it is building for)
12261226
# Then, check that it has at least 4 lines so that we can safely index up to that number
12271227
if instance_repo_match and len(comment_body) >= 4:
1228+
# Set some defaults
1229+
repo_id = ""
1230+
on_arch = ""
1231+
for_arch = ""
1232+
date = ""
1233+
status = ""
1234+
url = ""
1235+
result = ""
1236+
12281237
log(f"{fn}(): found bot build response in issue, processing...")
12291238

12301239
# First, extract the repo_id
12311240
log(f"{fn}(): found build for repository: {instance_repo_match.group('repo_id')}")
1232-
status_table['for repo'].append(instance_repo_match.group('repo_id'))
1241+
repo_id = instance_repo_match.group('repo_id')
12331242

12341243
# Then, try to match the architecture we build on.
12351244
# First try this including accelerator, to see if one was defined
@@ -1241,16 +1250,15 @@ def request_bot_build_issue_comments(repo_name, pr_number):
12411250
# Pattern with accelerator matched, append to status_table
12421251
log(f"{fn}(): found build on architecture: {on_arch_match.group('on_arch')}, "
12431252
f"with accelerator {on_arch_match.group('accelerator')}")
1244-
status_table['on arch'].append(f"`{on_arch_match.group('on_arch')}`, "
1245-
f"`{on_arch_match.group('accelerator')}`")
1253+
on_arch = f"`{on_arch_match.group('on_arch')}`, `{on_arch_match.group('accelerator')}`"
12461254
else:
12471255
# Pattern with accelerator did not match, retry without accelerator
12481256
on_arch_re = template_to_regex(on_arch_fmt)
12491257
on_arch_match = re.match(on_arch_re, comment_body[1])
12501258
if on_arch_match:
12511259
# Pattern without accelerator matched, append to status_table
12521260
log(f"{fn}(): found build on architecture: {on_arch_match.group('on_arch')}")
1253-
status_table['on arch'].append(f"`{on_arch_match.group('on_arch')}`")
1261+
on_arch = f"`{on_arch_match.group('on_arch')}`"
12541262
else:
12551263
# This shouldn't happen: we had an instance_repo_match, but no match for the 'on architecture'
12561264
msg = "Could not match regular expression for extracting the architecture to build on.\n"
@@ -1271,16 +1279,15 @@ def request_bot_build_issue_comments(repo_name, pr_number):
12711279
# Pattern with accelerator matched, append to status_table
12721280
log(f"{fn}(): found build for architecture: {for_arch_match.group('for_arch')}, "
12731281
f"with accelerator {for_arch_match.group('accelerator')}")
1274-
status_table['for arch'].append(f"`{for_arch_match.group('for_arch')}`, "
1275-
f"`{for_arch_match.group('accelerator')}`")
1282+
for_arch = f"`{for_arch_match.group('for_arch')}`, `{for_arch_match.group('accelerator')}`"
12761283
else:
12771284
# Pattern with accelerator did not match, retry without accelerator
12781285
for_arch_re = template_to_regex(for_arch_fmt)
12791286
for_arch_match = re.match(for_arch_re, comment_body[2])
12801287
if for_arch_match:
12811288
# Pattern without accelerator matched, append to status_table
12821289
log(f"{fn}(): found build for architecture: {for_arch_match.group('for_arch')}")
1283-
status_table['for arch'].append(f"`{for_arch_match.group('for_arch')}`")
1290+
for_arch = f"`{for_arch_match.group('for_arch')}`"
12841291
else:
12851292
# This shouldn't happen: we had an instance_repo_match, but no match for the 'on architecture'
12861293
msg = "Could not match regular expression for extracting the architecture to build for.\n"
@@ -1315,17 +1322,39 @@ def request_bot_build_issue_comments(repo_name, pr_number):
13151322
# add date, status, url to status_table if
13161323
for row in rows:
13171324
if row['job status'] == 'finished':
1318-
status_table['date'].append(row['date'])
1319-
status_table['status'].append(row['job status'])
1320-
status_table['url'].append(comment['html_url'])
1325+
date = row['date']
1326+
status = row['job status']
1327+
url = comment['html_url']
13211328
if 'FAILURE' in row['comment']:
1322-
status_table['result'].append(':cry: FAILURE')
1329+
result = ':cry: FAILURE'
13231330
elif 'SUCCESS' in row['comment']:
1324-
status_table['result'].append(':grin: SUCCESS')
1331+
result = ':grin: SUCCESS'
13251332
elif 'UNKNOWN' in row['comment']:
1326-
status_table['result'].append(':shrug: UNKNOWN')
1333+
result = ':shrug: UNKNOWN'
13271334
else:
1328-
status_table['result'].append(row['comment'])
1335+
result = row['comment']
1336+
elif row['job status'] in ['submitted', 'received', 'running']:
1337+
# Make sure that if the job is not finished yet, we also put something useful in these fields
1338+
# It is useful to know a job is submitted, running, etc
1339+
date = row['date']
1340+
status = row['job status']
1341+
url = comment['html_url']
1342+
result = row['comment']
1343+
else:
1344+
# Don't do anything for the test line for now - we might add an extra entry to the status
1345+
# table later to reflect the test result
1346+
continue
1347+
1348+
# Add all entries to status_table. We do this at the end of this loop so that the operation is
1349+
# more or less 'atomic', i.e. all vectors in the status_table dict have the same length
1350+
status_table['for repo'].append(repo_id)
1351+
status_table['on arch'].append(on_arch)
1352+
status_table['for arch'].append(for_arch)
1353+
status_table['date'].append(date)
1354+
status_table['status'].append(status)
1355+
status_table['url'].append(url)
1356+
status_table['result'].append(result)
1357+
13291358
if len(comments) != 100:
13301359
break
13311360
return status_table

0 commit comments

Comments
 (0)