From b93d60f9eee7cd095d34cb098d4d711cede3aeaf Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Tue, 8 Dec 2020 11:13:41 -0500 Subject: [PATCH 01/11] Add GitHub Actions CI --- .github/workflows/CI.yml | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/CI.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 00000000..12d29afe --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,55 @@ +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events + push: + pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + strategy: + matrix: + include: + - name: "MoltenVK (macOS)" + platform: "macos" + scheme: "MoltenVK Package (macOS only)" + demos-scheme: "Cube-macOS" + - name: "MoltenVK (iOS)" + platform: "ios" + scheme: "MoltenVK Package (iOS only)" + demos-scheme: "" + - name: "MoltenVK (tvOS)" + platform: "tvos" + scheme: "MoltenVK Package (tvOS only)" + demos-scheme: "" + fail-fast: false + + name: '${{ matrix.name }}' + + # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/specifications-for-github-hosted-runners#supported-runners-and-hardware-resources + runs-on: macos-latest + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + - name: Select Xcode version + # See: https://github.com/actions/virtual-environments/tree/main/images/macos + run: sudo xcode-select -switch /Applications/Xcode_12.2.app/Contents/Developer + + - name: Fetch Dependencies + run: | + ./fetchDependencies -v --no-parallel-build --${{ matrix.platform }} + + - name: Build MoltenVK + run: | + xcodebuild build -project MoltenVKPackaging.xcodeproj -scheme "${{ matrix.scheme }}" + + - name: Build Demos + if: success() && !(matrix.demos-scheme == '') + run: | + xcodebuild build -workspace Demos/Demos.xcworkspace -scheme "${{ matrix.demos-scheme }}" From c39f156ed997099d16d565a7c1c173fa695d8125 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Tue, 8 Dec 2020 11:36:29 -0500 Subject: [PATCH 02/11] GitHub Actions: Use xcpretty --- .github/workflows/CI.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 12d29afe..6fcc87d7 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -41,14 +41,22 @@ jobs: # See: https://github.com/actions/virtual-environments/tree/main/images/macos run: sudo xcode-select -switch /Applications/Xcode_12.2.app/Contents/Developer + - name: Create Build Logs Dir + run: | + mkdir -p "${HOME}/build_logs" + - name: Fetch Dependencies run: | ./fetchDependencies -v --no-parallel-build --${{ matrix.platform }} - name: Build MoltenVK run: | - xcodebuild build -project MoltenVKPackaging.xcodeproj -scheme "${{ matrix.scheme }}" - + set -o pipefail && xcodebuild build -project MoltenVKPackaging.xcodeproj -scheme "${{ matrix.scheme }}" | tee "${HOME}/build_logs/xcodebuild.log" | xcpretty -c + + - name: Output Build Logs on Failure + if: failure() + run: cat "${HOME}/build_logs/xcodebuild.log" + - name: Build Demos if: success() && !(matrix.demos-scheme == '') run: | From aa46313ae6ae4fb68e95e2f83f07ea227305b9f2 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Tue, 8 Dec 2020 12:02:55 -0500 Subject: [PATCH 03/11] GitHub Actions: Upload artifacts --- .github/workflows/CI.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6fcc87d7..dd5cba41 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -61,3 +61,13 @@ jobs: if: success() && !(matrix.demos-scheme == '') run: | xcodebuild build -workspace Demos/Demos.xcworkspace -scheme "${{ matrix.demos-scheme }}" + + - name: Tar Artifacts + # See: https://github.com/actions/upload-artifact#maintaining-file-permissions-and-case-sensitive-files + run: tar -cvf "${{ matrix.platform }}.tar" Package/Release/ + + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.platform }} + path: "${{ matrix.platform }}.tar" From 3443a9440714e7e3229b07f6641a8c56bc43a935 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Tue, 8 Dec 2020 13:21:57 -0500 Subject: [PATCH 04/11] GitHub Actions: Cache dependencies --- .github/workflows/CI.yml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index dd5cba41..5bbf9bf9 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -41,11 +41,33 @@ jobs: # See: https://github.com/actions/virtual-environments/tree/main/images/macos run: sudo xcode-select -switch /Applications/Xcode_12.2.app/Contents/Developer - - name: Create Build Logs Dir + - name: Prep + id: prep run: | + echo "Create Build Logs Dir" mkdir -p "${HOME}/build_logs" + echo "Get Xcode version info" + XCODE_VERSION="$(xcodebuild -version)" + echo "${XCODE_VERSION}" + XCODE_VERSION="$(echo "${XCODE_VERSION}" | tr '\t\r\n ' '_')" + echo "${XCODE_VERSION}" + echo "::set-output name=XCODE_VERSION::${XCODE_VERSION}" + + - name: Cache Dependencies + id: cache-dependencies + if: success() && !(github.event_name == 'push' && contains(github.ref, 'refs/tags/')) # never cache dependencies for pushed tags + uses: actions/cache@v2 + with: + path: External/build/ + key: ${{ runner.os }}-${{ steps.prep.outputs.XCODE_VERSION }}-${{ matrix.platform }}-${{ hashFiles('fetchDependencies','ExternalRevisions/**','ExternalDependencies.xcodeproj/**','Scripts/**') }} + + - name: Fetch Dependencies (Use Built Cache) + if: steps.cache-dependencies.outputs.cache-hit == 'true' + run: | + ./fetchDependencies -v --no-parallel-build --none - name: Fetch Dependencies + if: steps.cache-dependencies.outputs.cache-hit != 'true' run: | ./fetchDependencies -v --no-parallel-build --${{ matrix.platform }} From 32abeab72229eb772f8553df9d8fa183a8d3c049 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 09:36:17 -0500 Subject: [PATCH 05/11] Makefile: Support xcpretty (if available), falling back to xcodebuild -quiet parameter --- Makefile | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index e96a870a..2faf9f9f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,19 @@ XC_PROJ := MoltenVKPackaging.xcodeproj XC_SCHEME := MoltenVK Package +XCODEBUILD := set -o pipefail && $(shell command -v xcodebuild) +# Used to determine if xcpretty is available +XCPRETTY_PATH := $(shell command -v xcpretty 2> /dev/null) + +OUTPUT_FMT_CMD = +ifdef XCPRETTY_PATH + # Pipe output to xcpretty, while preserving full log as xcodebuild.log + OUTPUT_FMT_CMD = | tee "xcodebuild.log" | xcpretty -c +else + # Use xcodebuild -quiet parameter + OUTPUT_FMT_CMD = -quiet +endif + # Specify individually (not as dependencies) so the sub-targets don't run in parallel .PHONY: all all: @@ -22,55 +35,55 @@ all-debug: .PHONY: macos macos: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (macOS only)" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (macOS only)" $(OUTPUT_FMT_CMD) .PHONY: macos-debug macos-debug: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (macOS only)" -configuration "Debug" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (macOS only)" -configuration "Debug" $(OUTPUT_FMT_CMD) .PHONY: ios ios: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" $(OUTPUT_FMT_CMD) .PHONY: ios-debug ios-debug: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -configuration "Debug" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -configuration "Debug" $(OUTPUT_FMT_CMD) .PHONY: iossim iossim: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=iOS Simulator" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=iOS Simulator" $(OUTPUT_FMT_CMD) .PHONY: iossim-debug iossim-debug: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=iOS Simulator" -configuration "Debug" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=iOS Simulator" -configuration "Debug" $(OUTPUT_FMT_CMD) .PHONY: maccat maccat: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=macOS,variant=Mac Catalyst" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=macOS,variant=Mac Catalyst" $(OUTPUT_FMT_CMD) .PHONY: maccat-debug maccat-debug: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=macOS,variant=Mac Catalyst" -configuration "Debug" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (iOS only)" -destination "generic/platform=macOS,variant=Mac Catalyst" -configuration "Debug" $(OUTPUT_FMT_CMD) .PHONY: tvos tvos: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" $(OUTPUT_FMT_CMD) .PHONY: tvos-debug tvos-debug: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -configuration "Debug" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -configuration "Debug" $(OUTPUT_FMT_CMD) .PHONY: tvossim tvossim: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -destination "generic/platform=tvOS Simulator" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -destination "generic/platform=tvOS Simulator" $(OUTPUT_FMT_CMD) .PHONY: tvossim-debug tvossim-debug: - xcodebuild build -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -destination "generic/platform=tvOS Simulator" -configuration "Debug" + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -destination "generic/platform=tvOS Simulator" -configuration "Debug" $(OUTPUT_FMT_CMD) .PHONY: clean clean: - xcodebuild clean -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME)" + $(XCODEBUILD) clean -quiet -project "$(XC_PROJ)" -scheme "$(XC_SCHEME)" rm -rf Package # Usually requires 'sudo make install' From 2657ee59a5a23f3a2d4994603ad33dccc2393fe7 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 09:47:08 -0500 Subject: [PATCH 06/11] GitHub Actions: Use Makefile --- .github/workflows/CI.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5bbf9bf9..d15f454f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -8,6 +8,10 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: +env: + # See: https://github.com/actions/virtual-environments/tree/main/images/macos + XCODE_DEV_PATH: /Applications/Xcode_12.2.app/Contents/Developer + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: build: @@ -16,15 +20,15 @@ jobs: include: - name: "MoltenVK (macOS)" platform: "macos" - scheme: "MoltenVK Package (macOS only)" demos-scheme: "Cube-macOS" + - name: "MoltenVK (macCatalyst)" + platform: "maccat" + demos-scheme: "" - name: "MoltenVK (iOS)" platform: "ios" - scheme: "MoltenVK Package (iOS only)" demos-scheme: "" - name: "MoltenVK (tvOS)" platform: "tvos" - scheme: "MoltenVK Package (tvOS only)" demos-scheme: "" fail-fast: false @@ -38,14 +42,11 @@ jobs: - uses: actions/checkout@v2 - name: Select Xcode version - # See: https://github.com/actions/virtual-environments/tree/main/images/macos - run: sudo xcode-select -switch /Applications/Xcode_12.2.app/Contents/Developer + run: sudo xcode-select -switch "${XCODE_DEV_PATH}" - name: Prep id: prep run: | - echo "Create Build Logs Dir" - mkdir -p "${HOME}/build_logs" echo "Get Xcode version info" XCODE_VERSION="$(xcodebuild -version)" echo "${XCODE_VERSION}" @@ -58,7 +59,9 @@ jobs: if: success() && !(github.event_name == 'push' && contains(github.ref, 'refs/tags/')) # never cache dependencies for pushed tags uses: actions/cache@v2 with: - path: External/build/ + path: | + External/build + !External/build/Intermediates key: ${{ runner.os }}-${{ steps.prep.outputs.XCODE_VERSION }}-${{ matrix.platform }}-${{ hashFiles('fetchDependencies','ExternalRevisions/**','ExternalDependencies.xcodeproj/**','Scripts/**') }} - name: Fetch Dependencies (Use Built Cache) @@ -73,11 +76,11 @@ jobs: - name: Build MoltenVK run: | - set -o pipefail && xcodebuild build -project MoltenVKPackaging.xcodeproj -scheme "${{ matrix.scheme }}" | tee "${HOME}/build_logs/xcodebuild.log" | xcpretty -c + make ${{ matrix.platform }} - name: Output Build Logs on Failure if: failure() - run: cat "${HOME}/build_logs/xcodebuild.log" + run: cat "xcodebuild.log" - name: Build Demos if: success() && !(matrix.demos-scheme == '') From c81b666bae0cdd0552112346c0fef1084e85b91f Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 10:24:36 -0500 Subject: [PATCH 07/11] fetchDependencies: Support xcpretty (if available) --- fetchDependencies | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/fetchDependencies b/fetchDependencies index 4f559044..bba74569 100755 --- a/fetchDependencies +++ b/fetchDependencies @@ -395,6 +395,14 @@ echo echo ========== Started building dependency libraries at `date +"%r"` ========== echo Please be patient on first build +function execute_xcodebuild_command () { + if [ -n "${XCPRETTY}" ]; then + set -o pipefail && xcodebuild "$@" | tee -a "dependenciesbuild.log" | ${XCPRETTY} + else + xcodebuild "$@" + fi +} + # Build an Xcode scheme for an OS and platform # 1 - OS # 2 - Platform @@ -414,7 +422,7 @@ function build_impl() { echo Building external libraries for platform ${XC_PLTFM} and destination ${XC_DEST} - xcodebuild \ + execute_xcodebuild_command \ -project "${XC_PROJ}" \ -scheme "${XC_SCHEME}" \ -destination "generic/platform=${XC_DEST}" \ @@ -444,6 +452,19 @@ EXT_DEPS=ExternalDependencies XC_PROJ="${EXT_DEPS}.xcodeproj" XC_DD_PATH="${EXT_DIR}/build" +# Determine if xcpretty is present +XCPRETTY_PATH=$(command -v xcpretty 2> /dev/null || true) # ignore failures + +# If xcpretty is present, use it to format xcodebuild output +XCPRETTY="" +if [ -n "$XCPRETTY_PATH" ]; then + XCPRETTY="xcpretty -c" +fi +if [ "$XC_USE_BCKGND" != "" ]; then + # For now, avoid using xcpretty if parallel background tasks are being used + XCPRETTY="" +fi + # Structure build tasks by platform so they can be built in parallel per platform. # Content for each platform must be built in series to avoid if [ "$XC_USE_BCKGND" != "" ]; then From 7a92c39a77672ccdc808f5a7320cd78d9b189c52 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 10:35:54 -0500 Subject: [PATCH 08/11] GitHub Actions: Skip building Demos --- .github/workflows/CI.yml | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d15f454f..3ad2e78c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,21 +18,13 @@ jobs: strategy: matrix: include: - - name: "MoltenVK (macOS)" - platform: "macos" - demos-scheme: "Cube-macOS" - - name: "MoltenVK (macCatalyst)" - platform: "maccat" - demos-scheme: "" - - name: "MoltenVK (iOS)" - platform: "ios" - demos-scheme: "" - - name: "MoltenVK (tvOS)" - platform: "tvos" - demos-scheme: "" + - platform: "macos" + - platform: "maccat" + - platform: "ios" + - platform: "tvos" fail-fast: false - name: '${{ matrix.name }}' + name: 'MoltenVK (${{ matrix.platform }})' # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/specifications-for-github-hosted-runners#supported-runners-and-hardware-resources runs-on: macos-latest @@ -82,11 +74,6 @@ jobs: if: failure() run: cat "xcodebuild.log" - - name: Build Demos - if: success() && !(matrix.demos-scheme == '') - run: | - xcodebuild build -workspace Demos/Demos.xcworkspace -scheme "${{ matrix.demos-scheme }}" - - name: Tar Artifacts # See: https://github.com/actions/upload-artifact#maintaining-file-permissions-and-case-sensitive-files run: tar -cvf "${{ matrix.platform }}.tar" Package/Release/ From c676480e5fbca53eeaa8298f24ae620c2674f9b8 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 13:43:56 -0500 Subject: [PATCH 09/11] GitHub Actions: Output full dependency build logs (on failure) --- .github/workflows/CI.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3ad2e78c..bd8c2206 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -66,13 +66,20 @@ jobs: run: | ./fetchDependencies -v --no-parallel-build --${{ matrix.platform }} + - name: Output Dependency Build Logs on Failure + if: failure() + run: cat "dependenciesbuild.log" + - name: Build MoltenVK run: | make ${{ matrix.platform }} - - name: Output Build Logs on Failure + - name: Output MoltenVK Build Logs on Failure if: failure() - run: cat "xcodebuild.log" + run: | + if [ -f "xcodebuild.log" ]; then + cat "xcodebuild.log" + fi - name: Tar Artifacts # See: https://github.com/actions/upload-artifact#maintaining-file-permissions-and-case-sensitive-files From 41cfcdbac0043ca1c5a3b779ebd1b53ddebd5578 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 15:05:07 -0500 Subject: [PATCH 10/11] Remove .travis.yml --- .travis.yml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 81a3a5d2..00000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: objective-c - -# macOS and Xcode Version -os: osx -osx_image: xcode12.2 - -# Build with verbose logging to avoid Travis timing out. -script: - - ./fetchDependencies -v --no-parallel-build --macos - - xcodebuild build -project MoltenVKPackaging.xcodeproj -scheme "MoltenVK Package (macOS only)" - - xcodebuild build -workspace Demos/Demos.xcworkspace -scheme "Cube-macOS" - From 12981c063a654cc4806473f6f895eeb9d5976b92 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 9 Dec 2020 15:19:17 -0500 Subject: [PATCH 11/11] GitHub Actions: Remove explicit `--no-parallel-build` parameter --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index bd8c2206..c3fadd1d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -59,12 +59,12 @@ jobs: - name: Fetch Dependencies (Use Built Cache) if: steps.cache-dependencies.outputs.cache-hit == 'true' run: | - ./fetchDependencies -v --no-parallel-build --none + ./fetchDependencies -v --none - name: Fetch Dependencies if: steps.cache-dependencies.outputs.cache-hit != 'true' run: | - ./fetchDependencies -v --no-parallel-build --${{ matrix.platform }} + ./fetchDependencies -v --${{ matrix.platform }} - name: Output Dependency Build Logs on Failure if: failure()