Skip to content

Commit 82617d3

Browse files
authored
Merge pull request #512 from intersystems/master-ci-fix
Master ci fix
2 parents 1f69a07 + 44bfa5c commit 82617d3

File tree

4 files changed

+169
-28
lines changed

4 files changed

+169
-28
lines changed

.github/scripts/batcher.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env python3
2+
# This script groups elements in a JSON array into given number of batches
3+
# Usage example: cat data.json | python .github/scripts/batcher.py 10
4+
# The JSON array is expected to be passed from stdin
5+
# The output will be an array of comma-separated-values to stdout
6+
7+
import sys
8+
import json
9+
10+
def batch_array(arr, n):
11+
if n <= 0:
12+
raise ValueError("n must be a positive integer")
13+
14+
batch_size = len(arr) // n
15+
remainder = len(arr) % n
16+
17+
batched_array = []
18+
start_index = 0
19+
20+
for i in range(n):
21+
end_index = start_index + batch_size + (1 if i < remainder else 0)
22+
batched_array.append(arr[start_index:end_index])
23+
start_index = end_index
24+
25+
return batched_array
26+
27+
28+
if __name__ == "__main__":
29+
if len(sys.argv) != 2:
30+
print(f"Usage: cat data.json | python3 {sys.argv[0]} <batch_count>", file=sys.stderr)
31+
sys.exit(1)
32+
33+
n_batches = int(sys.argv[1])
34+
arr = json.load(sys.stdin)
35+
output = batch_array(arr, n_batches)
36+
json.dump([','.join(batch) for batch in output], sys.stdout, indent=2)

.github/scripts/summarize_logs.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python3
2+
# Summarize logs in a directory
3+
# Usage: summarize_logs.py <log_dir>
4+
5+
6+
import sys
7+
import re
8+
import glob
9+
10+
11+
if len(sys.argv) != 2:
12+
print(f"Usage: {sys.argv[0]} <log_dir>", file=sys.stderr)
13+
sys.exit(1)
14+
15+
p_pat = re.compile(r"Test for package (\S+) passed")
16+
f_pat = re.compile(r"Test for package (\S+) failed")
17+
18+
passed, failed = set(), set()
19+
20+
for fn in glob.glob(f"{sys.argv[1]}/*.txt"):
21+
with open(fn) as f:
22+
for line in f.readlines():
23+
m = p_pat.search(line)
24+
if m:
25+
passed.add(m.group(1))
26+
m = f_pat.search(line)
27+
if m:
28+
failed.add(m.group(1))
29+
30+
passed.remove("$package")
31+
failed.remove("$package")
32+
33+
print(f"A total of {len(passed)} packages passed:", sorted(passed))
34+
print(f"A total of {len(failed)} packages failed:", sorted(failed))
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Summarize package test results
2+
on:
3+
workflow_call:
4+
inputs:
5+
runId:
6+
type: number
7+
required: true
8+
description: "Id of the workflow run to summarize"
9+
workflow_dispatch:
10+
inputs:
11+
runId:
12+
type: number
13+
required: true
14+
description: "Id of the workflow run to summarize"
15+
16+
jobs:
17+
summarize:
18+
runs-on: ubuntu-latest
19+
env:
20+
BASE_URL: https://api.github.com/repos/intersystems/ipm/actions/runs
21+
steps:
22+
- name: Donwload log zip
23+
run: |
24+
curl -L -o logs.zip "${{ env.BASE_URL }}/${{ inputs.runId }}/logs" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}'
25+
- name: Unzip logs
26+
run: |
27+
unzip logs.zip -d logs/
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
- name: Summarize logs
31+
run: |
32+
# Could also use awk script, but python is easier to read and debug
33+
python3 .github/scripts/summarize_logs.py logs/
34+

.github/workflows/packages.yml

+65-28
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@ name: Test major packages
22
on:
33
workflow_dispatch:
44
inputs:
5+
nJobs:
6+
description: "Number of jobs to run in parallel"
7+
required: true
8+
type: number
9+
default: 8
510
minVersionCount:
611
description: "Minimum number of versions a package must have to be tested"
712
required: true
813
type: number
9-
default: 10
14+
default: 1
1015

