github.com/containers/podman/v4@v4.9.4/contrib/cirrus/runner.sh (about)

     1  #!/bin/bash
     2  
     3  set -eo pipefail
     4  
     5  # This script runs in the Cirrus CI environment, invoked from .cirrus.yml .
     6  # It can also be invoked manually in a `hack/get_ci_cm.sh` environment,
     7  # documentation of said usage is TBI.
     8  #
     9  # The principal deciding factor is the $TEST_FLAVOR envariable: for any
    10  # given value 'xyz' there must be a function '_run_xyz' to handle that
    11  # test. Several other envariables are used to differentiate further,
    12  # most notably:
    13  #
    14  #    PODBIN_NAME  : "podman" (i.e. local) or "remote"
    15  #    TEST_ENVIRON : 'host', or 'container'; desired environment in which to run
    16  #    CONTAINER    : 1 if *currently* running inside a container, 0 if host
    17  #
    18  
    19  # shellcheck source=contrib/cirrus/lib.sh
    20  source $(dirname $0)/lib.sh
    21  
    22  showrun echo "starting"
    23  
    24  function _run_validate() {
    25      # TODO: aarch64 images need python3-devel installed
    26      # https://github.com/containers/automation_images/issues/159
    27      showrun bigto ooe.sh dnf install -y python3-devel
    28  
    29      # git-validation tool fails if $EPOCH_TEST_COMMIT is empty
    30      # shellcheck disable=SC2154
    31      if [[ -n "$EPOCH_TEST_COMMIT" ]]; then
    32          showrun make validate
    33      else
    34          warn "Skipping git-validation since \$EPOCH_TEST_COMMIT is empty"
    35      fi
    36  
    37  }
    38  
    39  function _run_unit() {
    40      _bail_if_test_can_be_skipped test/goecho test/version
    41  
    42      # shellcheck disable=SC2154
    43      if [[ "$PODBIN_NAME" != "podman" ]]; then
    44          # shellcheck disable=SC2154
    45          die "$TEST_FLAVOR: Unsupported PODBIN_NAME='$PODBIN_NAME'"
    46      fi
    47      showrun make localunit
    48  }
    49  
    50  function _run_apiv2() {
    51      _bail_if_test_can_be_skipped test/apiv2
    52  
    53      (
    54          showrun make localapiv2-bash
    55          source .venv/requests/bin/activate
    56          showrun make localapiv2-python
    57      ) |& logformatter
    58  }
    59  
    60  function _run_compose() {
    61      _bail_if_test_can_be_skipped test/compose
    62  
    63      showrun ./test/compose/test-compose |& logformatter
    64  }
    65  
    66  function _run_compose_v2() {
    67      _bail_if_test_can_be_skipped test/compose
    68  
    69      showrun ./test/compose/test-compose |& logformatter
    70  }
    71  
    72  function _run_int() {
    73      _bail_if_test_can_be_skipped test/e2e
    74  
    75      dotest integration
    76  }
    77  
    78  function _run_sys() {
    79      _bail_if_test_can_be_skipped test/system
    80  
    81      dotest system
    82  }
    83  
    84  function _run_upgrade_test() {
    85      _bail_if_test_can_be_skipped test/system test/upgrade
    86  
    87      showrun bats test/upgrade |& logformatter
    88  }
    89  
    90  function _run_bud() {
    91      _bail_if_test_can_be_skipped test/buildah-bud
    92  
    93      showrun ./test/buildah-bud/run-buildah-bud-tests |& logformatter
    94  }
    95  
    96  function _run_bindings() {
    97      # install ginkgo
    98      showrun make .install.ginkgo
    99  
   100      # shellcheck disable=SC2155
   101      export PATH=$PATH:$GOSRC/hack:$GOSRC/test/tools/build
   102  
   103      # if logformatter sees this, it can link directly to failing source lines
   104      local gitcommit_magic=
   105      if [[ -n "$GIT_COMMIT" ]]; then
   106          gitcommit_magic="/define.gitCommit=${GIT_COMMIT}"
   107      fi
   108  
   109      (echo "$gitcommit_magic" && \
   110          showrun make testbindings) |& logformatter
   111  }
   112  
   113  function _run_docker-py() {
   114      source .venv/docker-py/bin/activate
   115      showrun make run-docker-py-tests
   116  }
   117  
   118  function _run_endpoint() {
   119      showrun make test-binaries
   120      showrun make endpoint
   121  }
   122  
   123  function _run_minikube() {
   124      _bail_if_test_can_be_skipped test/minikube
   125      msg "Testing  minikube."
   126      showrun bats test/minikube |& logformatter
   127  }
   128  
   129  function _run_farm() {
   130      _bail_if_test_can_be_skipped test/farm test/system
   131      msg "Testing podman farm."
   132      showrun bats test/farm |& logformatter
   133  }
   134  
   135  exec_container() {
   136      local var_val
   137      local cmd
   138      # Required to be defined by caller
   139      # shellcheck disable=SC2154
   140      msg "Re-executing runner inside container: $CTR_FQIN"
   141      msg "************************************************************"
   142  
   143      req_env_vars CTR_FQIN TEST_ENVIRON CONTAINER SECRET_ENV_RE
   144  
   145      # Line-separated arguments which include shell-escaped special characters
   146      declare -a envargs
   147      while read -r var; do
   148          # Pass "-e VAR" on the command line, not "-e VAR=value". Podman can
   149          # do a much better job of transmitting the value than we can,
   150          # especially when value includes spaces.
   151          envargs+=("-e" "$var")
   152      done <<<"$(passthrough_envars)"
   153  
   154      # VM Images and Container images are built using (nearly) identical operations.
   155      set -x
   156      # shellcheck disable=SC2154
   157      exec bin/podman run --rm --privileged --net=host --cgroupns=host \
   158          -v `mktemp -d -p /var/tmp`:/tmp:Z \
   159          -v /dev/fuse:/dev/fuse \
   160          -v "$GOPATH:$GOPATH:Z" \
   161          --workdir "$GOSRC" \
   162          -e "CONTAINER=1" \
   163          "${envargs[@]}" \
   164          $CTR_FQIN bash -c "$SCRIPT_BASE/setup_environment.sh && $SCRIPT_BASE/runner.sh"
   165  }
   166  
   167  function _run_swagger() {
   168      local upload_filename
   169      local upload_bucket
   170      local download_url
   171      local envvarsfile
   172      req_env_vars GCPJSON GCPNAME GCPPROJECT CTR_FQIN
   173  
   174      [[ -x /usr/local/bin/swagger ]] || \
   175          die "Expecting swagger binary to be present and executable."
   176  
   177      # The filename and bucket depend on the automation context
   178      #shellcheck disable=SC2154,SC2153
   179      if [[ -n "$CIRRUS_PR" ]]; then
   180          upload_bucket="libpod-pr-releases"
   181          upload_filename="swagger-pr$CIRRUS_PR.yaml"
   182      elif [[ -n "$CIRRUS_TAG" ]]; then
   183          upload_bucket="libpod-master-releases"
   184          upload_filename="swagger-$CIRRUS_TAG.yaml"
   185      elif [[ "$CIRRUS_BRANCH" == "main" ]]; then
   186          upload_bucket="libpod-master-releases"
   187          # readthedocs versioning uses "latest" for "main" (default) branch
   188          upload_filename="swagger-latest.yaml"
   189      elif [[ -n "$CIRRUS_BRANCH" ]]; then
   190          upload_bucket="libpod-master-releases"
   191          upload_filename="swagger-$CIRRUS_BRANCH.yaml"
   192      else
   193          die "Unknown execution context, expected a non-empty value for \$CIRRUS_TAG, \$CIRRUS_BRANCH, or \$CIRRUS_PR"
   194      fi
   195  
   196      # Swagger validation takes a significant amount of time
   197      msg "Pulling \$CTR_FQIN '$CTR_FQIN' (background process)"
   198      showrun bin/podman pull --quiet $CTR_FQIN &
   199  
   200      cd $GOSRC
   201      showrun make swagger
   202  
   203      # Cirrus-CI Artifact instruction expects file here
   204      cp -v $GOSRC/pkg/api/swagger.yaml ./
   205  
   206      envvarsfile=$(mktemp -p '' .tmp_$(basename $0)_XXXXXXXX)
   207      trap "rm -f $envvarsfile" EXIT  # contains secrets
   208      # Warning: These values must _not_ be quoted, podman will not remove them.
   209      #shellcheck disable=SC2154
   210      cat <<eof >>$envvarsfile
   211  GCPJSON=$GCPJSON
   212  GCPNAME=$GCPNAME
   213  GCPPROJECT=$GCPPROJECT
   214  FROM_FILEPATH=$GOSRC/swagger.yaml
   215  TO_GCSURI=gs://$upload_bucket/$upload_filename
   216  eof
   217  
   218      msg "Waiting for backgrounded podman pull to complete..."
   219      wait %%
   220      showrun bin/podman run -it --rm --security-opt label=disable \
   221          --env-file=$envvarsfile \
   222          -v $GOSRC:$GOSRC:ro \
   223          --workdir $GOSRC \
   224          $CTR_FQIN
   225      rm -f $envvarsfile
   226  }
   227  
   228  function _run_build() {
   229      # Ensure always start from clean-slate with all vendor modules downloaded
   230      showrun make clean
   231      showrun make vendor
   232      showrun make podman-release  # includes podman, podman-remote, and docs
   233  
   234      # Last-minute confirmation that we're testing the desired runtime.
   235      # This Can't Possibly Failâ„¢ in regular CI; only when updating VMs.
   236      # $CI_DESIRED_RUNTIME must be defined in .cirrus.yml.
   237      req_env_vars CI_DESIRED_RUNTIME
   238      runtime=$(bin/podman info --format '{{.Host.OCIRuntime.Name}}')
   239      # shellcheck disable=SC2154
   240      if [[ "$runtime" != "$CI_DESIRED_RUNTIME" ]]; then
   241          die "Built podman is using '$runtime'; this CI environment requires $CI_DESIRED_RUNTIME"
   242      fi
   243      msg "Built podman is using expected runtime='$runtime'"
   244  }
   245  
   246  function _run_altbuild() {
   247      # Subsequent windows-based tasks require a build.  Var. defined in .cirrus.yml
   248      # shellcheck disable=SC2154
   249      if [[ ! "$ALT_NAME" =~ Windows ]]; then
   250          # We can skip all these steps for test-only PRs, but not doc-only ones
   251          _bail_if_test_can_be_skipped docs
   252      fi
   253  
   254      local -a arches
   255      local arch
   256      req_env_vars ALT_NAME
   257      msg "Performing alternate build: $ALT_NAME"
   258      msg "************************************************************"
   259      set -x
   260      cd $GOSRC
   261      case "$ALT_NAME" in
   262          *Each*)
   263              showrun git fetch origin
   264              # The make-and-check-size script, introduced 2022-03-22 in #13518,
   265              # runs 'make' (the original purpose of this check) against
   266              # each commit, then checks image sizes to make sure that
   267              # none have grown beyond a given limit. That of course
   268              # requires a baseline, so our first step is to build the
   269              # branch point of the PR.
   270              local context_dir savedhead pr_base
   271              context_dir=$(mktemp -d --tmpdir make-size-check.XXXXXXX)
   272              savedhead=$(git rev-parse HEAD)
   273              # Push to PR base. First run of the script will write size files
   274              pr_base=$(git merge-base origin/$DEST_BRANCH HEAD)
   275              showrun git checkout $pr_base
   276              showrun hack/make-and-check-size $context_dir
   277              # pop back to PR, and run incremental makes. Subsequent script
   278              # invocations will compare against original size.
   279              showrun git checkout $savedhead
   280              showrun git rebase $pr_base -x "hack/make-and-check-size $context_dir"
   281              rm -rf $context_dir
   282              ;;
   283          *Windows*)
   284              showrun make podman-remote-release-windows_amd64.zip
   285              ;;
   286          *RPM*)
   287              showrun make package
   288              ;;
   289          Alt*x86*Cross)
   290              arches=(\
   291                  amd64
   292                  386)
   293              _build_altbuild_archs "${arches[@]}"
   294              ;;
   295          Alt*ARM*Cross)
   296              arches=(\
   297                  arm
   298                  arm64)
   299              _build_altbuild_archs "${arches[@]}"
   300              ;;
   301          Alt*Other*Cross)
   302              arches=(\
   303                  ppc64le
   304                  s390x)
   305              _build_altbuild_archs "${arches[@]}"
   306              ;;
   307          Alt*MIPS*Cross)
   308              arches=(\
   309                  mips
   310                  mipsle)
   311              _build_altbuild_archs "${arches[@]}"
   312              ;;
   313          Alt*MIPS64*Cross*)
   314              arches=(\
   315                  mips64
   316                  mips64le)
   317              _build_altbuild_archs "${arches[@]}"
   318              ;;
   319          *)
   320              die "Unknown/Unsupported \$$ALT_NAME '$ALT_NAME'"
   321      esac
   322  }
   323  
   324  function _build_altbuild_archs() {
   325      for arch in "$@"; do
   326          msg "Building release archive for $arch"
   327          showrun make podman-release-${arch}.tar.gz GOARCH=$arch
   328      done
   329  }
   330  
   331  function _run_release() {
   332      msg "podman info:"
   333      bin/podman info
   334  
   335      msg "Checking podman release (or potential release) criteria."
   336      # We're running under 'set -eo pipefail'; make sure this statement passes
   337      dev=$(bin/podman info |& grep -- -dev || echo -n '')
   338      if [[ -n "$dev" ]]; then
   339          die "Releases must never contain '-dev' in output of 'podman info' ($dev)"
   340      fi
   341  
   342      commit=$(bin/podman info --format='{{.Version.GitCommit}}' | tr -d '[:space:]')
   343      if [[ -z "$commit" ]]; then
   344          die "Releases must contain a non-empty Version.GitCommit in 'podman info'"
   345      fi
   346      msg "All OK"
   347  }
   348  
   349  
   350  # ***WARNING*** ***WARNING*** ***WARNING*** ***WARNING***
   351  #    Please see gitlab comment in setup_environment.sh
   352  # ***WARNING*** ***WARNING*** ***WARNING*** ***WARNING***
   353  function _run_gitlab() {
   354      rootless_uid=$(id -u)
   355      systemctl enable --now --user podman.socket
   356      export DOCKER_HOST=unix:///run/user/${rootless_uid}/podman/podman.sock
   357      export CONTAINER_HOST=$DOCKER_HOST
   358      cd $GOPATH/src/gitlab.com/gitlab-org/gitlab-runner
   359      set +e
   360      go test -v ./executors/docker |& tee $GOSRC/gitlab-runner-podman.log
   361      ret=$?
   362      set -e
   363      # This file is collected and parsed by Cirrus-CI so must be in $GOSRC
   364      cat $GOSRC/gitlab-runner-podman.log | \
   365          go-junit-report > $GOSRC/gitlab-runner-podman.xml
   366      return $ret
   367  }
   368  
   369  
   370  # Name pattern for logformatter output file, derived from environment
   371  function output_name() {
   372      # .cirrus.yml defines this as a short readable string for web UI
   373      std_name_fmt=$(sed -ne 's/^.*std_name_fmt \"\(.*\)\"/\1/p' <.cirrus.yml)
   374      test -n "$std_name_fmt" || die "Could not grep 'std_name_fmt' from .cirrus.yml"
   375  
   376      # Interpolate envariables. 'set -u' throws fatal if any are undefined
   377      (
   378          set -u
   379          eval echo "$std_name_fmt" | tr ' ' '-'
   380      )
   381  }
   382  
   383  function logformatter() {
   384      if [[ "$CI" == "true" ]]; then
   385          # Requires stdin and stderr combined!
   386          cat - \
   387              |& awk --file "${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/timestamp.awk" \
   388              |& "${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/logformatter" "$(output_name)"
   389      else
   390          # Assume script is run by a human, they want output immediately
   391          cat -
   392      fi
   393  }
   394  
   395  # Handle local|remote integration|system testing in a uniform way
   396  dotest() {
   397      local testsuite="$1"
   398      req_env_vars testsuite CONTAINER TEST_ENVIRON PRIV_NAME
   399  
   400      # shellcheck disable=SC2154
   401      if ((CONTAINER==0)) && [[ "$TEST_ENVIRON" == "container" ]]; then
   402          exec_container  # does not return
   403      fi;
   404  
   405      # containers/automation sets this to 0 for its dbg() function
   406      # but the e2e integration tests are also sensitive to it.
   407      unset DEBUG
   408  
   409      # shellcheck disable=SC2154
   410      local localremote="$PODBIN_NAME"
   411      case "$PODBIN_NAME" in
   412          podman)  localremote="local" ;;
   413      esac
   414  
   415      # We've had some oopsies where tests invoke 'podman' instead of
   416      # /path/to/built/podman. Let's catch those.
   417      sudo rm -f /usr/bin/podman /usr/bin/podman-remote
   418      fallback_podman=$(type -p podman || true)
   419      if [[ -n "$fallback_podman" ]]; then
   420          die "Found fallback podman '$fallback_podman' in \$PATH; tests require none, as a guarantee that we're testing the right binary."
   421      fi
   422  
   423      showrun make ${localremote}${testsuite} PODMAN_SERVER_LOG=$PODMAN_SERVER_LOG \
   424          |& logformatter
   425  }
   426  
   427  _run_machine-linux() {
   428      # N/B: Can't use _bail_if_test_can_be_skipped here b/c content isn't under test/
   429      showrun make localmachine |& logformatter
   430  }
   431  
   432  # Optimization: will exit if the only PR diffs are under docs/ or tests/
   433  # with the exception of any given arguments. E.g., don't run e2e or unit
   434  # or bud tests if the only PR changes are in test/system.
   435  function _bail_if_test_can_be_skipped() {
   436      local head base diffs
   437  
   438      # Cirrus sets these for PRs but not branches or cron. In cron and branches,
   439      #we never want to skip.
   440      for v in CIRRUS_CHANGE_IN_REPO CIRRUS_PR DEST_BRANCH; do
   441          if [[ -z "${!v}" ]]; then
   442              msg "[ _cannot do selective skip: \$$v is undefined ]"
   443              return 0
   444          fi
   445      done
   446      # And if this one *is* defined, it means we're not in PR-land; don't skip.
   447      if [[ -n "$CIRRUS_TAG" ]]; then
   448          msg "[ _cannot do selective skip: \$CIRRUS_TAG is defined ]"
   449          return 0
   450      fi
   451  
   452      # Defined by Cirrus-CI for all tasks
   453      # shellcheck disable=SC2154
   454      head=$CIRRUS_CHANGE_IN_REPO
   455      base=$(git merge-base $DEST_BRANCH $head)
   456      diffs=$(git diff --name-only $base $head)
   457  
   458      # If PR touches any files in an argument directory, we cannot skip
   459      for subdir in "$@"; do
   460          if grep -E -q "^$subdir/" <<<"$diffs"; then
   461              return 0
   462          fi
   463      done
   464  
   465      # PR does not touch any files under our input directories. Now see
   466      # if the PR touches files outside of the following directories, by
   467      # filtering these out from the diff results.
   468      for subdir in docs test; do
   469          # || true needed because we're running with set -e
   470          diffs=$(grep -E -v "^$subdir/" <<<"$diffs" || true)
   471      done
   472  
   473      # If we still have diffs, they indicate files outside of docs & test.
   474      # It is not safe to skip.
   475      if [[ -n "$diffs" ]]; then
   476          return 0
   477      fi
   478  
   479      msg "SKIPPING: This is a doc- and/or test-only PR with no changes under $*"
   480      exit 0
   481  }
   482  
   483  # Nearly every task in .cirrus.yml makes use of this shell script
   484  # wrapped by /usr/bin/time to collect runtime statistics.  Because the
   485  # --output option is used to log stats to a file, every child-process
   486  # inherits an open FD3 pointing at the log.  However, some testing
   487  # operations depend on making use of FD3, and so it must be explicitly
   488  # closed here (and for all further child-processes).
   489  # STATS_LOGFILE assumed empty/undefined outside of Cirrus-CI (.cirrus.yml)
   490  # shellcheck disable=SC2154
   491  exec 3<&-
   492  
   493  msg "************************************************************"
   494  # Required to be defined by caller
   495  # shellcheck disable=SC2154
   496  msg "Runner executing $TEST_FLAVOR $PODBIN_NAME-tests as $PRIV_NAME on $DISTRO_NV($OS_REL_VER)"
   497  if ((CONTAINER)); then
   498      # shellcheck disable=SC2154
   499      msg "Current environment container image: $CTR_FQIN"
   500  else
   501      # shellcheck disable=SC2154
   502      msg "Current environment VM image: $VM_IMAGE_NAME"
   503  fi
   504  msg "************************************************************"
   505  
   506  ((${SETUP_ENVIRONMENT:-0})) || \
   507      die "Expecting setup_environment.sh to have completed successfully"
   508  
   509  # shellcheck disable=SC2154
   510  if [[ "$PRIV_NAME" == "rootless" ]] && [[ "$UID" -eq 0 ]]; then
   511      # Remove /var/lib/cni, it is not required for rootless cni.
   512      # We have to test that it works without this directory.
   513      # https://github.com/containers/podman/issues/10857
   514      rm -rf /var/lib/cni
   515  
   516      # This must be done at the last second, otherwise `make` calls
   517      # in setup_environment (as root) will balk about ownership.
   518      msg "Recursively chowning \$GOPATH and \$GOSRC to $ROOTLESS_USER"
   519      if [[ $PRIV_NAME = "rootless" ]]; then
   520          chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
   521      fi
   522  
   523      req_env_vars ROOTLESS_USER
   524      msg "Re-executing runner through ssh as user '$ROOTLESS_USER'"
   525      msg "************************************************************"
   526      set -x
   527      exec ssh $ROOTLESS_USER@localhost \
   528              -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
   529              -o CheckHostIP=no $GOSRC/$SCRIPT_BASE/runner.sh
   530      # Does not return!
   531  fi
   532  # else: not running rootless, do nothing special
   533  
   534  # Dump important package versions. Before 2022-11-16 this took place as
   535  # a separate .cirrus.yml step, but it really belongs here.
   536  $(dirname $0)/logcollector.sh packages
   537  msg "************************************************************"
   538  
   539  
   540  cd "${GOSRC}/"
   541  
   542  handler="_run_${TEST_FLAVOR}"
   543  
   544  if [ "$(type -t $handler)" != "function" ]; then
   545      die "Unknown/Unsupported \$TEST_FLAVOR=$TEST_FLAVOR"
   546  fi
   547  
   548  showrun $handler
   549  
   550  showrun echo "finished"