| name: critest containerd | |
| on: | |
| push: | |
| tags: | |
| - "*" | |
| branches: | |
| - master | |
| pull_request: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| # | |
| # Run CRI tests against containerd | |
| # | |
| build-and-critest-containerd: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # ╔══════════════════╤═══════════╤═════════╗ | |
| # ║ master / release │ ubuntu │ windows ║ | |
| # ╠══════════════════╪═══════════╪═════════╣ | |
| # ║ v1 shim │ runc │ ║ | |
| # ╟──────────────────┼───────────┼─────────╢ | |
| # ║ v2 shim │ runc/crun │ ║ | |
| # ╟──────────────────┼───────────┼─────────╢ | |
| # ║ hcshim │ │ runhcs ║ | |
| # ╚══════════════════╧═══════════╧═════════╝ | |
| os: [ubuntu-24.04, windows-2025] | |
| # not every command likes the slash in branch name. | |
| # So will use format command to replace to either `_` or '/' | |
| version: [main, "release{0}2.3", "release{0}1.7"] | |
| runtime: | |
| [ | |
| io.containerd.runtime.v1.linux, | |
| io.containerd.runc.v1, | |
| io.containerd.runc.v2, | |
| containerd-shim-runhcs-v1, | |
| ] | |
| runc: [runc, crun] | |
| exclude: | |
| - runtime: io.containerd.runc.v1 | |
| os: windows-2025 | |
| - runtime: io.containerd.runc.v2 | |
| os: windows-2025 | |
| - runtime: io.containerd.runtime.v1.linux | |
| os: windows-2025 | |
| - runtime: containerd-shim-runhcs-v1 | |
| os: ubuntu-24.04 | |
| - runtime: io.containerd.runc.v1 | |
| runc: crun | |
| - runtime: io.containerd.runtime.v1.linux | |
| runc: crun | |
| - runc: crun | |
| os: windows-2025 | |
| name: ${{ format(matrix.version, '/') }} / ${{ matrix.os }} / ${{matrix.runtime}} / ${{matrix.runc}} | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout cri-tools for this commit | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: ${{github.workspace}}/src/github.com/kubernetes-sigs/cri-tools | |
| persist-credentials: false | |
| - name: Install Go | |
| uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version-file: ${{github.workspace}}/src/github.com/kubernetes-sigs/cri-tools/go.mod | |
| cache: false | |
| - name: Set env | |
| if: startsWith(matrix.os, 'windows') | |
| shell: bash | |
| run: | | |
| echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV | |
| echo "${{ github.workspace }}/bin" >> $GITHUB_PATH | |
| - name: Checkout containerd/containerd ${{ format(matrix.version, '/') }} | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: ${{ github.workspace }}/src/github.com/containerd/containerd | |
| repository: containerd/containerd | |
| ref: ${{ format(matrix.version, '/') }} | |
| persist-credentials: false | |
| - name: Checkout Microsoft/hcsshim | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| if: startsWith(matrix.os, 'windows') | |
| with: | |
| repository: Microsoft/hcsshim | |
| path: src/github.com/Microsoft/hcsshim | |
| persist-credentials: false | |
| # Paired with "Save go modules and build cache" at end of job. | |
| - name: Restore go modules and build cache | |
| uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: | | |
| ~/go/pkg/mod | |
| ~/.cache/go-build | |
| '%LocalAppData%\go-build' # Windows | |
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} | |
| - name: disable ipv6 | |
| if: startsWith(matrix.os, 'ubuntu') | |
| run: | | |
| sudo sysctl net.ipv6.conf.all.disable_ipv6=0 | |
| - name: Install Linux dependencies for containerd | |
| if: startsWith(matrix.os, 'ubuntu') | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| btrfs-progs \ | |
| libbtrfs-dev \ | |
| libseccomp2 \ | |
| libseccomp-dev \ | |
| socat | |
| - name: Install containerd on Linux | |
| if: startsWith(matrix.os, 'ubuntu') | |
| run: | | |
| make | |
| sudo -E PATH=$PATH make install | |
| working-directory: ${{ github.workspace }}/src/github.com/containerd/containerd | |
| - name: Install containerd on Windows | |
| shell: bash | |
| if: startsWith(matrix.os, 'windows') | |
| run: | | |
| mingw32-make.exe | |
| mingw32-make.exe install | |
| working-directory: ${{ github.workspace }}/src/github.com/containerd/containerd | |
| - name: Install cni on Linux (release-1.7) | |
| # TODO: Remove this step once containerd release/1.7 is no longer supported. | |
| if: startsWith(matrix.os, 'ubuntu') && matrix.version == 'release{0}1.7' | |
| shell: bash | |
| # See https://github.com/containerd/containerd/pull/12660 | |
| run: | | |
| sudo -E PATH=$PATH script/setup/install-cni | |
| working-directory: src/github.com/containerd/containerd | |
| - name: Install cni on Linux | |
| if: startsWith(matrix.os, 'ubuntu') && matrix.version != 'release{0}1.7' | |
| shell: bash | |
| run: | | |
| sudo -E PATH=$PATH script/setup/install-cni $(grep 'github.com/containernetworking/plugins' go.mod | awk '{print $2}') | |
| working-directory: src/github.com/containerd/containerd | |
| - name: Install cni on Windows | |
| if: startsWith(matrix.os, 'windows') | |
| shell: bash | |
| run: | | |
| set -o errexit | |
| set -o nounset | |
| set -o pipefail | |
| # WINCNI_BIN_DIR is the cni plugin directory | |
| WINCNI_BIN_DIR="${WINCNI_BIN_DIR:-"C:\\Program Files\\containerd\\cni\\bin"}" | |
| WINCNI_PKG=github.com/Microsoft/windows-container-networking | |
| WINCNI_VERSION=aa10a0b31e9f72937063436454def1760b858ee2 | |
| # Create a temporary GOPATH for cni installation. | |
| GOPATH="$(mktemp -d /tmp/cri-install-cni.XXXX)" | |
| # Install cni | |
| win_cni_src="${GOPATH}/src/${WINCNI_PKG}" | |
| mkdir -p ${win_cni_src} | |
| git clone https://${WINCNI_PKG} ${win_cni_src} | |
| cd ${win_cni_src} | |
| git checkout ${WINCNI_VERSION} | |
| make all | |
| install -D -m 755 "out/nat.exe" "${WINCNI_BIN_DIR}/nat.exe" | |
| install -D -m 755 "out/sdnbridge.exe" "${WINCNI_BIN_DIR}/sdnbridge.exe" | |
| install -D -m 755 "out/sdnoverlay.exe" "${WINCNI_BIN_DIR}/sdnoverlay.exe" | |
| # Clean the tmp GOPATH dir. | |
| rm -rf "${GOPATH}" | |
| - name: Configure cni on Windows | |
| if: startsWith(matrix.os, 'windows') | |
| shell: bash | |
| run: | | |
| set -o errexit | |
| set -o nounset | |
| set -o pipefail | |
| CNI_CONFIG_DIR="${CNI_CONFIG_DIR:-"C:\\Program Files\\containerd\\cni\\conf"}" | |
| mkdir -p "${CNI_CONFIG_DIR}" | |
| # split_ip splits ip into a 4-element array. | |
| split_ip() { | |
| local -r varname="$1" | |
| local -r ip="$2" | |
| for i in {0..3}; do | |
| eval "$varname"[$i]=$( echo "$ip" | cut -d '.' -f $((i + 1)) ) | |
| done | |
| } | |
| # subnet gets subnet for a gateway, e.g. 192.168.100.0/24. | |
| calculate_subnet() { | |
| local -r gateway="$1" | |
| local -r prefix_len="$2" | |
| split_ip gateway_array "$gateway" | |
| local len=$prefix_len | |
| for i in {0..3}; do | |
| if (( len >= 8 )); then | |
| mask=255 | |
| elif (( len > 0 )); then | |
| mask=$(( 256 - 2 ** ( 8 - len ) )) | |
| else | |
| mask=0 | |
| fi | |
| (( len -= 8 )) | |
| result_array[i]=$(( gateway_array[i] & mask )) | |
| done | |
| result="$(printf ".%s" "${result_array[@]}")" | |
| result="${result:1}" | |
| echo "$result/$((32 - prefix_len))" | |
| } | |
| # nat already exists on the Windows VM, the subnet and gateway | |
| # we specify should match that. | |
| gateway="$(powershell -c "(Get-NetIPAddress -InterfaceAlias 'vEthernet (nat)' -AddressFamily IPv4).IPAddress")" | |
| prefix_len="$(powershell -c "(Get-NetIPAddress -InterfaceAlias 'vEthernet (nat)' -AddressFamily IPv4).PrefixLength")" | |
| subnet="$(calculate_subnet "$gateway" "$prefix_len")" | |
| # The "name" field in the config is used as the underlying | |
| # network type right now (see | |
| # https://github.com/microsoft/windows-container-networking/pull/45), | |
| # so it must match a network type in: | |
| # https://docs.microsoft.com/en-us/windows-server/networking/technologies/hcn/hcn-json-document-schemas | |
| bash -c 'cat >"'"${CNI_CONFIG_DIR}"'"/0-containerd-nat.conf <<EOF | |
| { | |
| "cniVersion": "0.2.0", | |
| "name": "nat", | |
| "type": "nat", | |
| "master": "Ethernet", | |
| "ipam": { | |
| "subnet": "'$subnet'", | |
| "routes": [ | |
| { | |
| "GW": "'$gateway'" | |
| } | |
| ] | |
| }, | |
| "capabilities": { | |
| "portMappings": true, | |
| "dns": true | |
| } | |
| } | |
| EOF' | |
| - name: Install ${{matrix.runc}} runtime engine on Linux | |
| if: startsWith(matrix.os, 'ubuntu') | |
| env: | |
| RUNC_FLAVOR: ${{matrix.runc}} | |
| run: | | |
| sudo -E PATH=$PATH script/setup/install-runc | |
| working-directory: src/github.com/containerd/containerd | |
| - name: Build cri-tools on Linux | |
| if: startsWith(matrix.os, 'ubuntu') | |
| run: | | |
| make | |
| sudo -E PATH=$PATH make install | |
| working-directory: ${{ github.workspace }}/src/github.com/kubernetes-sigs/cri-tools | |
| - name: Build cri-tools on Windows | |
| if: startsWith(matrix.os, 'windows') | |
| run: | | |
| make | |
| make install | |
| working-directory: ${{ github.workspace }}/src/github.com/kubernetes-sigs/cri-tools | |
| - name: Install ginkgo on Linux | |
| if: startsWith(matrix.os, 'ubuntu') | |
| shell: bash | |
| run: | | |
| sudo chown -R $(id -u):$(id -g) $(go env GOPATH) | |
| go install github.com/onsi/ginkgo/v2/ginkgo@latest | |
| ginkgo version | |
| sudo cp $(command -v ginkgo) /usr/local/bin | |
| - name: Install ginkgo on Windows | |
| if: startsWith(matrix.os, 'windows') | |
| shell: bash | |
| run: | | |
| go install github.com/onsi/ginkgo/v2/ginkgo@latest | |
| ginkgo version | |
| cp $(command -v ginkgo) /usr/local/bin | |
| - name: Run critest on Linux | |
| if: startsWith(matrix.os, 'ubuntu') | |
| shell: bash | |
| run: | | |
| set -o errexit | |
| set -o nounset | |
| set -o pipefail | |
| set -x | |
| BDIR="/var/lib/containerd-critest" | |
| echo "containerd temp dir: ${BDIR}" | |
| sudo mkdir -p ${BDIR}/{root,state} | |
| sudo bash -c 'cat > ${BDIR}/config.toml <<EOF | |
| version = 2 | |
| [plugins] | |
| [plugins.cri.containerd.default_runtime] | |
| runtime_type = \"${{matrix.runtime}}\" | |
| EOF' | |
| # Enable NRI explicitly to ensure the expected socket path is used. | |
| # Containerd 1.7 is EOL soon so skip NRI on that branch only. | |
| # TODO: Remove the condition once 1.7 is removed. | |
| if [[ "${{ matrix.version }}" != "release{0}1.7" ]]; then | |
| sudo bash -c 'cat >> ${BDIR}/config.toml <<EOF | |
| [plugins."io.containerd.nri.v1.nri"] | |
| disable = false | |
| disable_connections = false | |
| plugin_path = "/opt/nri/plugins" | |
| socket_path = "/var/run/nri/nri.sock" | |
| EOF' | |
| sudo mkdir -p /var/run/nri | |
| sudo mkdir -p /opt/nri/plugins | |
| fi | |
| # Remove possibly existing containerd configuration | |
| sudo rm -rf /etc/containerd | |
| sudo PATH=$PATH bash -c "/usr/local/bin/containerd -a ${BDIR}/c.sock -root ${BDIR}/root -state ${BDIR}/state -log-level debug &> ${BDIR}/containerd-cri.log &" | |
| while ! grep -q 'containerd successfully booted' ${BDIR}/containerd-cri.log; do | |
| sleep 1 | |
| done | |
| sudo /usr/local/bin/ctr -a ${BDIR}/c.sock version | |
| sudo /usr/local/sbin/runc --version | |
| sudo mount | |
| # Build critest flags | |
| CRITEST_FLAGS="--ginkgo.v --runtime-endpoint=unix:///${BDIR}/c.sock --parallel=8" | |
| # TODO: Remove the condition once 1.7 is removed. | |
| if [[ "${{ matrix.version }}" != "release{0}1.7" ]]; then | |
| CRITEST_FLAGS="${CRITEST_FLAGS} --nri-socket=/var/run/nri/nri.sock" | |
| fi | |
| TEST_RC=0 | |
| sudo -E PATH=$PATH critest ${CRITEST_FLAGS} || TEST_RC=$? | |
| test $TEST_RC -ne 0 && cat ${BDIR}/containerd-cri.log | |
| sudo pkill containerd | |
| echo "CONTD_CRI_DIR=$BDIR" >> $GITHUB_ENV | |
| test $TEST_RC -eq 0 || /bin/false | |
| - name: Run critest on Windows | |
| if: startsWith(matrix.os, 'windows') | |
| shell: bash | |
| run: | | |
| set -o errexit | |
| set -o nounset | |
| set -o pipefail | |
| export PATH="/usr/local/bin:$PATH" | |
| FOCUS="${FOCUS:-"Conformance"}" | |
| REPORT_DIR="${REPORT_DIR:-"c/_artifacts"}" | |
| mkdir -p "${REPORT_DIR}" | |
| containerd -log-level debug &> "${REPORT_DIR}/containerd-cri.log" & | |
| pid=$! | |
| while ! grep -q 'containerd successfully booted' ${REPORT_DIR}/containerd-cri.log; do | |
| sleep 1 | |
| done | |
| ctr version | |
| set +o errexit | |
| SKIP="exec with tty=true and stdin=true" | |
| critest --runtime-endpoint=npipe:////./pipe/containerd-containerd --ginkgo.focus="${FOCUS}" --ginkgo.skip="${SKIP}" --report-dir="${REPORT_DIR}" --report-prefix="windows" | |
| TEST_RC=$? | |
| test $TEST_RC -ne 0 && cat ${REPORT_DIR}/containerd-cri.log | |
| set -o errexit | |
| kill -9 $pid | |
| echo "CONTD_CRI_DIR=$REPORT_DIR" >> $GITHUB_ENV | |
| exit ${TEST_RC} | |
| - name: Upload containerd ${{ format(matrix.version, '/') }} logs | |
| if: always() | |
| uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 | |
| with: | |
| name: containerd-${{ format(matrix.version, '_') }}-${{ matrix.os }}-${{matrix.runtime}}-${{matrix.runc}}-${{github.sha}}.log | |
| path: ${{env.CONTD_CRI_DIR}}/containerd-cri.log | |
| - name: Cleanup temp directory on Linux | |
| if: startsWith(matrix.os, 'ubuntu') | |
| shell: bash | |
| run: | | |
| echo "Cleanup temp directory $CONTD_CRI_DIR created for cri tests" | |
| sudo umount -Rl "$CONTD_CRI_DIR" 2>/dev/null || true | |
| sudo rm -rf "$CONTD_CRI_DIR" | |
| - name: Cleanup temp directory on Windows | |
| if: startsWith(matrix.os, 'windows') | |
| shell: bash | |
| run: | | |
| echo "Cleanup temp directory $CONTD_CRI_DIR created for cri tests" | |
| rm -rf "$CONTD_CRI_DIR" | |
| # Paired with "Restore go modules and build cache" near top of job. | |
| # Placed here so the cache includes dependencies fetched during the build. | |
| - name: Save go modules and build cache | |
| if: github.event_name != 'pull_request' | |
| uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: | | |
| ~/go/pkg/mod | |
| ~/.cache/go-build | |
| '%LocalAppData%\go-build' # Windows | |
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} |