|
6 | 6 | pull_request: |
7 | 7 | workflow_dispatch: |
8 | 8 |
|
| 9 | +permissions: |
| 10 | + contents: read |
| 11 | + packages: write |
| 12 | + |
9 | 13 | jobs: |
| 14 | + lint: |
| 15 | + name: lint |
| 16 | + runs-on: ubuntu-latest |
| 17 | + steps: |
| 18 | + - uses: actions/checkout@v4 |
| 19 | + - uses: actions/setup-go@v5 |
| 20 | + with: |
| 21 | + go-version-file: go.mod |
| 22 | + cache: true |
| 23 | + - name: Run linters |
| 24 | + run: make lint |
| 25 | + |
| 26 | + container-images: |
| 27 | + name: immutable container images |
| 28 | + runs-on: ubuntu-latest |
| 29 | + if: github.event_name != 'pull_request' |
| 30 | + steps: |
| 31 | + - uses: actions/checkout@v4 |
| 32 | + - uses: docker/login-action@v3 |
| 33 | + with: |
| 34 | + registry: ghcr.io |
| 35 | + username: ${{ github.actor }} |
| 36 | + password: ${{ secrets.GITHUB_TOKEN }} |
| 37 | + - name: Build and publish immutable images |
| 38 | + run: | |
| 39 | + docker build -t ghcr.io/${{ github.repository }}/smolvm-operator:${{ github.sha }} . |
| 40 | + docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t ghcr.io/${{ github.repository }}/smolvm-runtime:${{ github.sha }} . |
| 41 | + docker push ghcr.io/${{ github.repository }}/smolvm-operator:${{ github.sha }} |
| 42 | + docker push ghcr.io/${{ github.repository }}/smolvm-runtime:${{ github.sha }} |
| 43 | +
|
| 44 | + release-artifact: |
| 45 | + name: install artifact dry run |
| 46 | + runs-on: ubuntu-latest |
| 47 | + steps: |
| 48 | + - uses: actions/checkout@v4 |
| 49 | + - uses: actions/setup-go@v5 |
| 50 | + with: |
| 51 | + go-version-file: go.mod |
| 52 | + cache: true |
| 53 | + - name: Build reproducible install artifact |
| 54 | + run: make rc-artifacts VERSION=ci IMG=ghcr.io/${{ github.repository }}/smolvm-operator:${{ github.sha }} RUNTIME_IMG=ghcr.io/${{ github.repository }}/smolvm-runtime:${{ github.sha }} |
| 55 | + - name: Upload install artifact |
| 56 | + uses: actions/upload-artifact@v4 |
| 57 | + with: |
| 58 | + name: install-artifact |
| 59 | + path: dist/ |
| 60 | + |
10 | 61 | envtest: |
11 | 62 | name: envtest controller |
12 | 63 | runs-on: ubuntu-latest |
| 64 | + needs: [lint] |
13 | 65 | steps: |
14 | 66 | - uses: actions/checkout@v4 |
15 | 67 | - uses: actions/setup-go@v5 |
16 | 68 | with: |
17 | 69 | go-version-file: go.mod |
18 | 70 | cache: true |
19 | 71 | - name: Run controller-runtime envtest |
20 | | - run: make test |
| 72 | + run: make test-report |
| 73 | + - name: Upload test reports |
| 74 | + if: always() |
| 75 | + uses: actions/upload-artifact@v4 |
| 76 | + with: |
| 77 | + name: envtest-reports |
| 78 | + path: reports/ |
21 | 79 |
|
22 | 80 | kind-e2e: |
23 | | - name: kind e2e |
| 81 | + name: kind topology e2e |
24 | 82 | runs-on: ubuntu-latest |
| 83 | + needs: [envtest, release-artifact] |
25 | 84 | steps: |
26 | 85 | - uses: actions/checkout@v4 |
27 | 86 | - uses: actions/setup-go@v5 |
28 | 87 | with: |
29 | 88 | go-version-file: go.mod |
30 | 89 | cache: true |
| 90 | + - name: Prepare KVM-backed multi-node kind mounts |
| 91 | + run: | |
| 92 | + set -euxo pipefail |
| 93 | + test -e /dev/kvm |
| 94 | + sudo chmod 666 /dev/kvm |
| 95 | + for node in control-plane worker worker2; do |
| 96 | + sudo mkdir -p "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run" |
| 97 | + sudo chmod 777 "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run" |
| 98 | + done |
| 99 | + - name: Build e2e images and manifest |
| 100 | + run: | |
| 101 | + docker build -t smolvm-operator:e2e . |
| 102 | + docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t smolvm-runtime:e2e . |
| 103 | + make build-installer IMG=smolvm-operator:e2e RUNTIME_IMG=smolvm-runtime:e2e |
31 | 104 | - uses: helm/kind-action@v1 |
32 | 105 | with: |
33 | 106 | cluster_name: kind |
34 | | - - name: Run one deployment e2e test |
| 107 | + config: .github/kind-kvm-multinode-config.yaml |
| 108 | + - name: Load e2e images |
| 109 | + run: | |
| 110 | + kind load docker-image smolvm-operator:e2e --name kind |
| 111 | + kind load docker-image smolvm-runtime:e2e --name kind |
| 112 | + - name: Run deployed topology e2e test |
35 | 113 | env: |
36 | 114 | RUN_E2E: "true" |
| 115 | + E2E_INSTALL_MANIFEST: dist/install.yaml |
37 | 116 | KIND_CLUSTER: kind |
38 | | - run: make test-e2e |
| 117 | + run: make test-e2e-report |
| 118 | + - name: Upload e2e reports |
| 119 | + if: always() |
| 120 | + uses: actions/upload-artifact@v4 |
| 121 | + with: |
| 122 | + name: e2e-reports |
| 123 | + path: reports/ |
39 | 124 |
|
40 | | - smolvm-runtime-smoke: |
41 | | - name: smolvm runtime smoke |
| 125 | + smolvm-runtime-e2e: |
| 126 | + name: smolvm runtime lifecycle e2e |
42 | 127 | runs-on: ubuntu-latest |
43 | | - timeout-minutes: 20 |
| 128 | + needs: [envtest, release-artifact] |
| 129 | + timeout-minutes: 45 |
44 | 130 | steps: |
45 | 131 | - uses: actions/checkout@v4 |
46 | 132 | - uses: actions/setup-go@v5 |
47 | 133 | with: |
48 | 134 | go-version-file: go.mod |
49 | 135 | cache: true |
| 136 | + - name: Prepare KVM-backed multi-node kind mounts |
| 137 | + run: | |
| 138 | + set -euxo pipefail |
| 139 | + test -e /dev/kvm |
| 140 | + sudo chmod 666 /dev/kvm |
| 141 | + for node in control-plane worker worker2; do |
| 142 | + sudo mkdir -p "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run" |
| 143 | + sudo chmod 777 "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run" |
| 144 | + done |
| 145 | + - name: Build runtime e2e images and manifest |
| 146 | + run: | |
| 147 | + docker build -t smolvm-operator:runtime-e2e . |
| 148 | + docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t smolvm-runtime:runtime-e2e . |
| 149 | + make build-installer IMG=smolvm-operator:runtime-e2e RUNTIME_IMG=smolvm-runtime:runtime-e2e |
50 | 150 | - uses: helm/kind-action@v1 |
51 | 151 | with: |
52 | 152 | cluster_name: runtime |
53 | | - - name: Install smolvm |
| 153 | + config: .github/kind-kvm-multinode-config.yaml |
| 154 | + - name: Load runtime e2e images |
54 | 155 | run: | |
55 | | - sudo apt-get update |
56 | | - sudo apt-get install -y libvirglrenderer1 libepoxy0 libgbm1 |
57 | | - curl -fsSL -o /tmp/smolvm.tar.gz https://github.com/smol-machines/smolvm/releases/download/v0.8.1/smolvm-0.8.1-linux-x86_64.tar.gz |
58 | | - mkdir -p /tmp/smolvm |
59 | | - tar -xzf /tmp/smolvm.tar.gz -C /tmp/smolvm --strip-components=1 |
60 | | - echo /tmp/smolvm >> "$GITHUB_PATH" |
61 | | - /tmp/smolvm/smolvm --version |
62 | | - - name: Run operator against real smolvm runtime |
| 156 | + kind load docker-image smolvm-operator:runtime-e2e --name runtime |
| 157 | + kind load docker-image smolvm-runtime:runtime-e2e --name runtime |
| 158 | + - name: Run runtime lifecycle e2e |
| 159 | + env: |
| 160 | + RUN_E2E: "true" |
| 161 | + E2E_INSTALL_MANIFEST: dist/install.yaml |
| 162 | + KIND_CLUSTER: runtime |
| 163 | + RUNTIME_E2E: "true" |
| 164 | + run: make test-runtime-e2e-report |
| 165 | + - name: Upload runtime logs |
| 166 | + if: always() |
| 167 | + uses: actions/upload-artifact@v4 |
| 168 | + with: |
| 169 | + name: runtime-e2e-logs |
| 170 | + path: reports/ |
| 171 | + |
| 172 | + release-hardening-e2e: |
| 173 | + name: upgrade multi-node and failure gates |
| 174 | + runs-on: ubuntu-latest |
| 175 | + needs: [envtest, release-artifact] |
| 176 | + steps: |
| 177 | + - uses: actions/checkout@v4 |
| 178 | + - uses: actions/setup-go@v5 |
| 179 | + with: |
| 180 | + go-version-file: go.mod |
| 181 | + cache: true |
| 182 | + - name: Prepare KVM-backed multi-node kind mounts |
63 | 183 | run: | |
64 | 184 | set -euxo pipefail |
| 185 | + test -e /dev/kvm |
65 | 186 | sudo chmod 666 /dev/kvm |
66 | | - export LD_LIBRARY_PATH="/tmp/smolvm/lib:${LD_LIBRARY_PATH:-}" |
67 | | - export LD_PRELOAD="$(find /usr/lib -name 'libvirglrenderer.so.1' | head -1)" |
68 | | - smolvm serve start --listen 127.0.0.1:8080 > smolvm-serve.log 2>&1 & |
69 | | - serve_pid=$! |
70 | | - trap 'kubectl delete smolvm runtime-smoke --ignore-not-found=true --wait=false || true; kill $serve_pid || true; cat smolvm-serve.log || true' EXIT |
71 | | -
|
72 | | - for i in {1..60}; do |
73 | | - curl -fsS http://127.0.0.1:8080/api/v1/machines && break |
74 | | - sleep 1 |
| 187 | + for node in control-plane worker worker2; do |
| 188 | + sudo mkdir -p "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run" |
| 189 | + sudo chmod 777 "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run" |
75 | 190 | done |
76 | | -
|
77 | | - make install |
78 | | - SMOLVM_API_URL=http://127.0.0.1:8080 go run ./cmd/main.go \ |
79 | | - --metrics-bind-address=0 \ |
80 | | - --health-probe-bind-address=:8081 > manager.log 2>&1 & |
81 | | - manager_pid=$! |
82 | | - trap 'kubectl delete smolvm runtime-smoke --ignore-not-found=true --wait=false || true; kill $manager_pid || true; kill $serve_pid || true; cat manager.log || true; cat smolvm-serve.log || true' EXIT |
83 | | -
|
84 | | - cat <<'EOF' | kubectl apply -f - |
85 | | - apiVersion: vm.smolvm.dev/v1alpha1 |
86 | | - kind: SmolVM |
87 | | - metadata: |
88 | | - name: runtime-smoke |
89 | | - spec: |
90 | | - running: true |
91 | | - image: alpine:latest |
92 | | - resources: |
93 | | - cpus: 1 |
94 | | - memoryMiB: 128 |
95 | | - EOF |
96 | | -
|
97 | | - ready=false |
98 | | - for i in {1..48}; do |
99 | | - echo "--- poll $i ---" |
100 | | - kubectl get smolvm runtime-smoke -o yaml || true |
101 | | - curl -fsS http://127.0.0.1:8080/api/v1/machines || true |
102 | | - status=$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || true) |
103 | | - if [ "$status" = "True" ]; then |
104 | | - ready=true |
105 | | - break |
106 | | - fi |
107 | | - sleep 10 |
108 | | - done |
109 | | - if [ "$ready" != "true" ]; then |
110 | | - echo "runtime-smoke did not become Ready" |
111 | | - kubectl get smolvm runtime-smoke -o yaml || true |
112 | | - curl -fsS http://127.0.0.1:8080/api/v1/machines || true |
| 191 | + - name: Build hardening e2e images and manifests |
| 192 | + env: |
| 193 | + PREVIOUS_INSTALL_MANIFEST_URL: ${{ vars.PREVIOUS_INSTALL_MANIFEST_URL }} |
| 194 | + run: | |
| 195 | + set -euxo pipefail |
| 196 | + if [ -z "$PREVIOUS_INSTALL_MANIFEST_URL" ]; then |
| 197 | + echo "PREVIOUS_INSTALL_MANIFEST_URL repository variable is required for upgrade e2e" >&2 |
113 | 198 | exit 1 |
114 | 199 | fi |
115 | | - test "$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.conditions[?(@.type=="RuntimeReady")].status}')" = "True" |
116 | | - test "$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.conditions[?(@.type=="GuestReady")].status}')" = "Unknown" |
117 | | -
|
118 | | - kubectl patch smolvm runtime-smoke --type=merge -p '{"spec":{"running":false}}' |
119 | | - kubectl wait smolvm runtime-smoke \ |
120 | | - --for=jsonpath='{.status.phase}'=Stopped \ |
121 | | - --timeout=5m |
122 | | -
|
123 | | - machine=$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.machineName}') |
124 | | - kubectl delete smolvm runtime-smoke --wait=true --timeout=5m |
125 | | - for i in {1..30}; do |
126 | | - if ! curl -fsS http://127.0.0.1:8080/api/v1/machines | grep -q "$machine"; then |
127 | | - exit 0 |
128 | | - fi |
129 | | - sleep 2 |
130 | | - done |
131 | | - echo "runtime machine $machine still exists after CR deletion" |
132 | | - curl -fsS http://127.0.0.1:8080/api/v1/machines || true |
133 | | - exit 1 |
| 200 | + mkdir -p dist |
| 201 | + curl -fsSL "$PREVIOUS_INSTALL_MANIFEST_URL" -o dist/previous-install.yaml |
| 202 | + docker build -t smolvm-operator:rc . |
| 203 | + docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t smolvm-runtime:rc . |
| 204 | + make build-installer IMG=smolvm-operator:rc RUNTIME_IMG=smolvm-runtime:rc |
| 205 | + cp dist/install.yaml dist/rc-install.yaml |
| 206 | + - uses: helm/kind-action@v1 |
| 207 | + with: |
| 208 | + cluster_name: hardening |
| 209 | + config: .github/kind-kvm-multinode-config.yaml |
| 210 | + - name: Load hardening images |
| 211 | + run: | |
| 212 | + kind load docker-image smolvm-operator:rc --name hardening |
| 213 | + kind load docker-image smolvm-runtime:rc --name hardening |
| 214 | + - name: Run upgrade, multi-node, and failure checks |
| 215 | + env: |
| 216 | + RUN_E2E: "true" |
| 217 | + E2E_INSTALL_MANIFEST: dist/rc-install.yaml |
| 218 | + PREVIOUS_INSTALL_MANIFEST: dist/previous-install.yaml |
| 219 | + RC_INSTALL_MANIFEST: dist/rc-install.yaml |
| 220 | + run: | |
| 221 | + make test-upgrade-e2e-report |
| 222 | + make test-multinode-e2e-report |
| 223 | + make test-failure-e2e-report |
| 224 | + - name: Upload release hardening reports |
| 225 | + if: always() |
| 226 | + uses: actions/upload-artifact@v4 |
| 227 | + with: |
| 228 | + name: release-hardening-reports |
| 229 | + path: reports/ |
0 commit comments