ci: add integration tests #88
Workflow file for this run
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: CI | |
| on: | |
| # When added to a merge queue. | |
| # See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue#triggering-merge-group-checks-with-github-actions | |
| merge_group: | |
| pull_request: | |
| branches: ['main', 'release/**'] | |
| permissions: # added using https://github.com/step-security/secure-workflows | |
| contents: read | |
| jobs: | |
| setup: | |
| name: Setup | |
| runs-on: ubuntu-latest | |
| outputs: | |
| kernel-version: ${{ steps.set-vars.outputs.kernel-version }} | |
| containerd-version: ${{ steps.set-vars.outputs.containerd-version }} | |
| steps: | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| sparse-checkout: | | |
| .github/.tool-versions | |
| - name: Set variables | |
| id: set-vars | |
| run: | | |
| kernel_version=$(grep -E '^kernel [0-9.]+$' .github/.tool-versions | sed -E 's/^kernel ([0-9.]+)$/\1/') | |
| echo "kernel-version=${kernel_version}" >> $GITHUB_OUTPUT | |
| containerd_version=$(grep -E '^containerd [0-9.]+$' .github/.tool-versions | sed -E 's/^containerd ([0-9.]+)$/\1/') | |
| echo "containerd-version=${containerd_version}" >> $GITHUB_OUTPUT | |
| linters: | |
| permissions: | |
| contents: read # for actions/checkout to fetch code | |
| pull-requests: read # for golangci/golangci-lint-action to fetch pull requests | |
| name: Linters | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 | |
| - run: make validate | |
| # | |
| # Project checks | |
| # | |
| project: | |
| name: Project Checks | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| path: src/github.com/containerd/nerdbox | |
| fetch-depth: 100 | |
| - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 | |
| with: | |
| go-version-file: 'src/github.com/containerd/nerdbox/.github/.tool-versions' | |
| - uses: containerd/project-checks@d7751f3c375b8fe4a84c02a068184ee4c1f59bc4 # v1.2.2 | |
| if: github.repository == 'containerd/nerdbox' | |
| with: | |
| working-directory: src/github.com/containerd/nerdbox | |
| repo-access-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: verify go modules and vendor directory | |
| run: | | |
| make verify-vendor | |
| working-directory: src/github.com/containerd/nerdbox | |
| # | |
| # Protobuf checks | |
| # | |
| protos: | |
| name: Protobuf | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| defaults: | |
| run: | |
| working-directory: src/github.com/containerd/nerdbox | |
| steps: | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| path: src/github.com/containerd/nerdbox | |
| # Needed for proto lookup during generation | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| repository: containerd/containerd | |
| path: src/github.com/containerd/containerd | |
| - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 | |
| with: | |
| go-version-file: 'src/github.com/containerd/nerdbox/.github/.tool-versions' | |
| - name: Set env | |
| shell: bash | |
| run: | | |
| echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV | |
| echo "${{ github.workspace }}/bin" >> $GITHUB_PATH | |
| - name: Install protobuf | |
| run: | | |
| sudo -E PATH=$PATH script/install-protobuf | |
| sudo chmod +x /usr/local/bin/protoc | |
| sudo chmod og+rx /usr/local/include/google /usr/local/include/google/protobuf /usr/local/include/google/protobuf/compiler | |
| sudo chmod -R og+r /usr/local/include/google/protobuf/ | |
| protoc --version | |
| - run: script/install-proto-tools | |
| - run: make proto-fmt | |
| - run: make check-protos check-api-descriptors | |
| # | |
| # Build kernels on cache miss | |
| # | |
| build-kernels: | |
| name: Build Kernels (if needed) | |
| runs-on: ${{ matrix.os }} | |
| needs: setup | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| arch: x86_64 | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| steps: | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - uses: ./.github/actions/build-kernel | |
| with: | |
| kernel_version: ${{ needs.setup.outputs.kernel-version }} | |
| kernel_arch: ${{ matrix.arch }} | |
| # | |
| # Integration tests | |
| # | |
| integration: | |
| name: Integration Tests | |
| needs: [setup, build-kernels] | |
| # Always run after kernel builds complete (whether they were cached or not) | |
| if: | | |
| always() && | |
| (needs.build-kernels.result == 'success' || needs.build-kernels.result == 'skipped') | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| arch: x86_64 | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| steps: | |
| - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: Calculate kernel cache key | |
| id: cache-key | |
| run: | | |
| # Hash the kernel config and patches to create a unique cache key | |
| CONFIG_FILE="kernel/config-${{ needs.setup.outputs.kernel-version }}-${{ matrix.arch }}" | |
| if [ ! -f "$CONFIG_FILE" ]; then | |
| echo "Error: Kernel config file $CONFIG_FILE not found" | |
| exit 1 | |
| fi | |
| # Calculate hash of config file and all patches | |
| CONFIG_HASH=$(sha256sum "$CONFIG_FILE" | cut -d' ' -f1) | |
| PATCHES_HASH=$(find kernel/patches -type f -name "*.patch" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1) | |
| # Combine version, arch, config hash, and patches hash | |
| CACHE_KEY="kernel-${{ needs.setup.outputs.kernel-version }}-${{ matrix.arch }}-${CONFIG_HASH:0:8}-${PATCHES_HASH:0:8}" | |
| echo "cache-key=${CACHE_KEY}" >> $GITHUB_OUTPUT | |
| echo "Kernel cache key: ${CACHE_KEY}" | |
| - name: Restore cached kernel | |
| id: cache-kernel | |
| uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 | |
| with: | |
| path: _output/nerdbox-kernel-${{ matrix.arch }} | |
| key: ${{ steps.cache-key.outputs.cache-key }} | |
| - name: Verify kernel from cache | |
| run: | | |
| if [ "${{ steps.cache-kernel.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ Kernel restored from cache" | |
| else | |
| echo "❌ Kernel not in cache - this should not happen after build-kernels-on-demand" | |
| exit 1 | |
| fi | |
| ls -lh _output/nerdbox-kernel-${{ matrix.arch }} | |
| file _output/nerdbox-kernel-${{ matrix.arch }} | |
| - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 | |
| - name: Build remaining artifacts (initrd and shim) | |
| run: | | |
| echo "Building host and guest binaries:" | |
| docker buildx bake host-binaries guest-binaries | |
| - name: Verify all artifacts | |
| run: | | |
| echo "Verifying build artifacts:" | |
| ls -lh _output/ | |
| echo "" | |
| echo "Kernel:" | |
| file _output/nerdbox-kernel-${{ matrix.arch }} | |
| echo "" | |
| echo "Initrd:" | |
| file _output/nerdbox-initrd | |
| echo "" | |
| echo "Shim:" | |
| file _output/containerd-shim-nerdbox-v1 | |
| - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 | |
| with: | |
| go-version-file: '.github/.tool-versions' | |
| - name: Setup containerd | |
| uses: ./.github/actions/setup-containerd | |
| with: | |
| containerd_version: ${{ needs.setup.outputs.containerd-version }} | |
| architecture: ${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }} | |
| - name: Run integration tests | |
| id: integration-tests | |
| run: go test -v ./integration/... | |
| - name: Output containerd logs on failure | |
| if: failure() && steps.integration-tests.outcome == 'failure' | |
| run: | | |
| echo "Integration tests failed. Outputting containerd logs..." | |
| echo "==================== CONTAINERD LOGS ====================" | |
| sudo cat /var/log/containerd/containerd.log || echo "No containerd logs found" | |
| echo "=========================================================" | |
| echo "" | |
| echo "Containerd process status:" | |
| ps aux | grep containerd | grep -v grep || echo "No containerd processes running" | |
| - name: Stop containerd | |
| if: always() | |
| run: | | |
| echo "Stopping containerd..." | |
| # Try to stop containerd gracefully using pkill | |
| if pgrep -x containerd > /dev/null; then | |
| echo "Found running containerd process(es)" | |
| sudo pkill -TERM containerd || true | |
| # Wait up to 10 seconds for graceful shutdown | |
| for i in {1..10}; do | |
| if ! pgrep -x containerd > /dev/null; then | |
| echo "Containerd stopped gracefully" | |
| break | |
| fi | |
| if [ $i -eq 10 ]; then | |
| echo "Containerd did not stop gracefully, forcing shutdown..." | |
| sudo pkill -KILL containerd || true | |
| fi | |
| sleep 1 | |
| done | |
| else | |
| echo "No containerd process found running" | |
| fi | |
| # Clean up PID file if it exists | |
| if [ -f /var/run/containerd.pid ]; then | |
| sudo rm -f /var/run/containerd.pid | |
| echo "Cleaned up containerd PID file" | |
| fi | |
| # Verify containerd is stopped | |
| if pgrep -x containerd > /dev/null; then | |
| echo "Warning: Containerd process still running after cleanup attempt" | |
| ps aux | grep containerd | grep -v grep | |
| else | |
| echo "Containerd stopped successfully" | |
| fi |