Skip to content

Commit c8ab35d

Browse files
committed
test(tmachine): qualify RPM package upgrades
Signed-off-by: Evan Lezar <elezar@nvidia.com>
1 parent 878d186 commit c8ab35d

10 files changed

Lines changed: 608 additions & 26 deletions

File tree

‎.agents/skills/test-release-canary/SKILL.md‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ rolling dev release produced by the triggering workflow. Kubernetes pins the
2929
matching `0.0.0-dev` chart and `:dev` images.
3030

3131
The host-package jobs exercise fresh installs, not upgrades from persisted
32-
gateway state. Release Dev and Release Tag additionally run the tmachine Ubuntu
33-
DEB upgrade lane: it installs the latest retained prerelease source, upgrades
34-
to the candidate DEB, verifies an existing sandbox survives, and creates a new
35-
sandbox. That lane is part of the release conformance matrix, not this canary.
36-
Validate Homebrew and RPM exact-default migration with the release-tooling and
37-
package lifecycle tests before relying on the canary.
32+
gateway state. Release Dev and Release Tag additionally run tmachine Ubuntu DEB
33+
and Fedora RPM upgrade lanes: they install the latest retained prerelease
34+
packages and matching runtime images, upgrade to the candidate packages, verify
35+
an existing sandbox survives, and create a new sandbox. Those lanes are part of
36+
the release conformance matrix, not this canary. Validate Homebrew exact-default
37+
migration with the release-tooling and package lifecycle tests before relying
38+
on the canary.
3839

3940
The canary does not install or import `@nvidia/openshell-sdk`. TypeScript SDK
4041
validation lives in the `TypeScript SDK` branch check, including a publish

‎.github/workflows/branch-e2e.yml‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ jobs:
9595
outputs:
9696
cargo: ${{ steps.version.outputs.cargo }}
9797
deb: ${{ steps.version.outputs.deb }}
98+
rpm_version: ${{ steps.version.outputs.rpm_version }}
99+
rpm_release: ${{ steps.version.outputs.rpm_release }}
98100
steps:
99101
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
100102
with:
@@ -106,9 +108,13 @@ jobs:
106108
run: |
107109
cargo="$(python3 tasks/scripts/release.py get-version --cargo)"
108110
deb="$(python3 tasks/scripts/release.py get-version --dev --deb)"
111+
rpm_version="$(python3 tasks/scripts/release.py get-version --dev --rpm-version)"
112+
rpm_release="$(python3 tasks/scripts/release.py get-version --dev --rpm-release)"
109113
{
110114
echo "cargo=$cargo"
111115
echo "deb=$deb"
116+
echo "rpm_version=$rpm_version"
117+
echo "rpm_release=$rpm_release"
112118
} >> "$GITHUB_OUTPUT"
113119
114120
build-binaries:
@@ -232,9 +238,23 @@ jobs:
232238
deb-version: ${{ needs.version.outputs.deb }}
233239
checkout-ref: ${{ github.sha }}
234240

241+
build-rpm-upgrade:
242+
name: Build RPM packages for upgrade qualification
243+
needs: [pr_metadata, version, build-binaries]
244+
if: needs.pr_metadata.outputs.run_integration_upgrades == 'true'
245+
permissions:
246+
actions: read
247+
contents: read
248+
uses: ./.github/workflows/rpm-package.yml
249+
with:
250+
checkout-ref: ${{ github.sha }}
251+
rpm-version: ${{ needs.version.outputs.rpm_version }}
252+
rpm-release: ${{ needs.version.outputs.rpm_release }}
253+
cargo-version: ${{ needs.version.outputs.cargo }}
254+
235255
prepare-integration-upgrades:
236256
name: Prepare upgrade qualification inputs
237-
needs: [pr_metadata, build-binaries, build-images, build-deb-upgrade]
257+
needs: [pr_metadata, build-binaries, build-images, build-deb-upgrade, build-rpm-upgrade]
238258
if: needs.pr_metadata.outputs.run_integration_upgrades == 'true'
239259
permissions:
240260
actions: read
@@ -243,7 +263,9 @@ jobs:
243263
uses: ./.github/workflows/prepare-integration-inputs.yml
244264
with:
245265
deb-artifact-name: deb-linux-amd64
266+
rpm-artifact-name: rpm-linux-x86_64
246267
include-deb-upgrade-source: true
268+
include-rpm-upgrade-source: true
247269

