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"