Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions .agents/skills/test-release-canary/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ before installing a snap. The Debian and Kubernetes CLI lanes remove snapd so
they continue to exercise the dev Debian package. Kubernetes pins the matching
`0.0.0-dev` chart and `:dev` images.

RPM package installation also has tmachine conformance coverage in
`Branch E2E Checks` (with `test:e2e`), `Release Dev`, and `Release Tag`. Those
lanes use the `rpm` installer on `fedora-podman-rootful` and
`fedora-podman-rootless` with candidate CLI and
gateway RPMs and matching runtime images. Branch RPM package builds run on
every approved branch run, independently of optional E2E labels.

The host-package jobs exercise fresh installs, not upgrades from a persisted
schema-v1 gateway config. Validate Homebrew and RPM exact-default migration with
the release-tooling and package lifecycle tests before relying on the canary.
Expand Down
34 changes: 29 additions & 5 deletions .github/workflows/branch-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,15 @@ jobs:

version:
needs: [pr_metadata]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_any_e2e == 'true'
if: needs.pr_metadata.outputs.should_run == 'true'
permissions:
contents: read
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
cargo: ${{ steps.version.outputs.cargo }}
rpm_version: ${{ steps.version.outputs.rpm_version }}
rpm_release: ${{ steps.version.outputs.rpm_release }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -99,7 +101,13 @@ jobs:
id: version
run: |
cargo="$(python3 tasks/scripts/release.py get-version --cargo)"
echo "cargo=$cargo" >> "$GITHUB_OUTPUT"
rpm_version="$(python3 tasks/scripts/release.py get-version --dev --rpm-version)"
rpm_release="$(python3 tasks/scripts/release.py get-version --dev --rpm-release)"
{
echo "cargo=$cargo"
echo "rpm_version=$rpm_version"
echo "rpm_release=$rpm_release"
} >> "$GITHUB_OUTPUT"

build-binaries:
needs: version
Expand Down Expand Up @@ -200,14 +208,30 @@ jobs:
packages: write
uses: ./.github/workflows/build-images.yml

build-rpm:
name: Build RPM packages
needs: [pr_metadata, version, build-binaries]
if: needs.pr_metadata.outputs.should_run == 'true'
permissions:
actions: read
contents: read
uses: ./.github/workflows/rpm-package.yml
with:
checkout-ref: ${{ github.sha }}
rpm-version: ${{ needs.version.outputs.rpm_version }}
rpm-release: ${{ needs.version.outputs.rpm_release }}
cargo-version: ${{ needs.version.outputs.cargo }}

prepare-integration:
needs: [pr_metadata, build-binaries, build-images]
needs: [pr_metadata, build-binaries, build-images, build-rpm]
if: needs.pr_metadata.outputs.run_integration == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/prepare-integration-inputs.yml
with:
rpm-artifact-name: rpm-linux-x86_64

# Run driver-independent conformance tests.
conformance-integration:
Expand All @@ -225,8 +249,8 @@ jobs:
[
{"environment":"ubuntu-docker-rootful","installer":"binaries","testsuite":"conformance"},
{"environment":"ubuntu-k3s","installer":"k3s","testsuite":"conformance"},
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"conformance"},
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"conformance"}
{"environment":"fedora-podman-rootful","installer":"rpm","testsuite":"conformance"},
{"environment":"fedora-podman-rootless","installer":"rpm","testsuite":"conformance"}
]

