Release Canary #1469
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Canary | |
| on: | |
| workflow_dispatch: | |
| workflow_run: | |
| workflows: ["Release Dev"] | |
| types: [completed] | |
| permissions: | |
| actions: read | |
| contents: read | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| OPENSHELL_VERSION: dev | |
| OPENSHELL_TELEMETRY_ENABLED: "false" | |
| jobs: | |
| macos: | |
| name: macOS Homebrew | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: macos-latest-xlarge | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Ensure VM driver | |
| run: | | |
| launchctl setenv OPENSHELL_COMPUTE_DRIVER vm | |
| launchctl setenv OPENSHELL_TELEMETRY_ENABLED "$OPENSHELL_TELEMETRY_ENABLED" | |
| - name: Install and check gateway status | |
| run: | | |
| set -euo pipefail | |
| curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh | sh | |
| openshell --version | |
| openshell status | |
| # GitHub-hosted macOS runners do not expose the Hypervisor.framework | |
| # support libkrun needs. Sandbox launch is covered by the VM E2E lane. | |
| - name: Collect Homebrew diagnostics | |
| if: failure() | |
| run: | | |
| set +e | |
| brew services info openshell | |
| for log in \ | |
| "$(brew --prefix)/var/log/openshell/openshell-gateway.out.log" \ | |
| "$(brew --prefix)/var/log/openshell/openshell-gateway.err.log"; do | |
| if [ -f "$log" ]; then | |
| echo "--- $log ---" | |
| tail -n 300 "$log" | |
| fi | |
| done | |
| ubuntu-deb: | |
| name: Ubuntu DEB | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Remove snapd | |
| run: | | |
| set -euo pipefail | |
| snaps=$(snap list 2>/dev/null | awk 'NR > 1 { print $1 }') | |
| if [ -n "$snaps" ]; then | |
| sudo snap remove $snaps | |
| fi | |
| sudo apt-get -y --purge remove snapd | |
| ! command -v snap >/dev/null 2>&1 | |
| - name: Ensure Docker | |
| run: | | |
| if ! command -v docker >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install -y docker.io | |
| fi | |
| sudo systemctl start docker || sudo service docker start | |
| mkdir -p "${HOME}/.config/openshell" | |
| printf 'OPENSHELL_COMPUTE_DRIVER=docker\nOPENSHELL_TELEMETRY_ENABLED=%s\n' \ | |
| "$OPENSHELL_TELEMETRY_ENABLED" > "${HOME}/.config/openshell/gateway.env" | |
| docker info | |
| - name: Install and check status | |
| run: | | |
| set -euo pipefail | |
| curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh | sh | |
| openshell status | |
| sandbox="rc-${GITHUB_RUN_ID}" | |
| openshell sandbox create --name "$sandbox" --detach | |
| openshell sandbox exec --name "$sandbox" --no-tty -- true | |
| openshell sandbox delete "$sandbox" | |
| fedora: | |
| name: Fedora RPM | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: linux-amd64-cpu8 | |
| timeout-minutes: 20 | |
| env: | |
| FEDORA_CANARY_CONTAINER: openshell-fedora-canary-${{ github.run_id }}-${{ github.run_attempt }} | |
| steps: | |
| - name: Start Fedora systemd container and root user manager | |
| run: | | |
| set -euo pipefail | |
| docker run --detach \ | |
| --name "${FEDORA_CANARY_CONTAINER}" \ | |
| --privileged \ | |
| --cgroupns=host \ | |
| --tmpfs /run \ | |
| --tmpfs /tmp \ | |
| --volume /sys/fs/cgroup:/sys/fs/cgroup:rw \ | |
| fedora:latest \ | |
| bash -lc 'dnf install -y curl dbus-daemon podman systemd && exec /usr/sbin/init' | |
| for _ in $(seq 1 120); do | |
| if docker exec "${FEDORA_CANARY_CONTAINER}" systemctl list-units --no-pager >/dev/null 2>&1; then | |
| break | |
| fi | |
| if [ "$(docker inspect -f '{{.State.Running}}' "${FEDORA_CANARY_CONTAINER}")" != "true" ]; then | |
| echo "::error::Fedora systemd container exited before systemd became reachable" | |
| docker logs "${FEDORA_CANARY_CONTAINER}" >&2 || true | |
| exit 1 | |
| fi | |
| sleep 1 | |
| done | |
| if ! docker exec "${FEDORA_CANARY_CONTAINER}" systemctl list-units --no-pager >/dev/null 2>&1; then | |
| echo "::error::Fedora systemd container did not become reachable within 120s" | |
| docker logs "${FEDORA_CANARY_CONTAINER}" >&2 || true | |
| exit 1 | |
| fi | |
| docker exec --interactive "${FEDORA_CANARY_CONTAINER}" env \ | |
| HOME=/root \ | |
| XDG_RUNTIME_DIR=/run/user/0 \ | |
| DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus \ | |
| bash -s <<'EOF' | |
| set -euo pipefail | |
| # install.sh manages the RPM gateway as a systemd user unit. This | |
| # container is booted with systemd as PID 1, but it still has no | |
| # login session. Start root's user manager explicitly so the | |
| # installer can test service restart and gateway registration | |
| # instead of its "restart later" fallback. | |
| mkdir -p "${XDG_RUNTIME_DIR}" | |
| chmod 700 "${XDG_RUNTIME_DIR}" | |
| systemctl start user-runtime-dir@0.service || true | |
| systemctl start user@0.service | |
| for _ in $(seq 1 30); do | |
| if systemctl --user daemon-reload; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| if ! systemctl --user daemon-reload; then | |
| systemctl status user@0.service --no-pager >&2 || true | |
| journalctl -u user@0.service --no-pager -n 80 >&2 || true | |
| systemctl --user status --no-pager >&2 || true | |
| exit 1 | |
| fi | |
| EOF | |
| - name: Install and check status | |
| run: | | |
| set -euo pipefail | |
| docker exec --interactive "${FEDORA_CANARY_CONTAINER}" env \ | |
| HOME=/root \ | |
| XDG_RUNTIME_DIR=/run/user/0 \ | |
| DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus \ | |
| OPENSHELL_VERSION="$OPENSHELL_VERSION" \ | |
| OPENSHELL_TELEMETRY_ENABLED="$OPENSHELL_TELEMETRY_ENABLED" \ | |
| CANARY_SANDBOX="rc-${GITHUB_RUN_ID}" \ | |
| INSTALL_SH_URL="https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh" \ | |
| bash -s <<'EOF' | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.config/openshell" | |
| printf 'OPENSHELL_COMPUTE_DRIVER=podman\nOPENSHELL_TELEMETRY_ENABLED=%s\n' \ | |
| "$OPENSHELL_TELEMETRY_ENABLED" > "${HOME}/.config/openshell/gateway.env" | |
| podman info | |
| curl -LsSf "${INSTALL_SH_URL}" | sh | |
| openshell status | |
| openshell sandbox create --name "$CANARY_SANDBOX" --detach | |
| openshell sandbox exec --name "$CANARY_SANDBOX" --no-tty -- true | |
| openshell sandbox delete "$CANARY_SANDBOX" | |
| EOF | |
| - name: Stop Fedora systemd container | |
| if: always() | |
| run: | | |
| docker rm -f "${FEDORA_CANARY_CONTAINER}" >/dev/null 2>&1 || true | |
| ubuntu-snap-system-docker: | |
| name: Ubuntu Snap with system Docker | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Install snapd | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y snapd | |
| sudo systemctl enable --now snapd.socket | |
| sudo systemctl start snapd | |
| sudo snap wait system seed.loaded | |
| - name: Ensure Docker | |
| run: | | |
| set -euo pipefail | |
| if ! command -v docker >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install -y docker.io | |
| fi | |
| sudo systemctl start docker || sudo service docker start | |
| docker info | |
| - name: Install and check status | |
| run: | | |
| set -euo pipefail | |
| sudo systemctl set-environment \ | |
| "OPENSHELL_TELEMETRY_ENABLED=${OPENSHELL_TELEMETRY_ENABLED}" | |
| curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh | sh | |
| sudo snap list openshell | |
| if sudo snap list docker >/dev/null 2>&1; then | |
| echo "install.sh unexpectedly installed the Docker snap" >&2 | |
| exit 1 | |
| fi | |
| snap info openshell | grep -E '^tracking: +latest/edge$' | |
| docker info | |
| sudo snap connections openshell | grep -E '^docker +openshell:docker +:docker +' | |
| openshell --version | |
| sudo snap services openshell | |
| openshell status | |
| - name: Create and exercise a sandbox | |
| run: | | |
| set -euo pipefail | |
| sandbox="rc-system-docker-${GITHUB_RUN_ID}" | |
| openshell sandbox create --name "$sandbox" --detach | |
| openshell sandbox exec --name "$sandbox" --no-tty -- true | |
| openshell sandbox delete "$sandbox" | |
| - name: Collect Snap diagnostics | |
| if: failure() | |
| run: | | |
| set +e | |
| docker info | |
| sudo systemctl status docker.service --no-pager | |
| sudo journalctl -b -u docker.service --no-pager -n 300 | |
| sudo snap services openshell | |
| sudo snap connections openshell | |
| sudo snap changes | |
| sudo systemctl status snap.openshell.gateway.service --no-pager | |
| sudo journalctl -b -u snap.openshell.gateway.service --no-pager -n 300 | |
| sudo journalctl -b -u snapd.service --no-pager -n 300 | |
| sudo snap logs openshell.gateway -n=300 | |
| sudo ss -ltnp '( sport = :17670 )' | |
| ubuntu-snap-docker-preflight: | |
| name: Ubuntu Snap Docker preflight | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Install snapd | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y snapd | |
| sudo systemctl enable --now snapd.socket | |
| sudo systemctl start snapd | |
| sudo snap wait system seed.loaded | |
| - name: Remove system Docker | |
| run: | | |
| set -euo pipefail | |
| sudo systemctl stop docker.service docker.socket 2>/dev/null || true | |
| sudo apt-get -y --purge remove docker-ce docker-ce-cli containerd.io \ | |
| docker-buildx-plugin docker-compose-plugin docker.io 2>/dev/null || true | |
| ! command -v docker >/dev/null 2>&1 | |
| - name: Verify installer rejects missing Docker | |
| run: | | |
| set -euo pipefail | |
| curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh -o install.sh | |
| if OPENSHELL_VERSION=dev sh install.sh >install.log 2>&1; then | |
| echo "install.sh unexpectedly succeeded without Docker" >&2 | |
| cat install.log >&2 | |
| exit 1 | |
| fi | |
| cat install.log | |
| grep -F "Docker is required before installing the OpenShell snap" install.log | |
| ! sudo snap list docker >/dev/null 2>&1 | |
| ! sudo snap list openshell >/dev/null 2>&1 | |
| - name: Verify installer rejects Docker snap | |
| run: | | |
| set -euo pipefail | |
| sudo snap install docker | |
| if OPENSHELL_VERSION=dev sh install.sh >docker-snap.log 2>&1; then | |
| echo "install.sh unexpectedly succeeded with the Docker snap" >&2 | |
| cat docker-snap.log >&2 | |
| exit 1 | |
| fi | |
| cat docker-snap.log | |
| grep -F "the Docker snap is not currently compatible with OpenShell" docker-snap.log | |
| sudo snap list docker >/dev/null | |
| ! sudo snap list openshell >/dev/null 2>&1 | |
| - name: Collect Snap diagnostics | |
| if: failure() | |
| run: | | |
| set +e | |
| cat install.log | |
| cat docker-snap.log | |
| sudo snap changes | |
| sudo journalctl -b -u snapd.service --no-pager -n 300 | |
| kubernetes: | |
| name: Kubernetes Helm (kind) | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| env: | |
| KIND_CLUSTER_NAME: release-canary-${{ github.run_id }} | |
| RELEASE_NAME: openshell | |
| RELEASE_NAMESPACE: openshell | |
| KIND_GATEWAY_NAME: kind | |
| AGENT_SANDBOX_VERSION: v1.0.3 | |
| steps: | |
| - name: Checkout Agent Sandbox helper | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| sparse-checkout: | | |
| e2e/support/install-agent-sandbox.sh | |
| sparse-checkout-cone-mode: false | |
| persist-credentials: false | |
| - name: Install Helm | |
| uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1 | |
| - name: Create kind cluster | |
| uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0 | |
| with: | |
| cluster_name: ${{ env.KIND_CLUSTER_NAME }} | |
| wait: 120s | |
| - name: Install Agent Sandbox controller | |
| run: bash e2e/support/install-agent-sandbox.sh | |
| - name: Install OpenShell Helm chart from GHCR OCI | |
| run: | | |
| set -euo pipefail | |
| helm install "$RELEASE_NAME" oci://ghcr.io/nvidia/openshell/helm-chart \ | |
| --version 0.0.0-dev \ | |
| --namespace "$RELEASE_NAMESPACE" --create-namespace \ | |
| --set server.disableTls=true \ | |
| --set server.auth.allowUnauthenticatedUsers=true \ | |
| --set "server.telemetryEnabled=${OPENSHELL_TELEMETRY_ENABLED}" \ | |
| --wait --timeout 5m | |
| - name: Verify gateway pod is Ready | |
| run: | | |
| set -euo pipefail | |
| kubectl wait --namespace "$RELEASE_NAMESPACE" \ | |
| --for=condition=Ready pod \ | |
| --selector="app.kubernetes.io/name=openshell,app.kubernetes.io/instance=${RELEASE_NAME}" \ | |
| --timeout=300s | |
| - name: Port-forward gateway service | |
| run: | | |
| set -euo pipefail | |
| nohup kubectl port-forward --namespace "$RELEASE_NAMESPACE" \ | |
| "svc/${RELEASE_NAME}" 8080:8080 \ | |
| > port-forward.log 2>&1 & | |
| echo $! > port-forward.pid | |
| for _ in $(seq 1 30); do | |
| if (echo > /dev/tcp/127.0.0.1/8080) >/dev/null 2>&1; then | |
| echo "port-forward is reachable" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "port-forward did not become reachable" >&2 | |
| cat port-forward.log >&2 | |
| exit 1 | |
| - name: Remove snapd | |
| run: | | |
| set -euo pipefail | |
| snaps=$(snap list 2>/dev/null | awk 'NR > 1 { print $1 }') | |
| if [ -n "$snaps" ]; then | |
| sudo snap remove $snaps | |
| fi | |
| sudo apt-get -y --purge remove snapd | |
| ! command -v snap >/dev/null 2>&1 | |
| - name: Install OpenShell CLI | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.config/openshell" | |
| printf 'OPENSHELL_COMPUTE_DRIVER=docker\n' > "${HOME}/.config/openshell/gateway.env" | |
| curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh | sh | |
| - name: Register kind gateway and check status | |
| run: | | |
| set -euo pipefail | |
| openshell gateway add http://127.0.0.1:8080 --local --name "$KIND_GATEWAY_NAME" | |
| openshell status | |
| sandbox="rc-${GITHUB_RUN_ID}" | |
| openshell sandbox create --name "$sandbox" --detach | |
| openshell sandbox exec --name "$sandbox" --no-tty -- true | |
| openshell sandbox delete "$sandbox" | |
| - name: Diagnostics on failure | |
| if: failure() | |
| run: | | |
| set +e | |
| echo "--- helm status ---" | |
| helm status "$RELEASE_NAME" --namespace "$RELEASE_NAMESPACE" | |
| echo "--- helm get manifest ---" | |
| helm get manifest "$RELEASE_NAME" --namespace "$RELEASE_NAMESPACE" | |
| echo "--- get all ---" | |
| kubectl get all --namespace "$RELEASE_NAMESPACE" | |
| echo "--- describe pods ---" | |
| kubectl describe pods --namespace "$RELEASE_NAMESPACE" | |
| echo "--- pod logs ---" | |
| kubectl logs --namespace "$RELEASE_NAMESPACE" \ | |
| --selector="app.kubernetes.io/name=openshell,app.kubernetes.io/instance=${RELEASE_NAME}" \ | |
| --tail=200 --all-containers --prefix | |
| echo "--- port-forward log ---" | |
| cat port-forward.log 2>/dev/null | |
| echo "--- openshell gateway list ---" | |
| openshell gateway list 2>/dev/null | |
| echo "--- openshell version ---" | |
| openshell --version 2>/dev/null |