Skip to content

Commit b7cb6d3

Browse files
authored
chore: align releases and CI with DiracX (#484)
* chore: bump diracx-charts versions when new release * chore: use SHA instead of tags to improve security
1 parent 27a6b8d commit b7cb6d3

22 files changed

Lines changed: 302 additions & 173 deletions

.github/workflows/deployment.yml

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,61 @@ jobs:
150150
context: .
151151
push: true
152152
tags: ghcr.io/diracgrid/diracx-web/static:${{ needs.release-please.outputs.tag_name }}
153-
platforms: linux/amd64,linux/arm64
153+
platforms: linux/amd64,linux/arm64
154+
155+
# Helm charts are updated in diracx-charts
156+
# -----------------------------------------
157+
158+
update-charts:
159+
name: Update Helm charts
160+
needs:
161+
- release-please
162+
- build-deploy-diracx-web-release-image
163+
runs-on: ubuntu-latest
164+
if: ${{ needs.release-please.outputs.release_created == 'true' }}
165+
steps:
166+
- name: Checkout diracx-web (for update script)
167+
uses: actions/checkout@v6
168+
with:
169+
path: diracx-web
170+
sparse-checkout: .github/workflows
171+
172+
- name: Checkout diracx-charts
173+
uses: actions/checkout@v6
174+
with:
175+
repository: DIRACGrid/diracx-charts
176+
token: ${{ secrets.CHARTS_UPDATE_TOKEN }}
177+
path: diracx-charts
178+
179+
- name: Configure Git
180+
run: |
181+
cd diracx-charts
182+
git config user.name "github-actions[bot]"
183+
git config user.email "github-actions[bot]@users.noreply.github.com"
184+
185+
- name: Update chart versions
186+
run: |
187+
python diracx-web/.github/workflows/update_chart_version.py \
188+
--charts-dir diracx-charts \
189+
--web-version "${{ needs.release-please.outputs.tag_name }}"
190+
191+
- name: Install pre-commit
192+
run: pip install pre-commit
193+
194+
- name: Run pre-commit to update README
195+
run: |
196+
cd diracx-charts
197+
pre-commit run --all-files || true
198+
199+
- name: Commit and push changes
200+
if: success()
201+
run: |
202+
cd diracx-charts
203+
git add -A
204+
205+
if ! git diff --cached --quiet; then
206+
git commit -m "chore: bump diracx-web to ${{ needs.release-please.outputs.tag_name }}"
207+
git push origin master
208+
else
209+
echo "No changes to commit"
210+
fi

.github/workflows/gubbins-test.yml

Lines changed: 54 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -54,101 +54,41 @@ jobs:
5454
prepare-gubbins-backend:
5555
runs-on: ubuntu-latest
5656
if: ${{ github.event_name != 'push' || github.repository == 'DIRACGrid/diracx-web' }}
57-
defaults:
58-
run:
59-
# We need extglob for REFERENCE_BRANCH substitution
60-
shell: bash -l -O extglob {0}
6157
steps:
6258
- name: Clone source
6359
run: |
6460
cd ..
6561
git clone https://github.com/DIRACGrid/diracx.git
6662
67-
# Prepare the gubbins extension
68-
- name: Where the magic happens (Move extensions to a temporary directory)
69-
run: |
70-
# We have to copy the code to another directory
71-
# and make it a git repository by itself because otherwise the
72-
# root in the pyproject to do not make sense once mounted
73-
# in the containers.
74-
cp -r ../diracx/extensions/gubbins /tmp/
75-
sed -i 's@../..@.@g' /tmp/gubbins/pyproject.toml
76-
sed -i 's@../../@@g' /tmp/gubbins/gubbins-*/pyproject.toml
77-
78-
- name: Upload artifact
79-
uses: actions/upload-artifact@v7
80-
with:
81-
name: gubbins
82-
path: /tmp/gubbins
83-
include-hidden-files: true
84-
85-
# Prepare the gubbins image
86-
# - Build the gubbins wheels
87-
- uses: actions/setup-python@v6
88-
with:
89-
python-version: '3.14'
90-
- name: Installing dependencies
91-
run: |
92-
cd ../diracx
93-
python -m pip install \
94-
build \
95-
python-dateutil \
96-
pytz \
97-
readme_renderer[md] \
98-
requests \
99-
setuptools_scm
100-
- name: Build distributions
101-
run: |
102-
cd ../diracx
103-
for pkg_dir in $PWD/diracx-*; do
104-
echo "Building $pkg_dir"
105-
python -m build --outdir $PWD/dist $pkg_dir
106-
done
107-
# Also build the diracx metapackage
108-
python -m build --outdir $PWD/dist .
109-
# And build the gubbins package
110-
for pkg_dir in $PWD/extensions/gubbins/gubbins-*; do
111-
# Skip the testing package
112-
if [[ "${pkg_dir}" =~ .*testing.* ]];
113-
then
114-
echo "Do not build ${pkg_dir}";
115-
continue;
116-
fi
117-
echo "Building $pkg_dir"
118-
python -m build --outdir $PWD/dist $pkg_dir
119-
done
120-
- name: "Find wheels"
121-
id: find_wheel
122-
run: |
123-
cd ../diracx/dist
124-
# We need to copy them there to be able to access them in the RUN --mount
125-
cp diracx*.whl gubbins*.whl ../extensions/containers/services/
126-
for wheel_fn in *.whl; do
127-
pkg_name=$(basename "${wheel_fn}" | cut -d '-' -f 1)
128-
echo "${pkg_name}-wheel-name=$(ls "${pkg_name}"-*.whl)" >> $GITHUB_OUTPUT
129-
done
130-
131-
# - Build the gubbins image using the wheels
132-
- name: Set up QEMU
133-
uses: docker/setup-qemu-action@v4
63+
# Build gubbins container images using pixi
13464
- name: Set up Docker Buildx
13565
uses: docker/setup-buildx-action@v4
13666

137-
- name: Build and export service
67+
- name: Build gubbins services image
13868
uses: docker/build-push-action@v7
13969
with:
140-
context: ../diracx/extensions/containers/services
141-
tags: gubbins/services:dev
70+
context: ../diracx
71+
file: ../diracx/containers/Dockerfile
72+
build-args: |
73+
PIXI_ENV=gubbins-container-services
74+
tags: ghcr.io/gubbins/services:dev
14275
outputs: type=docker,dest=/tmp/gubbins_services_image.tar
76+
77+
- name: Build gubbins client image
78+
uses: docker/build-push-action@v7
79+
with:
80+
context: ../diracx
81+
file: ../diracx/containers/Dockerfile
14382
build-args: |
144-
EXTRA_PACKAGES_TO_INSTALL=git+https://github.com/DIRACGrid/DIRAC.git@integration
145-
EXTENSION_CUSTOM_SOURCES_TO_INSTALL=/bindmount/gubbins_db*.whl,/bindmount/gubbins_routers*.whl,/bindmount/gubbins_client*.whl
83+
PIXI_ENV=gubbins-container-client
84+
tags: ghcr.io/gubbins/client:dev
85+
outputs: type=docker,dest=/tmp/gubbins_client_image.tar
14686

147-
- name: Upload artifact
87+
- name: Upload gubbins images
14888
uses: actions/upload-artifact@v7
14989
with:
150-
name: gubbins-services-img
151-
path: /tmp/gubbins_services_image.tar
90+
name: gubbins-images
91+
path: /tmp/gubbins_*_image.tar
15292

15393
prepare-gubbins-frontend-as-a-standalone:
15494
runs-on: ubuntu-latest
@@ -226,7 +166,7 @@ jobs:
226166
# WARNING: In your CI/CD pipeline, you should remove the following steps #
227167
# ------------------------------------------------------------------------#
228168
- name: Download gubbins-web
229-
uses: actions/download-artifact@v8
169+
uses: actions/download-artifact@v7
230170
with:
231171
name: gubbins-web
232172
path: /tmp/gubbins-web
@@ -258,43 +198,57 @@ jobs:
258198
# ========================================================================#
259199
# WARNING: In your CI/CD pipeline, you should remove the following steps #
260200
# ------------------------------------------------------------------------#
261-
- name: Download gubbins
262-
uses: actions/download-artifact@v8
263-
with:
264-
name: gubbins
265-
path: /tmp/gubbins
266-
267-
- name: Create a new git repository
268-
run: |
269-
git init /tmp/gubbins/
270-
271-
- name: Clone diracx source
201+
- name: Clone diracx source
272202
run: |
273203
cd ..
274204
git clone https://github.com/DIRACGrid/diracx.git
275205
276-
- name: Download gubbins:services image
277-
uses: actions/download-artifact@v8
206+
- name: Download gubbins images
207+
uses: actions/download-artifact@v7
278208
with:
279-
name: gubbins-services-img
209+
name: gubbins-images
280210
path: /tmp/
281211

282-
- name: Load docker image
283-
run: docker load --input /tmp/gubbins_services_image.tar
212+
- name: Load gubbins images
213+
run: |
214+
docker load --input /tmp/gubbins_services_image.tar
215+
rm -f /tmp/gubbins_services_image.tar
216+
docker load --input /tmp/gubbins_client_image.tar
217+
rm -f /tmp/gubbins_client_image.tar
284218
285219
- name: Download gubbins-web
286-
uses: actions/download-artifact@v8
220+
uses: actions/download-artifact@v7
287221
with:
288222
name: gubbins-web
289223
path: /tmp/gubbins-web
290224
# ------------------------------------------------------------------------#
291225
# ========================================================================#
292-
226+
293227
# Runs the demo with the extension source code
294-
- name: Start demo
228+
- name: Start demo
295229
run: |
296230
cd ..
297-
diracx-charts/run_demo.sh --exit-when-done --set-value developer.autoReload=false --ci-values ./diracx/extensions/gubbins_values.yaml --load-docker-image "gubbins/services:dev" diracx/ /tmp/gubbins/ /tmp/gubbins-web/
231+
232+
# Download helm/kubectl/kind first
233+
diracx-charts/run_demo.sh --only-download-deps
234+
235+
# Copy gubbins-charts to a temporary location and build dependencies
236+
cp -r ./diracx/extensions/gubbins-charts /tmp/
237+
diracx-charts/.demo/helm dependency build /tmp/gubbins-charts
238+
# Replace the downloaded subchart with the locally-cloned one to
239+
# ensure we have the pixi-compatible ConfigMap entrypoint
240+
rm -f /tmp/gubbins-charts/charts/diracx-*.tgz
241+
diracx-charts/.demo/helm package diracx-charts/diracx -d /tmp/gubbins-charts/charts/
242+
243+
diracx-charts/run_demo.sh \
244+
--exit-when-done \
245+
--set-value diracx.developer.autoReload=false \
246+
--extension-chart-path /tmp/gubbins-charts \
247+
--ci-values ./diracx/extensions/gubbins_values.yaml \
248+
--load-docker-image "ghcr.io/gubbins/services:dev" \
249+
--load-docker-image "ghcr.io/gubbins/client:dev" \
250+
--prune-loaded-images \
251+
/tmp/gubbins-web/
298252
299253
- name: Debugging information
300254
run: |
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env python3
2+
"""Update diracx-charts with a new diracx-web version.
3+
4+
Bumps the chart version and updates the web image tag in values.yaml.
5+
Does NOT modify appVersion (that tracks the diracx server version).
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import argparse
11+
import re
12+
import sys
13+
from pathlib import Path
14+
15+
16+
def bump_version(current_version: str) -> str:
17+
"""Bump a version: increment alpha number if present, otherwise patch."""
18+
match = re.match(
19+
r"^(\d+\.\d+\.\d+)-alpha\.(\d+)$", current_version
20+
)
21+
if match:
22+
base, alpha = match.group(1), int(match.group(2))
23+
return f"{base}-alpha.{alpha + 1}"
24+
25+
match = re.match(r"^(\d+)\.(\d+)\.(\d+)$", current_version)
26+
if match:
27+
major, minor, patch = match.groups()
28+
return f"{major}.{minor}.{int(patch) + 1}"
29+
30+
raise ValueError(f"Invalid version format: {current_version}")
31+
32+
33+
def main() -> None:
34+
parser = argparse.ArgumentParser(
35+
description="Update diracx-charts for a new diracx-web release"
36+
)
37+
parser.add_argument(
38+
"--charts-dir",
39+
type=Path,
40+
required=True,
41+
help="Path to the diracx-charts repository",
42+
)
43+
parser.add_argument(
44+
"--web-version",
45+
required=True,
46+
help="New diracx-web version (e.g., v0.1.0)",
47+
)
48+
args = parser.parse_args()
49+
50+
chart_yaml = args.charts_dir / "diracx" / "Chart.yaml"
51+
values_yaml = args.charts_dir / "diracx" / "values.yaml"
52+
53+
for path in (chart_yaml, values_yaml):
54+
if not path.exists():
55+
print(f"Error: {path} not found")
56+
sys.exit(1)
57+
58+
# Read and bump chart version
59+
chart_content = chart_yaml.read_text()
60+
version_match = re.search(r'^version:\s*"?([^"\n]+)"?', chart_content, re.MULTILINE)
61+
if not version_match:
62+
print("Error: could not find version in Chart.yaml")
63+
sys.exit(1)
64+
65+
current_chart_version = version_match.group(1)
66+
new_chart_version = bump_version(current_chart_version)
67+
68+
chart_content = re.sub(
69+
r'^version:\s*.*$',
70+
f'version: "{new_chart_version}"',
71+
chart_content,
72+
flags=re.MULTILINE,
73+
)
74+
chart_yaml.write_text(chart_content)
75+
print(f"Chart version: {current_chart_version} -> {new_chart_version}")
76+
77+
# Update web image tag in values.yaml
78+
values_content = values_yaml.read_text()
79+
values_content = re.sub(
80+
r'(^ web:\s*\n tag:\s*).*$',
81+
rf'\g<1>{args.web_version}',
82+
values_content,
83+
flags=re.MULTILINE,
84+
)
85+
values_yaml.write_text(values_content)
86+
print(f"Web image tag: {args.web_version}")
87+
88+
89+
if __name__ == "__main__":
90+
main()

packages/diracx-web/test/e2e/dashboard.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe("DashboardDrawer", { retries: { runMode: 5, openMode: 3 } }, () => {
1111
);
1212
});
1313

14-
cy.visit("/");
14+
cy.visitApp();
1515
});
1616

1717
it("should render the drawer", () => {

packages/diracx-web/test/e2e/importExportState.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ describe("Export and import app state", () => {
55
beforeEach(() => {
66
cy.login();
77

8-
cy.visit("/");
8+
cy.visitApp();
99

1010
// Open 2 Job Monitor apps
1111
cy.get('[data-testid="add-application-button"]').click();

packages/diracx-web/test/e2e/jobMonitor.columns.cy.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import {
99
describe("Job Monitor - Columns", () => {
1010
beforeEach(() => {
1111
cy.login();
12-
13-
cy.visit("/");
1412
setupJobMonitorDashboard();
13+
cy.visitApp();
1514

1615
cy.contains("Job Monitor").click();
1716

0 commit comments

Comments
 (0)