From 75426c6d712fe5ea23c284f284f5f91dfc9d6ea3 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 8 May 2026 21:51:35 -0400 Subject: [PATCH 1/2] ci: add GHA workflow for unit and e2e tests Unfortunately for now we also have to build bink ourselves, but ideally in the future we can just fetch built binaries. Or if bink switches to being built as a container, we can just pull that. Assisted-by: Pi (Claude Opus 4.6) --- .github/workflows/ci.yaml | 118 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..ddedcce --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,118 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: ci-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + unit: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + cache: true + + - name: Unit tests + run: make unit + + - name: Vet + run: make vet + + - name: Lint + run: make lint + + # TODO: Replace with fetching a released binary once bink publishes GitHub + # releases. + build-bink: + runs-on: ubuntu-latest + steps: + - name: Checkout bink + uses: actions/checkout@v6 + with: + repository: alicefr/bink + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + cache: true + + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + libgpgme-dev \ + libbtrfs-dev \ + libdevmapper-dev \ + pkg-config + + - name: Build bink + run: make build-bink + + - name: Upload bink binary + uses: actions/upload-artifact@v7 + with: + name: bink + path: bink + + e2e: + runs-on: ubuntu-latest + needs: build-bink + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Download bink binary + uses: actions/download-artifact@v8 + with: + name: bink + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + cache: true + + - name: Set up KVM + run: sudo chmod 666 /dev/kvm + + - name: Configure kernel + run: | + # Unload AppArmor profiles — the passt profile blocks remount + # operations needed for passt's self-sandboxing inside containers. + sudo aa-teardown 2>/dev/null || true + # Allow unprivileged user namespace creation (needed by passt + # inside containers). + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + + - name: Enable KSM + run: | + sudo sh -c 'echo 1 > /sys/kernel/mm/ksm/run' + sudo sh -c 'echo 5000 > /sys/kernel/mm/ksm/pages_to_scan' + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y podman + + - name: Start podman socket + run: systemctl --user start podman.socket + + - name: Run e2e tests + run: | + chmod +x bink + make e2e V=1 + env: + BINK_PATH: ${{ github.workspace }}/bink From d5386627ff02c2634b81ea14c38a2b3dde06d2d0 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 8 May 2026 22:12:24 -0400 Subject: [PATCH 2/2] crd_test: fix errcheck lint warnings in validation tests Assisted-by: Pi (Claude Opus 4.6) --- internal/controller/crd_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/controller/crd_test.go b/internal/controller/crd_test.go index 1766860..60480a9 100644 --- a/internal/controller/crd_test.go +++ b/internal/controller/crd_test.go @@ -221,7 +221,7 @@ func TestBootcNodePoolEnumValidation(t *testing.T) { testutil.WithRebootPolicy("Invalid"), ) if err := k8sClient.Create(ctx, pool); err == nil { - k8sClient.Delete(ctx, pool) + _ = k8sClient.Delete(ctx, pool) t.Fatal("Expected creation with invalid rebootPolicy to fail, but it succeeded") } } @@ -232,7 +232,7 @@ func TestBootcNodeEnumValidation(t *testing.T) { node := testutil.NewNode("invalid-image-state", testImageDigestRefA) node.Spec.DesiredImageState = "Invalid" if err := k8sClient.Create(ctx, node); err == nil { - k8sClient.Delete(ctx, node) + _ = k8sClient.Delete(ctx, node) t.Fatal("Expected creation with invalid desiredImageState to fail, but it succeeded") } } @@ -242,7 +242,7 @@ func TestBootcNodePoolMinLengthValidation(t *testing.T) { pool := testutil.NewPool("empty-image-ref", "") if err := k8sClient.Create(ctx, pool); err == nil { - k8sClient.Delete(ctx, pool) + _ = k8sClient.Delete(ctx, pool) t.Fatal("Expected creation with empty image.ref to fail, but it succeeded") } } @@ -252,7 +252,7 @@ func TestBootcNodeMinLengthValidation(t *testing.T) { node := testutil.NewNode("empty-desired-image", "") if err := k8sClient.Create(ctx, node); err == nil { - k8sClient.Delete(ctx, node) + _ = k8sClient.Delete(ctx, node) t.Fatal("Expected creation with empty desiredImage to fail, but it succeeded") } }