1116
jobs:
1217
matrix-setup:
@@ -17,9 +22,11 @@ jobs:
1722
outputs:
1823
matrix: ${{ steps.set-matrix.outputs.matrix }}
1924
steps:
25+
- name: Checkout repository
26+
uses: actions/checkout@v4
2027
- id: set-matrix
2128
run: |
22-
matrix=$(curl -L "$PM_URL" | jq -cr "$JQ_SCRIPT")
29+
matrix=$(curl -L "$PM_URL" | jq -cr "$JQ_SCRIPT" | python3 .github/scripts/batcher.py ${{ inputs.nJobs }} | jq -cr .)
2330
echo "matrix=$matrix" >> $GITHUB_OUTPUT
2431
2532
prepare-image:
@@ -43,14 +50,14 @@ jobs:
4350
- name: Test Image
4451
run: |
4552
docker load -i /tmp/zpmimage.tar
46-
docker image ls
4753
CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm)
4854
docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh
4955
docker exec -i $CONTAINER iris session IRIS << EOF
5056
zpm "list":1
5157
zn "%SYS"
5258
zpm "test zpm -v -only":1:1
5359
EOF
60+
docker container stop $CONTAINER
5461
- name: Upload Image
5562
uses: actions/upload-artifact@v2
5663
with:
@@ -65,7 +72,7 @@ jobs:
6572
strategy:
6673
fail-fast: false
6774
matrix:
68-
package: ${{ fromJson(needs.matrix-setup.outputs.matrix) }}
75+
packages: ${{ fromJson(needs.matrix-setup.outputs.matrix) }}
6976
steps:
7077
- uses: actions/checkout@master
7178
- name: Set up Docker Buildx
@@ -78,33 +85,63 @@ jobs:
7885
- name: Load Image
7986
run: |
8087
docker load -i /tmp/zpmimage.tar
81-
docker image ls
82-
- name: Container Setup
83-
id: setup-zpm
84-
timeout-minutes: 15
85-
run: |
86-
# Don't specify the container name because `act` will run multiple jobs in parallel and cause name conflicts
87-
CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm)
88-
echo "CONTAINER=$CONTAINER" >> $GITHUB_OUTPUT
89-
docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh
90-
docker exec -i $CONTAINER iris session IRIS << EOF
91-
zpm "repo -r -name registry -url https://pm.community.intersystems.com/":1
92-
halt
93-
EOF
94-
- name: Test ${{ matrix.package }}
95-
timeout-minutes: 15
88+
- name: Run tests sequentially
9689
env:
97-
CONTAINER: ${{ steps.setup-zpm.outputs.CONTAINER }}
9890
test-flags: >-
9991
-verbose -DUnitTest.ManagerClass=%UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml
10092
-DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=%UnitTest.Manager
10193
run: |
102-
docker exec -i ${{ env.CONTAINER }} iris session IRIS << EOF
103-
zpm "install ${{ matrix.package }}":1
104-
zpm "${{ matrix.package }} test -only ${{ env.test-flags }}":1:1
94+
# Don't specify the container name because `act` will run multiple jobs in parallel and cause name conflicts
95+
packages=${{ matrix.packages }}
96+
IFS=','
97+
RED='\033[0;31m'
98+
GREEN='\033[0;32m'
99+
NC='\033[0m'
100+
101+
# The EOF of the following heredocs are intentially unindented
102+
# because <<-EOF doesn't like spaces while yaml only allows spaces
103+
# A potential solution is to use a script file instead of a block
104+
for package in $packages; do
105+
echo "::group::Set up container for package $package"
106+
CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm)
107+
docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh
108+
docker exec -i $CONTAINER iris session IRIS <<- EOF
109+
zpm "config set analytics 0":1
110+
zpm "repo -r -name registry -url https://pm.community.intersystems.com/":1
111+
halt
105112
EOF
106-
- name: Stop Container
107-
run: |
108-
# To ensure a clean state after using `act` locally
109-
docker stop -t 5 ${{ steps.setup-zpm.outputs.CONTAINER }}
110-
docker ps
113+
echo "::endgroup::"
114+
115+
echo "::group::Test package $package"
116+
set +e
117+
docker exec -i $CONTAINER iris session IRIS <<- EOF
118+
zpm "install $package":1
119+
zpm "$package test -only ${{ env.test-flags }}":1:1
120+
EOF
121+
122+
if [ $? -ne 0 ]; then
123+
# ATTENTION: Don't change the format of the following echo without updating the regex in the summarize.py script
124+
echo -e "\n${RED}Test for package $package failed${NC}" >&2
125+
else
126+
# ATTENTION: Don't change the format of the following echo without updating the regex in the summarize.py script
127+
echo -e "\n${GREEN}Test for package $package passed${NC}"
128+
fi
129+
echo "::endgroup::"
130+
131+
echo "::group::Clean up container for $package"
132+
# To ensure a clean state after using `act` locally
133+
docker stop -t 5 $CONTAINER
134+
echo "::endgroup::"
135+
done
136+
137+
IFS=' '
138+
139+
summarize:
140+
needs:
141+
- run-tests
142+
runs-on: ubuntu-latest
143+
steps:
144+
- name: Call package-summary workflow
145+
uses: ./.github/workflows/packages-summary.yml
146+
with:
147+
runId: ${{ github.run_id }}

0 commit comments

Comments
 (0)