instruction: Create a GitHub Actions workflow for CI/CD automation with automated testing
output: ## ci.yml
  
  **Repository:** containerd/containerd
  **File Type:** Github Workflow
  **Purpose:** Production configuration from containerd project
  
  ```yaml
  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:
    #
    # golangci-lint
    #
    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: ${{ matrix.os }}
      timeout-minutes: 10
  
      strategy:
        matrix:
          os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest]
  
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: ./.github/actions/install-go
        - uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9  # v8.0.0
          with:
            version: v2.1.5
            skip-cache: true
            args: --timeout=8m
  
    #
    # Project checks
    #
    project:
      name: Project Checks
      runs-on: ubuntu-latest
      timeout-minutes: 5
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
          with:
            path: src/github.com/containerd/containerd
            fetch-depth: 100
  
        - uses: ./src/github.com/containerd/containerd/.github/actions/install-go
  
        - uses: containerd/project-checks@d7751f3c375b8fe4a84c02a068184ee4c1f59bc4 # v1.2.2
          if: github.repository == 'containerd/containerd'
          with:
            working-directory: src/github.com/containerd/containerd
            repo-access-token: ${{ secrets.GITHUB_TOKEN }}
  
        - name: verify go modules and vendor directory
          run: |
            sudo apt-get install -y jq
            make verify-vendor
          working-directory: src/github.com/containerd/containerd
  
    #
    # Protobuf checks
    #
    protos:
      name: Protobuf
      runs-on: ubuntu-latest
      timeout-minutes: 5
  
      defaults:
        run:
          working-directory: src/github.com/containerd/containerd
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
          with:
            path: src/github.com/containerd/containerd
  
        - uses: ./src/github.com/containerd/containerd/.github/actions/install-go
  
        - 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/setup/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/setup/install-dev-tools
        - run: make proto-fmt
        - run: make check-protos check-api-descriptors
  
    man:
      name: Manpages
      runs-on: ubuntu-latest
      timeout-minutes: 5
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: ./.github/actions/install-go
        - run: go install github.com/cpuguy83/go-md2man/v2@v2.0.7
        - run: make man
  
    # Make sure binaries compile with other minor platforms.
    # Well-known architectures are covered in release.yml.
    crossbuild:
      name: Crossbuild Binaries
      needs: [project, linters, protos, man]
      runs-on: ubuntu-latest
      timeout-minutes: 10
      strategy:
        fail-fast: false
        matrix:
          include:
            - goos: linux
              goarch: arm
              goarm: "7"
            - goos: linux
              goarch: arm
              goarm: "5"
            - goos: freebsd
              goarch: amd64
            - goos: freebsd
              goarch: arm64
            - goos: windows
              goarch: arm
              goarm: "7"
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: ./.github/actions/install-go
        - run: |
            set -e -x
  
            packages=""
            platform="${{matrix.goos}}/${{matrix.goarch}}"
            if [ -n "${{matrix.goarm}}" ]; then
              platform+="/v${{matrix.goarm}}"
            fi
  
            case "${platform}" in
            linux/arm/v5)
              packages+=" crossbuild-essential-armel"
              echo "CGO_ENABLED=1" >> $GITHUB_ENV
              echo "CC=arm-linux-gnueabi-gcc" >> $GITHUB_ENV
              ;;
            linux/arm/v7)
              packages+=" crossbuild-essential-armhf"
              echo "CGO_ENABLED=1" >> $GITHUB_ENV
              echo "CC=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
              ;;
            windows/arm/v7)
              echo "CGO_ENABLED=0" >> $GITHUB_ENV
              ;;
            esac
  
            if [ -n "${packages}" ]; then
              sudo apt-get update && sudo apt-get install -y ${packages}
            fi
          name: Install deps
        - name: Build
          env:
            GOOS: ${{matrix.goos}}
            GOARCH: ${{matrix.goarch}}
            GOARM: ${{matrix.goarm}}
          run: |
            make build
            make binaries
  
    #
    # Build containerd binaries
    #
    binaries:
      name: Binaries
      runs-on: ${{ matrix.os }}
      timeout-minutes: 20
      needs: [project, linters, protos, man]
  
      strategy:
        matrix:
          os: [ubuntu-22.04, ubuntu-24.04, ubuntu-24.04-arm, macos-13, windows-2022]
          go-version: ["1.24.6", "1.25.0"]
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: ./.github/actions/install-go
          with:
            go-version: ${{ matrix.go-version }}
        - name: Make
          run: |
            make build
            make binaries
  
    #
    # Integration and CRI tests
    #
    integration-windows:
      name: Windows Integration
      runs-on: ${{ matrix.os }}
      timeout-minutes: 90
      needs: [project, linters, protos, man]
      env:
        GOTEST: gotestsum --
  
      strategy:
        fail-fast: false
        matrix:
          os: [windows-2022]
          cgroup_driver: [cgroupfs]
  
      defaults:
        run:
          shell: bash
          working-directory: src/github.com/containerd/containerd
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
          with:
            path: src/github.com/containerd/containerd
  
        - uses: ./src/github.com/containerd/containerd/.github/actions/install-go
  
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
          with:
            repository: kubernetes-sigs/cri-tools
            path: src/github.com/kubernetes-sigs/cri-tools
            fetch-depth: 0
  
        - name: Set env
          run: |
            echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
            echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
            echo "${{ github.workspace }}/src/github.com/containerd/containerd/bin" >> $GITHUB_PATH
            echo "${{ github.workspace }}/src/github.com/kubernetes-sigs/cri-tools/build/bin/windows/amd64" >> $GITHUB_PATH
  
        - run: script/setup/install-dev-tools
  
        - name: Binaries
          shell: bash
          env:
            CGO_ENABLED: 1
          run: |
            set -o xtrace
            mingw32-make.exe binaries
            CRITEST_VERSION=$(cat script/setup/critools-version)
            cd ../../kubernetes-sigs/cri-tools
            git checkout "${CRITEST_VERSION}"
            make critest
  
        - run: script/setup/install-cni-windows
  
        - env:
            TEST_IMAGE_LIST: ${{github.workspace}}/repolist.toml
            CRI_TEST_IMAGES: ${{github.workspace}}/cri-test-images.yaml
            BUSYBOX_TESTING_IMAGE_REF: "registry.k8s.io/e2e-test-images/busybox:1.29-2"
            RESOURCE_CONSUMER_TESTING_IMAGE_REF: "registry.k8s.io/e2e-test-images/resource-consumer:1.10"
            WEBSERVER_TESTING_IMAGE_REF: "registry.k8s.io/e2e-test-images/nginx:1.14-2"
          run: |
            cat > "${{ env.TEST_IMAGE_LIST }}" << EOF
            busybox = "${{ env.BUSYBOX_TESTING_IMAGE_REF }}"
            ResourceConsumer = "${{ env.RESOURCE_CONSUMER_TESTING_IMAGE_REF }}"
            EOF
            cat > "${{ env.CRI_TEST_IMAGES }}" << EOF
            defaultTestContainerImage: ${{ env.BUSYBOX_TESTING_IMAGE_REF }}
            webServerTestImage: ${{ env.WEBSERVER_TESTING_IMAGE_REF }}
            EOF
  
        - name: Get crictl tool
          shell: powershell
          run: |
            # Get critctl tool. Used for cri-integration tests
            $CRICTL_DOWNLOAD_URL="https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.26.0/crictl-v1.26.0-windows-amd64.tar.gz"
            curl.exe -L $CRICTL_DOWNLOAD_URL -o c:\crictl.tar.gz
            tar -xvf c:\crictl.tar.gz
            mv crictl.exe "${{ github.workspace }}/bin/crictl.exe" # Move crictl somewhere in path
  
        - run: script/setup/install-gotestsum
        - run: script/setup/install-teststat
        - name: Tests
          env:
            CGO_ENABLED: 1
            GOTESTSUM_JUNITFILE: ${{github.workspace}}/test-unit-root.xml
            GOTESTSUM_JSONFILE: ${{github.workspace}}/test-unit-root-gotest.json
          run: mingw32-make.exe test root-test
        - run: if [ -f *-gotest.json ]; then echo '# Root Test' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh ${TESTFILE}
          env:
            TESTFILE: ${{github.workspace}}/test-unit-root-gotest.json
          if: always()
  
        - name: Integration 1
          env:
            CGO_ENABLED: 1
            GOTESTSUM_JUNITFILE: ${{github.workspace}}/test-integration-serial-junit.xml
            GOTESTSUM_JSONFILE: ${{github.workspace}}/test-integration-serial-gotest.json
            EXTRA_TESTFLAGS: "-timeout=20m"
          run: mingw32-make.exe integration
        - run: if [ -f *-gotest.json ]; then echo '# Integration 1' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh "$TESTFILE"
          env:
            TESTFILE: ${{github.workspace}}/test-integration-serial-gotest.json
          if: success()
  
        # Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
        - name: Integration 2
          env:
            TESTFLAGS_PARALLEL: 1
            EXTRA_TESTFLAGS: "-short"
            CGO_ENABLED: 1
            GOTESTSUM_JUNITFILE: ${{github.workspace}}/test-integration-parallel-junit.xml
            GOTESTSUM_JSONFILE: ${{github.workspace}}/test-integration-parallel-gotest.json
          run: mingw32-make.exe integration
        - run: if [ -f *-gotest.json ]; then echo '# Integration 2' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh "$TESTFILE"
          env:
            TESTFILE: ${{github.workspace}}/test-integration-parallel-gotest.json
          if: success()
  
        - name: CRI Integration Test
          env:
            TEST_IMAGE_LIST: ${{github.workspace}}/repolist.toml
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
          run: |
            make cri-integration
  
        - name: cri-tools critest
          env:
            CRI_TEST_IMAGES: ${{github.workspace}}/cri-test-images.yaml
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
          shell: powershell
          run: |
            Start-Process -FilePath containerd.exe -NoNewWindow -RedirectStandardError true -PassThru
            get-process | sls containerd
            start-sleep 5
            # This test is exceedingly flaky only on ws2022 so skip for now to keep CI happy.
            # Info: https://github.com/containerd/containerd/issues/6652
            if( '${{ matrix.os }}' -eq 'windows-2022' )
            {
              $skip = "-ginkgo.skip=runtime should support exec with tty=true and stdin=true"
            }
            critest.exe --runtime-endpoint=npipe://.//pipe//containerd-containerd --test-images-file='${{env.CRI_TEST_IMAGES}}' --report-dir='${{github.workspace}}/critestreport' $skip
  
        - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
          if: always()
          with:
            name: TestResults ${{ matrix.os }} ${{ matrix.cgroup_driver }}
            path: |
              ${{github.workspace}}/*-junit.xml
              ${{github.workspace}}/*-gotest.json
              ${{github.workspace}}/report/*.log
  
    integration-linux:
      name: Linux Integration
      runs-on: ${{ matrix.os }}
      timeout-minutes: 60
      needs: [project, linters, protos, man]
  
      strategy:
        fail-fast: false
        matrix:
          runtime:
            - io.containerd.runc.v2
          runc: [runc]  # crun can be added here to debug crun issues
          os: [ubuntu-22.04, ubuntu-24.04, ubuntu-24.04-arm]
          cgroup_driver: [cgroupfs, systemd]
  
      env:
        GOTEST: gotestsum --
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: ./.github/actions/install-go
  
        - name: Install containerd dependencies
          env:
            RUNC_FLAVOR: ${{ matrix.runc }}
          run: |
            sudo apt-get update
            sudo apt-get install -y gperf dmsetup strace xfsprogs
            script/setup/install-seccomp
            script/setup/install-runc
            script/setup/install-cni $(grep containernetworking/plugins go.mod | awk '{print $2}')
            script/setup/install-critools
            script/setup/install-failpoint-binaries
  
        # Disable criu testing on arm64 until we can solve the consistent failures of restore testing
        - if: matrix.os != 'ubuntu-24.04-arm'
          name: Install criu
          run: |
            sudo add-apt-repository -y ppa:criu/ppa
            sudo apt-get update
            sudo apt-get install -y criu
  
        - name: Install containerd
          env:
            CGO_ENABLED: 1
          run: |
            make binaries GO_BUILD_FLAGS="-mod=vendor"
            sudo -E PATH=$PATH make install
  
        - run: script/setup/install-gotestsum
        - run: script/setup/install-teststat
        - name: Tests
          env:
            GOTESTSUM_JUNITFILE: ${{github.workspace}}/test-unit-root-junit.xml
            GOTESTSUM_JSONFILE: ${{github.workspace}}/test-unit-root-gotest.json
          run: |
            make test
            sudo -E PATH=$PATH make root-test
        - run: if [ -f *-gotest.json ]; then echo '# Root Test' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh *-gotest.json
          if: always()
  
        - name: Integration 1
          env:
            TEST_RUNTIME: ${{ matrix.runtime }}
            RUNC_FLAVOR: ${{ matrix.runc }}
            GOTESTSUM_JUNITFILE: ${{github.workspace}}/test-integration-serial-junit.xml
            GOTESTSUM_JSONFILE: ${{github.workspace}}/test-integration-serial-gotest.json
          run: |
            extraflags=""
            [ "${RUNC_FLAVOR}" == "crun" ] && {
                    extraflags="EXTRA_TESTFLAGS=-no-criu";
            }
            sudo -E PATH=$PATH make integration ${extraflags} TESTFLAGS_RACE=-race
        - run: if [ -f *-gotest.json ]; then echo '# Integration 1' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh *-gotest.json
          if: always()
  
        # Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
        - name: Integration 2
          env:
            TEST_RUNTIME: ${{ matrix.runtime }}
            RUNC_FLAVOR: ${{ matrix.runc }}
            GOTESTSUM_JUNITFILE: ${{github.workspace}}/test-integration-parallel-junit.xml
            GOTESTSUM_JSONFILE: ${{github.workspace}}/test-integration-parallel-gotest.json
          run: |
            extraflags=""
            [ "${RUNC_FLAVOR}" == "crun" ] && {
                    extraflags="EXTRA_TESTFLAGS=-no-criu";
            }
            sudo -E PATH=$PATH TESTFLAGS_PARALLEL=1 make integration ${extraflags}
        - run: if [ -f *-gotest.json ]; then echo '# Integration 2' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh *-gotest.json
          if: always()
  
        - name: CRI Integration Test
          env:
            TEST_RUNTIME: ${{ matrix.runtime }}
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
            RUNC_FLAVOR: ${{ matrix.runc }}
          run: |
            cat /sys/fs/cgroup/cgroup.controllers
            systemctl status
            [ "${RUNC_FLAVOR}" == "crun" ] && {
               export XDG_RUNTIME_DIR=/run/user/$(id -u)
            }
            runc --version
            CONTAINERD_RUNTIME=$TEST_RUNTIME make cri-integration
  
        - name: cri-tools critest
          env:
            TEST_RUNTIME: ${{ matrix.runtime }}
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
          run: |
            env
            sudo -E PATH=$PATH ./script/critest.sh "${{github.workspace}}/report"
  
        - name: Install tools
          # The GitHub Actions image already has buildah and podman included. Not the
          # ubuntu-24.04-arm images. buildah and podman  is needed to convert the
          # Kubernetes checkpoint archive to an OCI image.
          # See contrib/checkpoint/checkpoint-restore-cri-test.sh
          if: matrix.os == 'ubuntu-24.04-arm'
          run: sudo apt-get install -y buildah podman
  
        - if: matrix.os != 'ubuntu-24.04-arm'
          name: Checkpoint/Restore via CRI
          env:
            TEST_RUNTIME: ${{ matrix.runtime }}
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
          run: |
            env
            sudo -E PATH=$PATH ./contrib/checkpoint/checkpoint-restore-cri-test.sh
  
        # Log the status of this VM to investigate issues like
        # https://github.com/containerd/containerd/issues/4969
        - name: Host Status
          if: always()
          run: |
            set -x
            mount
            df
            losetup -l
        - name: Kernel Message
          if: failure()
          run: |
            sudo lsmod
            sudo dmesg -T -f kern
  
        - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
          if: always()
          with:
            name: TestResults ${{ matrix.runtime }} ${{matrix.runc}} ${{ matrix.os }} ${{ matrix.cgroup_driver }}
            path: |
              *-junit.xml
              *-gotest.json
              ${{github.workspace}}/report/*.xml
              ${{github.workspace}}/report/*.log
  
    integration-vagrant:
      name: Vagrant integration
      runs-on: ubuntu-latest
      timeout-minutes: 60
      needs: [project, linters, protos, man]
  
      strategy:
        fail-fast: false
        matrix:
          include:
            - box: fedora/41-cloud-base
              cgroup_driver: cgroupfs
              runc: runc
            - box: fedora/41-cloud-base
              cgroup_driver: systemd
              runc: runc
            - box: fedora/41-cloud-base
              cgroup_driver: cgroupfs
              runc: crun
            - box: fedora/41-cloud-base
              cgroup_driver: systemd
              runc: crun
              # We have to keep EL8 to test old glibc, cgroup, kernel, etc.
              # The image was changed from rockylinux/8 to almalinux/8,
              # as the former one no longer works:
              # https://github.com/containerd/containerd/pull/10297
            - box: almalinux/8
              cgroup_driver: cgroupfs
              runc: runc
            - box: almalinux/8
              cgroup_driver: systemd
              runc: runc
            - box: almalinux/9
              cgroup_driver: cgroupfs
              runc: runc
            - box: almalinux/9
              cgroup_driver: systemd
              runc: runc
      env:
        BOX: ${{ matrix.box }}
        CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
        RUNC_FLAVOR: ${{ matrix.runc }}
      steps:
        - name: Show the host info
          run: |
            set -x
            uname -a
            cat /etc/os-release
            cat /proc/cpuinfo
            free -mt
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
          with:
            path: /root/.vagrant.d
            key: vagrant-${{ matrix.box }}
        - name: Set up vagrant
          run: |
            # Canonical's Vagrant 2.2.19 dpkg cannot download Fedora 38 image: https://bugs.launchpad.net/vagrant/+bug/2017828
            # So we have to install Vagrant >= 2.3.1 from the upstream: https://github.com/opencontainers/runc/blob/v1.1.8/.cirrus.yml#L41-L49
            curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
            echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
            sudo sed -i 's/^Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources
            sudo apt-get update
            sudo apt-get install -y libvirt-daemon libvirt-daemon-system vagrant ovmf
            # https://github.com/vagrant-libvirt/vagrant-libvirt/issues/1725#issuecomment-1454058646
            sudo cp /usr/share/OVMF/OVMF_VARS_4M.fd /var/lib/libvirt/qemu/nvram/
            sudo systemctl enable --now libvirtd
            sudo apt-get build-dep -y ruby-libvirt
            sudo apt-get install -y --no-install-recommends libxslt-dev libxml2-dev libvirt-dev ruby-bundler ruby-dev zlib1g-dev
            sudo env VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT=1 vagrant plugin install vagrant-libvirt
        - name: Boot VM
          run: |
            sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --no-tty
            if  [ "$BOX" = "fedora/41-cloud-base" ]; then
              # Install the kernel update for Fedora 41 to fix an error "Extension MARK revision 0 not supported, missing kernel module"
              # https://bugzilla.redhat.com/show_bug.cgi?id=2321325
              sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=upgrade-packages
              sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant halt
              sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant up
            fi
        - name: test-integration
          run: sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=selinux,install-runc,install-gotestsum,test-integration
        - name: test-cri-integration
          run: sudo BOX=$BOX CGROUP_DRIVER=$CGROUP_DRIVER RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=selinux,install-runc,install-gotestsum,test-cri-integration
        - name: test-cri
          run: sudo BOX=$BOX CGROUP_DRIVER=$CGROUP_DRIVER RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=selinux,install-runc,install-gotestsum,test-cri
  
    tests-cri-in-userns:
      name: "CRI-in-UserNS"
  
      runs-on: ubuntu-latest
      timeout-minutes: 40
      needs: [project, linters, protos, man]
  
      strategy:
        fail-fast: false
        matrix:
          cgroup_driver: [cgroupfs, systemd]
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - name: Set up cgroup v2 delegation
          run: |
            sudo mkdir -p /etc/systemd/system/user@.service.d
            cat <<EOF | sudo tee /etc/systemd/system/user@.service.d/delegate.conf
            [Service]
            Delegate=cpu cpuset io memory pids
            EOF
            sudo systemctl daemon-reload
        - name: Build cri-in-userns image
          env:
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
          run: |
            if [ "$CGROUP_DRIVER" = "systemd" ];then
              podman build --target cri-in-userns-systemd -t cri-in-userns-systemd -f ./contrib/Dockerfile.test .
            else
              podman build --target cri-in-userns -t cri-in-userns -f ./contrib/Dockerfile.test .
            fi
  
        - name: Run cri-in-userns image
          env:
            CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
          # Rootless Podman is used for testing CRI-in-UserNS
          # (We could use rootless Docker or rootless nerdctl, but we are using Podman here because it is preinstalled)
          run: |
            if [ "$CGROUP_DRIVER" = "systemd" ];then
                set +e
                touch ./critest_exit_code.txt
                podman run --rm --privileged --group-add keep-groups -v ./critest_exit_code.txt:/tmp/critest_exit_code.txt cri-in-userns-systemd
                exit_code=`cat ./critest_exit_code.txt`
                echo "exit_code:"$exit_code
                if [ "$exit_code" -gt 0 ]; then
                  exit 1
                else
                  exit 0
                fi
            else
              podman run --rm --privileged cri-in-userns
            fi
  
    tests-mac-os:
      name: MacOS unit tests
      runs-on: macos-latest
      timeout-minutes: 10
      needs: [project, linters, protos, man]
      env:
        GOTEST: gotestsum --
  
      steps:
        - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        - uses: ./.github/actions/install-go
        - run: script/setup/install-gotestsum
        - run: script/setup/install-teststat
        - name: Tests
          env:
            GOTESTSUM_JUNITFILE: "${{ github.workspace }}/macos-test-junit.xml"
            GOTESTSUM_JSONFILE: "${{ github.workspace }}/macos-test-gotest.json"
          run: make test
        - run: if [ -f *-gotest.json ]; then echo '# Unit Tests' >> $GITHUB_STEP_SUMMARY; teststat -markdown *-gotest.json >> $GITHUB_STEP_SUMMARY; fi
          if: always()
        - run: script/test/test2annotation.sh *-gotest.json
          if: always()
        - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
          if: always()
          with:
            name: TestResults MacOS
            path: |
              *-junit.xml
              *-gotest.json
  
    # Currently Github actions UI supports no masks to mark matrix jobs as required to pass status checks.
    # This means that every time version of Go, containerd, or OS is changed, a corresponding job should
    # be added to the list of required checks. Which is not very convenient.
    # To workaround this, a special job is added to report statuses of all other jobs, with fixed title.
    # So it needs to be added to the list of required checks only once.
    #
    # See https://github.com/orgs/community/discussions/26822
    results:
      name: Report required job statuses
      runs-on: ubuntu-latest
      # List job dependencies which are required to pass status checks in order to be merged via merge queue.
      needs: [linters, project, protos, binaries, integration-linux, integration-windows, tests-cri-in-userns, tests-mac-os]
      if: ${{ always() }}
      steps:
        - run: exit 1
          if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
  
  ```
  
  This GitHub Actions workflow demonstrates production CI/CD practices including automated testing, building, and deployment.