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