# Run feature-specific integration tests:
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/prepare-integration-inputs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ on:
required: false
type: string
default: ""
rpm-artifact-name:
description: RPM package artifact to include in the tmachine inputs
required: false
type: string
default: ""
outputs:
source_sha:
description: Source revision of the candidate artifacts
Expand Down Expand Up @@ -94,6 +99,37 @@ jobs:
mv artifacts/packages/download/*.deb artifacts/packages/openshell.deb
rmdir artifacts/packages/download

- name: Download RPM package artifact
if: inputs['rpm-artifact-name'] != ''
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ inputs['rpm-artifact-name'] }}
path: artifacts/packages/rpm/download
github-token: ${{ github.token }}
run-id: ${{ inputs['artifact-run-id'] || github.run_id }}

- name: Stage RPM package inputs
if: inputs['rpm-artifact-name'] != ''
run: |
set -euo pipefail
shopt -s nullglob
download_dir=artifacts/packages/rpm/download
cli_rpms=("$download_dir"/openshell-[0-9]*.rpm)
gateway_rpms=("$download_dir"/openshell-gateway-[0-9]*.rpm)
if [[ ${#cli_rpms[@]} -ne 1 || ${#gateway_rpms[@]} -ne 1 ]]; then
echo "candidate artifact must contain exactly one CLI and one gateway RPM" >&2
exit 1
fi
cli_identity=${cli_rpms[0]%.rpm}
gateway_identity=${gateway_rpms[0]%.rpm}
if [[ ${cli_identity##*.} != "${gateway_identity##*.}" ]]; then
echo "candidate CLI and gateway RPM architectures must match" >&2
exit 1
fi
mv "${cli_rpms[0]}" artifacts/packages/rpm/openshell.rpm
mv "${gateway_rpms[0]}" artifacts/packages/rpm/openshell-gateway.rpm
rm -rf "$download_dir"

- name: Log in to GHCR
run: echo "${{ github.token }}" | docker login ghcr.io -u "${GITHUB_ACTOR}" --password-stdin

Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/release-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,15 @@ jobs:
checkout-ref: ${{ github.sha }}

prepare-integration:
needs: [build-binaries, build-deb, build-images]
needs: [build-binaries, build-deb, build-images, build-rpm]
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/prepare-integration-inputs.yml
with:
deb-artifact-name: deb-linux-amd64
rpm-artifact-name: rpm-linux-x86_64

conformance-integration:
needs: prepare-integration
Expand All @@ -122,6 +123,13 @@ jobs:
category: conformance
source-sha: ${{ needs.prepare-integration.outputs.source_sha }}
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
test-matrix: >-
[
{"environment":"ubuntu-docker-rootful","installer":"deb","testsuite":"conformance"},
{"environment":"ubuntu-k3s","installer":"k3s","testsuite":"conformance"},
{"environment":"fedora-podman-rootful","installer":"rpm","testsuite":"conformance"},
{"environment":"fedora-podman-rootless","installer":"rpm","testsuite":"conformance"}
]

feature-specific-integration:
needs: prepare-integration
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}

prepare-integration:
needs: [compute-versions, build-binaries, build-deb, build-images]
needs: [compute-versions, build-binaries, build-deb, build-images, build-rpm]
permissions:
actions: read
contents: read
Expand All @@ -161,6 +161,7 @@ jobs:
with:
source-sha: ${{ needs.compute-versions.outputs.source_sha }}
deb-artifact-name: deb-linux-amd64
rpm-artifact-name: rpm-linux-x86_64

conformance-integration:
needs: prepare-integration
Expand All @@ -173,6 +174,13 @@ jobs:
category: conformance
source-sha: ${{ needs.prepare-integration.outputs.source_sha }}
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
test-matrix: >-
[
{"environment":"ubuntu-docker-rootful","installer":"deb","testsuite":"conformance"},
{"environment":"ubuntu-k3s","installer":"k3s","testsuite":"conformance"},
{"environment":"fedora-podman-rootful","installer":"rpm","testsuite":"conformance"},
{"environment":"fedora-podman-rootless","installer":"rpm","testsuite":"conformance"}
]

feature-specific-integration:
needs: prepare-integration
Expand Down
5 changes: 5 additions & 0 deletions CI.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ Windows checks are not required for merging and do not run in merge queues.
Main and manual runs also build release binaries, with `continue-on-error: true`
so Windows failures do not fail the workflow.

Every approved `Branch E2E Checks` run builds the RPM packages, including
runs without optional E2E labels. Core integration qualification installs the
CLI and gateway RPMs on Fedora with rootful and rootless Podman and runs conformance using
the matching runtime images. Release Dev and Release Tag run the same RPM lane.

Three opt-in labels enable the long-running E2E suites:

- `test:e2e` runs the Docker, rootless Podman, Kubernetes, and VM E2E suites
Expand Down
92 changes: 2 additions & 90 deletions tests/ansible/playbooks/openshell-deb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,94 +21,6 @@
ansible.builtin.apt:
deb: /var/tmp/openshell.deb

- name: Copy OpenShell runtime images
become: true
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "/var/tmp/{{ item.name }}.tar"
mode: "0644"
loop:
- name: openshell-sandbox
src: "{{ openshell_sandbox_image }}"
- name: openshell-supervisor
src: "{{ openshell_supervisor_image }}"

- name: Load OpenShell runtime images
become: true
ansible.builtin.command:
argv:
- docker
- load
- --input
- "/var/tmp/{{ item }}.tar"
loop:
- openshell-sandbox
- openshell-supervisor

# The package normally starts from its built-in runtime-image defaults.
# Qualification instead pins the candidate images staged by tmachine, so
# keep that override separate from the operator-owned gateway.toml.
- name: Create OpenShell qualification configuration directory
become: true
ansible.builtin.file:
path: /var/lib/openshell-qualification
state: directory
owner: root
group: root
mode: "0755"

- name: Configure candidate OpenShell runtime images for qualification
become: true
ansible.builtin.copy:
dest: /var/lib/openshell-qualification/gateway.toml
owner: root
group: root
mode: "0644"
content: |
[openshell]
version = 2

[openshell.drivers.docker]
sandbox_runtime_image = "docker.io/openshell/sandbox:tmachine"
supervisor_image = "docker.io/openshell/supervisor:tmachine"

- name: Create OpenShell environment directory
ansible.builtin.file:
path: /home/tmachine/.config/openshell
state: directory
mode: "0700"

- name: Select qualification gateway configuration
ansible.builtin.copy:
dest: /home/tmachine/.config/openshell/gateway.env
mode: "0600"
content: |
OPENSHELL_GATEWAY_CONFIG=/var/lib/openshell-qualification/gateway.toml

- name: Start tmachine user manager
ansible.builtin.include_role:
name: tmachine_user_manager

- name: Start packaged OpenShell gateway service
ansible.builtin.systemd_service:
name: openshell-gateway.service
scope: user
daemon_reload: true
enabled: true
state: started
environment:
XDG_RUNTIME_DIR: /run/user/1000
DBUS_SESSION_BUS_ADDRESS: unix:path=/run/user/1000/bus

- name: Wait for OpenShell gateway
ansible.builtin.wait_for:
host: 127.0.0.1
port: 17670
timeout: 60

- name: Register packaged OpenShell gateway
- name: Prepare packaged OpenShell gateway
ansible.builtin.include_role:
name: openshell_client
vars:
openshell_client_gateway_endpoint: https://127.0.0.1:17670
openshell_client_gateway_name: openshell
name: openshell_packaged_gateway
34 changes: 34 additions & 0 deletions tests/ansible/playbooks/openshell-rpm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

---
- name: Install OpenShell RPM packages
hosts: all
gather_facts: false
tasks:
- name: Wait for SSH
ansible.builtin.wait_for_connection:

- name: Copy OpenShell RPM packages
become: true
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "/var/tmp/{{ item.name }}.rpm"
mode: "0644"
loop:
- { name: openshell, src: "{{ openshell_rpm }}" }
- { name: openshell-gateway, src: "{{ openshell_gateway_rpm }}" }

- name: Install OpenShell RPM packages
become: true
ansible.builtin.dnf:
name:
- /var/tmp/openshell.rpm
- /var/tmp/openshell-gateway.rpm
state: present
disable_gpg_check: true
allow_downgrade: true

- name: Prepare packaged OpenShell gateway
ansible.builtin.include_role:
name: openshell_packaged_gateway
Loading
Loading