248270
integration-upgrades:
249271
name: Integration upgrades
@@ -259,7 +281,8 @@ jobs:
259281
integration-inputs-artifact-id: ${{ needs.prepare-integration-upgrades.outputs.integration_inputs_artifact_id }}
260282
test-matrix: >-
261283
[
262-
{"environment":"ubuntu-docker-rootful","installer":"deb-upgrade-source","testsuite":"deb-upgrade"}
284+
{"environment":"ubuntu-docker-rootful","installer":"deb-upgrade-source","testsuite":"deb-upgrade"},
285+
{"environment":"fedora-podman-rootless","installer":"rpm-upgrade-source","testsuite":"rpm-upgrade"}
263286
]
264287
265288
# Run driver-independent conformance tests.

‎.github/workflows/prepare-integration-inputs.yml‎

Lines changed: 155 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,21 @@ on:
1616
required: false
1717
type: string
1818
default: ""
19+
rpm-artifact-name:
20+
description: RPM package artifact to include in the tmachine inputs
21+
required: false
22+
type: string
23+
default: ""
1924
include-deb-upgrade-source:
2025
description: Include the latest retained prerelease DEB and runtime images as upgrade inputs
2126
required: false
2227
type: boolean
2328
default: false
29+
include-rpm-upgrade-source:
30+
description: Include the latest retained prerelease RPMs and runtime images as upgrade inputs
31+
required: false
32+
type: boolean
33+
default: false
2434
outputs:
2535
source_sha:
2636
description: Source revision of the candidate artifacts
@@ -91,6 +101,30 @@ jobs:
91101
mv artifacts/packages/download/*.deb artifacts/packages/openshell.deb
92102
rmdir artifacts/packages/download
93103
104+
- name: Download RPM package artifact
105+
if: inputs['rpm-artifact-name'] != ''
106+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
107+
with:
108+
name: ${{ inputs['rpm-artifact-name'] }}
109+
path: artifacts/packages/rpm/download
110+
github-token: ${{ github.token }}
111+
run-id: ${{ inputs['artifact-run-id'] || github.run_id }}
112+
113+
- name: Stage RPM package inputs
114+
if: inputs['rpm-artifact-name'] != ''
115+
run: |
116+
set -euo pipefail
117+
download_dir=artifacts/packages/rpm/download
118+
cli_rpm=$(find "$download_dir" -maxdepth 1 -type f -name 'openshell-[0-9]*.x86_64.rpm' -print -quit)
119+
gateway_rpm=$(find "$download_dir" -maxdepth 1 -type f -name 'openshell-gateway-[0-9]*.x86_64.rpm' -print -quit)
120+
if [[ -z "$cli_rpm" || -z "$gateway_rpm" ]]; then
121+
echo "candidate artifact did not contain the expected x86_64 CLI and gateway RPMs" >&2
122+
exit 1
123+
fi
124+
mv "$cli_rpm" artifacts/packages/rpm/openshell.rpm
125+
mv "$gateway_rpm" artifacts/packages/rpm/openshell-gateway.rpm
126+
rm -rf "$download_dir"
127+
94128
- name: Resolve prerelease Debian upgrade source
95129
if: inputs['include-deb-upgrade-source']
96130
id: upgrade-source
@@ -160,22 +194,25 @@ jobs:
160194
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
161195
with:
162196
name: ${{ steps.upgrade-source.outputs.artifact }}
163-
path: artifacts/upgrade/source/download
197+
path: artifacts/upgrade/deb/source/download
164198
github-token: ${{ github.token }}
165199
run-id: ${{ steps.upgrade-source.outputs['run-id'] }}
166200

167201
- name: Stage prerelease Debian upgrade source
168202
if: inputs['include-deb-upgrade-source']
169203
run: |
170204
set -euo pipefail
171-
source_dir=artifacts/upgrade/source
205+
source_dir=artifacts/upgrade/deb/source
172206
download_dir="${source_dir}/download"
173207
deb_path=$(find "$download_dir" -maxdepth 1 -type f -name 'openshell_*_amd64.deb' -print -quit)
174208
if [[ -z "$deb_path" || ! -f "${download_dir}/openshell-checksums-sha256.txt" ]]; then
175209
echo "prerelease source artifact did not contain the expected Debian package and checksums" >&2
176210
exit 1
177211
fi
178-
grep -F " $(basename "$deb_path")" "${download_dir}/openshell-checksums-sha256.txt" | sha256sum --check --status
212+
(
213+
cd "$download_dir"
214+
grep -F " $(basename "$deb_path")" openshell-checksums-sha256.txt | sha256sum --check --status
215+
)
179216
mv "$deb_path" "${source_dir}/openshell.deb"
180217
mv "${download_dir}/openshell-checksums-sha256.txt" "${source_dir}/openshell-checksums-sha256.txt"
181218
rmdir "$download_dir"
@@ -188,15 +225,127 @@ jobs:
188225
run: |
189226
set -euo pipefail
190227
image_tag="${IMAGE_TAG#v}"
191-
mkdir -p artifacts/upgrade/source
228+
mkdir -p artifacts/upgrade/deb/source
229+
230+
docker pull "ghcr.io/nvidia/openshell/sandbox:${image_tag}"
231+
docker tag "ghcr.io/nvidia/openshell/sandbox:${image_tag}" openshell/sandbox:tmachine
232+
docker save --output artifacts/upgrade/deb/source/openshell-sandbox-tmachine.tar openshell/sandbox:tmachine
233+
234+
docker pull "ghcr.io/nvidia/openshell/supervisor:${image_tag}"
235+
docker tag "ghcr.io/nvidia/openshell/supervisor:${image_tag}" openshell/supervisor:tmachine
236+
docker save --output artifacts/upgrade/deb/source/openshell-supervisor-tmachine.tar openshell/supervisor:tmachine
237+
238+
- name: Resolve prerelease RPM upgrade source
239+
if: inputs['include-rpm-upgrade-source']
240+
id: rpm-upgrade-source
241+
env:
242+
GH_TOKEN: ${{ github.token }}
243+
run: |
244+
set -euo pipefail
245+
successful_run_ids=$(gh api --paginate \
246+
"repos/${GITHUB_REPOSITORY}/actions/workflows/release-tag.yml/runs?status=success&per_page=100" \
247+
--jq '.workflow_runs[] | select(.status == "completed" and .conclusion == "success") | .id')
248+
artifact_records=$(gh api --paginate \
249+
"repos/${GITHUB_REPOSITORY}/actions/artifacts?per_page=100" \
250+
--jq '.artifacts[] | select(.expired == false) | [.workflow_run.id, .name] | @tsv')
251+
source_tag=$(printf '%s\n--ARTIFACTS--\n%s\n' "$successful_run_ids" "$artifact_records" | awk -F '\t' '
252+
$0 == "--ARTIFACTS--" {
253+
reading_artifacts = 1
254+
next
255+
}
256+
!reading_artifacts {
257+
if ($1 ~ /^[0-9]+$/) successful_runs[$1] = 1
258+
next
259+
}
260+
$1 in successful_runs && $2 ~ /^openshell-v[0-9]+\.[0-9]+\.[0-9]+-pre\.[1-9][0-9]*-linux-x86_64-rpm$/ {
261+
tag = $2
262+
sub(/^openshell-/, "", tag)
263+
sub(/-linux-x86_64-rpm$/, "", tag)
264+
version = tag
265+
sub(/^v/, "", version)
266+
split(version, parts, "-pre\\.")
267+
split(parts[1], core, "\\.")
268+
sequence = parts[2] + 0
269+
if (!found || core[1] + 0 > major ||
270+
(core[1] + 0 == major && core[2] + 0 > minor) ||
271+
(core[1] + 0 == major && core[2] + 0 == minor && core[3] + 0 > patch) ||
272+
(core[1] + 0 == major && core[2] + 0 == minor && core[3] + 0 == patch && sequence > prerelease)) {
273+
selected = tag
274+
major = core[1] + 0
275+
minor = core[2] + 0
276+
patch = core[3] + 0
277+
prerelease = sequence
278+
found = 1
279+
}
280+
}
281+
END {
282+
if (found) print selected
283+
}')
284+
if [[ -z "$source_tag" ]]; then
285+
echo "no retained prerelease RPM artifact is available" >&2
286+
exit 1
287+
fi
288+
source_artifact="openshell-${source_tag}-linux-x86_64-rpm"
289+
source_run_id=$(gh api \
290+
"repos/${GITHUB_REPOSITORY}/actions/artifacts?name=${source_artifact}&per_page=100" \
291+
--jq '[.artifacts[] | select(.expired == false)] | sort_by(.created_at) | last | .workflow_run.id')
292+
if [[ -z "$source_run_id" || "$source_run_id" == "null" ]]; then
293+
echo "no retained artifact run is available for ${source_artifact}" >&2
294+
exit 1
295+
fi
296+
{
297+
echo "tag=${source_tag}"
298+
echo "artifact=${source_artifact}"
299+
echo "run-id=${source_run_id}"
300+
} >> "$GITHUB_OUTPUT"
301+
302+
- name: Download prerelease RPM upgrade source
303+
if: inputs['include-rpm-upgrade-source']
304+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
305+
with:
306+
name: ${{ steps.rpm-upgrade-source.outputs.artifact }}
307+
path: artifacts/upgrade/rpm/source/download
308+
github-token: ${{ github.token }}
309+
run-id: ${{ steps.rpm-upgrade-source.outputs['run-id'] }}
310+
311+
- name: Stage prerelease RPM upgrade source
312+
if: inputs['include-rpm-upgrade-source']
313+
run: |
314+
set -euo pipefail
315+
source_dir=artifacts/upgrade/rpm/source
316+
download_dir="${source_dir}/download"
317+
cli_rpm=$(find "$download_dir" -maxdepth 1 -type f -name 'openshell-[0-9]*.x86_64.rpm' -print -quit)
318+
gateway_rpm=$(find "$download_dir" -maxdepth 1 -type f -name 'openshell-gateway-[0-9]*.x86_64.rpm' -print -quit)
319+
if [[ -z "$cli_rpm" || -z "$gateway_rpm" || ! -f "${download_dir}/openshell-checksums-sha256.txt" ]]; then
320+
echo "prerelease source artifact did not contain the expected RPMs and checksums" >&2
321+
exit 1
322+
fi
323+
(
324+
cd "$download_dir"
325+
grep -F " $(basename "$cli_rpm")" openshell-checksums-sha256.txt | sha256sum --check --status
326+
grep -F " $(basename "$gateway_rpm")" openshell-checksums-sha256.txt | sha256sum --check --status
327+
)
328+
mv "$cli_rpm" "${source_dir}/openshell.rpm"
329+
mv "$gateway_rpm" "${source_dir}/openshell-gateway.rpm"
330+
mv "${download_dir}/openshell-checksums-sha256.txt" "${source_dir}/openshell-checksums-sha256.txt"
331+
rm -rf "$download_dir"
332+
333+
- name: Export prerelease runtime images for RPM upgrade source
334+
if: inputs['include-rpm-upgrade-source']
335+
env:
336+
IMAGE_TAG: ${{ steps.rpm-upgrade-source.outputs.tag }}
337+
run: |
338+
set -euo pipefail
339+
image_tag="${IMAGE_TAG#v}"
340+
mkdir -p artifacts/upgrade/rpm/source
192341
193342
docker pull "ghcr.io/nvidia/openshell/sandbox:${image_tag}"
194343
docker tag "ghcr.io/nvidia/openshell/sandbox:${image_tag}" openshell/sandbox:tmachine
195-
docker save --output artifacts/upgrade/source/openshell-sandbox-tmachine.tar openshell/sandbox:tmachine
344+
docker save --output artifacts/upgrade/rpm/source/openshell-sandbox-tmachine.tar openshell/sandbox:tmachine
196345
197346
docker pull "ghcr.io/nvidia/openshell/supervisor:${image_tag}"
198347
docker tag "ghcr.io/nvidia/openshell/supervisor:${image_tag}" openshell/supervisor:tmachine
199-
docker save --output artifacts/upgrade/source/openshell-supervisor-tmachine.tar openshell/supervisor:tmachine
348+
docker save --output artifacts/upgrade/rpm/source/openshell-supervisor-tmachine.tar openshell/supervisor:tmachine
200349
201350
- name: Log in to GHCR
202351
run: echo "${{ github.token }}" | docker login ghcr.io -u "${GITHUB_ACTOR}" --password-stdin

‎.github/workflows/release-dev.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,17 @@ jobs:
102102
checkout-ref: ${{ github.sha }}
103103

104104
prepare-integration:
105-
needs: [build-binaries, build-deb, build-images]
105+
needs: [build-binaries, build-deb, build-images, build-rpm]
106106
permissions:
107107
actions: read
108108
contents: read
109109
packages: read
110110
uses: ./.github/workflows/prepare-integration-inputs.yml
111111
with:
112112
deb-artifact-name: deb-linux-amd64
113+
rpm-artifact-name: rpm-linux-x86_64
113114
include-deb-upgrade-source: true
115+
include-rpm-upgrade-source: true
114116

115117
conformance-integration:
116118
needs: prepare-integration
@@ -127,6 +129,7 @@ jobs:
127129
[
128130
{"environment":"ubuntu-docker-rootful","installer":"deb","testsuite":"conformance"},
129131
{"environment":"ubuntu-docker-rootful","installer":"deb-upgrade-source","testsuite":"deb-upgrade"},
132+
{"environment":"fedora-podman-rootless","installer":"rpm-upgrade-source","testsuite":"rpm-upgrade"},
130133
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"conformance"},
131134
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"conformance"}
132135
]

‎.github/workflows/release-tag.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,17 @@ jobs:
130130
checkout-ref: ${{ needs.compute-versions.outputs.source_sha }}
131131

132132
prepare-integration:
133-
needs: [compute-versions, build-binaries, build-deb, build-images]
133+
needs: [compute-versions, build-binaries, build-deb, build-images, build-rpm]
134134
permissions:
135135
actions: read
136136
contents: read
137137
packages: read
138138
uses: ./.github/workflows/prepare-integration-inputs.yml
139139
with:
140140
deb-artifact-name: deb-linux-amd64
141+
rpm-artifact-name: rpm-linux-x86_64
141142
include-deb-upgrade-source: true
143+
include-rpm-upgrade-source: true
142144

143145
conformance-integration:
144146
needs: prepare-integration
@@ -155,6 +157,7 @@ jobs:
155157
[
156158
{"environment":"ubuntu-docker-rootful","installer":"deb","testsuite":"conformance"},
157159
{"environment":"ubuntu-docker-rootful","installer":"deb-upgrade-source","testsuite":"deb-upgrade"},
160+
{"environment":"fedora-podman-rootless","installer":"rpm-upgrade-source","testsuite":"rpm-upgrade"},
158161
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"conformance"},
159162
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"conformance"}
160163
]

0 commit comments

Comments
 (0)