Prepare for 12.11.0 #4727
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Pull request build and test | |
on: | |
push: | |
# The workflow will run only when both `branches` and `paths-ignore` are satisfied. | |
branches: | |
- main | |
paths-ignore: | |
- "**.md" | |
- "**.png" | |
- "packages/realm-web/**" | |
- "packages/realm-web-integration-tests/**" | |
- "packages/realm-react/**" | |
- "packages/realm-tools/**" | |
pull_request: | |
# Note that the workflow will still run if paths outside of `paths-ignore` have | |
# been modified in the PR, irrespective of an individual commit only modifying | |
# ignored paths. (See: https://github.com/actions/runner/issues/2324) | |
paths-ignore: | |
- "**.md" | |
- "**.png" | |
- "packages/realm-web/**" | |
- "packages/realm-web-integration-tests/**" | |
- "packages/realm-react/**" | |
- "packages/realm-tools/**" | |
workflow_dispatch: | |
env: | |
CMAKE_VERSION: 3.29.2 | |
NDK_VERSION: 25.1.8937393 | |
JAVA_VERSION: 17 | |
WIREIT_LOGGER: simple | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
generate-jsi: | |
name: Generate JSI binding source-code | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: npm | |
- name: Install dependencies | |
# Ignoring scripts to prevent a prebuild from getting fetched / built | |
run: npm ci --ignore-scripts | |
- name: Generate JSI | |
run: | | |
npm run bindgen:jsi --workspace realm | |
- name: Upload dist artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: jsi-binding-source | |
# Including README.md to pin paths to the root of the repository | |
path: | | |
README.md | |
packages/realm/binding/jsi/jsi_init.cpp | |
build-ts: | |
name: Build TypeScript files | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: npm | |
- name: Install dependencies | |
# Ignoring scripts to prevent a prebuilt from getting fetched / built | |
run: npm ci --ignore-scripts | |
- name: Bundle all packages | |
run: npm run bundle | |
- name: Upload dist artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ts-build | |
# Including README.md to pin paths to the root of the repository | |
path: | | |
README.md | |
packages/*/dist | |
packages/realm/binding/dist | |
packages/realm/binding/generated | |
prebuild-node: | |
name: Prebuild ${{ matrix.os }} ${{ matrix.arch }} (Node.js) | |
runs-on: ${{ matrix.runner }} | |
env: | |
REALM_DISABLE_ANALYTICS: 1 | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- os: linux | |
runner: ubuntu-latest | |
arch: x64 | |
- os: linux | |
runner: ubuntu-latest | |
arch: arm | |
- os: linux | |
runner: ubuntu-latest | |
arch: arm64 | |
- os: windows | |
runner: windows-latest | |
arch: x64 | |
- os: windows | |
runner: windows-2019 | |
arch: ia32 | |
- os: darwin | |
runner: macos-latest | |
arch: x64 | |
- os: darwin | |
runner: macos-latest | |
arch: arm64 | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20.11.1 | |
cache: npm | |
- name: Get NPM cache directory | |
id: npm-cache-dir | |
shell: bash | |
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT | |
- name: Restore NPM cache | |
id: npm-cache | |
uses: actions/cache@v4 | |
with: | |
path: ${{ steps.npm-cache-dir.outputs.dir }} | |
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
- name: Setup Wireit cache | |
uses: google/wireit@setup-github-actions-caching/v1 | |
- name: MSVC Setup | |
if: ${{ runner.os == 'Windows' }} | |
uses: ilammy/msvc-dev-cmd@v1 | |
- name: Setup CMake | |
uses: jwlawson/actions-setup-cmake@v2 | |
with: | |
cmake-version: ${{ env.CMAKE_VERSION }} | |
# ninja-build is used by default if available and results in faster build times | |
# On linux, electron requires a connected display. We fake this by giving it a headless environment using xvfb | |
# Relevant issue: https://github.com/juliangruber/browser-run/issues/147 | |
- name: Linux Environment setup | |
if: ${{ matrix.runner == 'ubuntu-latest' }} | |
run: sudo apt-get install ccache ninja-build | |
# The ccache installed by github doesn't want to be moved around. Let the ccache action download a new one. | |
- name: Remove pre-installed ccache | |
if: ${{ runner.os == 'Windows' }} | |
shell: bash | |
# There are two; remove both | |
run: | | |
rm -fv $(which ccache) | |
rm -fv $(which ccache) | |
- name: ccache | |
uses: hendrikmuhs/ccache-action@v1 | |
with: | |
key: ${{ runner.os }}-${{ matrix.os }}-${{ matrix.arch }} | |
max-size: '2.0G' | |
- name: Prepend ccache executables to the PATH | |
if: ${{ runner.os != 'Windows' }} | |
run: | | |
echo "/usr/lib/ccache:/usr/local/opt/ccache/libexec" >> $GITHUB_PATH | |
# in CI file timestamps change with every run so instead rely on file content hashing | |
# https://reactnative.dev/docs/build-speed#using-this-approach-on-a-ci | |
- name: Configure ccache | |
run: ccache --set-config="compiler_check=content" | |
- name: Install dependencies | |
# Ignoring scripts to prevent a prebuilt from getting fetched / built | |
run: npm ci --ignore-scripts | |
- name: Insert ccache executables | |
if: ${{ runner.os == 'Windows' }} | |
shell: bash | |
run: | | |
cl_exe=$(which cl.exe) | |
cl_dir=$(dirname "$cl_exe") | |
# For 32-bit it uses a different compiler than the one in the path | |
if [ ${{ matrix.arch }} = ia32 ]; then | |
cl_dir=$(dirname "$cl_dir")/x86 | |
cl_exe="$cl_dir/cl.exe" | |
fi | |
cl_dir_windows="C:${cl_dir#/c}" | |
mv -v "$cl_exe" "$cl_dir"/cl-real.exe | |
cp -v "$cl_dir"/cl.exe.config "$cl_dir"/cl-real.exe.config | |
ccache_exe=$(which ccache.exe) | |
cp -v "$ccache_exe" "$cl_dir"/cl.exe | |
ls -l "$cl_dir" | |
echo "CCACHE_COMPILER=$cl_dir_windows/cl-real.exe" >> $GITHUB_ENV | |
echo 'CCACHE_COMPILERTYPE=msvc' >> $GITHUB_ENV | |
echo 'CCACHE_STATSLOG=C:\Users\runneradmin\ccache\statslog.txt' >> $GITHUB_ENV | |
#echo 'CCACHE_LOGFILE=C:\Users\runneradmin\ccache\logfile.txt' >> $GITHUB_ENV | |
# This tells msbuild to compile only one file at a time; ccache needs that. | |
echo 'UseMultiToolTask=true' >> $GITHUB_ENV | |
echo 'VCPKG_KEEP_ENV_VARS=CCACHE_COMPILER;CCACHE_STATSLOG;CCACHE_LOGFILE;CCACHE_COMPILERTYPE;UseMultiToolTask' >> $GITHUB_ENV | |
- name: Build native module | |
run: npm run prebuild-node --workspace realm | |
env: | |
PREBUILD_ARCH: ${{ matrix.arch }} | |
- name: Upload prebuild artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: node-${{ matrix.os }}-${{ matrix.arch }}-prebuild | |
# Including README.md to pin paths to the root of the repository | |
path: | | |
README.md | |
packages/realm/prebuilds/realm-*-napi-*.tar.gz | |
prebuild-apple-archives: | |
name: Prebuild ${{ matrix.platform }} (Apple React Native) | |
runs-on: macos-latest-large | |
strategy: | |
fail-fast: false | |
matrix: | |
platform: | |
- iphonesimulator | |
- iphoneos | |
- macosx | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: npm | |
- name: Setup CMake | |
uses: jwlawson/actions-setup-cmake@v2 | |
with: | |
cmake-version: ${{ env.CMAKE_VERSION }} | |
- name: Setup Ccache | |
uses: hendrikmuhs/ccache-action@v1 | |
with: | |
key: ${{ runner.os }}-${{ matrix.platform }} | |
max-size: '2.0G' | |
# On CI, file timestamps change with every run so instead rely on file content hashing | |
# https://reactnative.dev/docs/build-speed#using-this-approach-on-a-ci | |
- name: Configure ccache | |
run: ccache --set-config="compiler_check=content" | |
- name: Install dependencies | |
run: npm ci | |
- name: Build archive | |
run: npm run prebuild-apple --workspace realm -- --platform ${{ matrix.platform }} --skip-creating-xcframework | |
- name: Upload archive | |
uses: actions/upload-artifact@v4 | |
with: | |
name: apple-${{ matrix.platform }}-archive | |
# Including README.md to pin paths to the root of the repository | |
path: | | |
README.md | |
packages/realm/bindgen/vendor/realm-core/build-xcode/include/ | |
packages/realm/bindgen/vendor/realm-core/build-xcode/${{ matrix.platform }}.xcarchive/Products/usr/local/lib/librealm-combined.a | |
if-no-files-found: error | |
prebuild-apple: | |
name: Combine Xcframework (Apple React Native) | |
runs-on: macos-latest-large | |
needs: [prebuild-apple-archives] | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: npm | |
- name: Install dependencies | |
run: npm ci | |
- name: Download archives | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: apple-*-archive | |
merge-multiple: true | |
- name: Create Xcframework | |
run: npm run prebuild-apple --workspace realm -- --platform none --skip-collecting-headers | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: apple-prebuild | |
# Including README.md to pin paths to the root of the repository | |
path: | | |
README.md | |
packages/realm/prebuilds/apple/realm-core.xcframework/ | |
if-no-files-found: error | |
prebuild-android: | |
name: Prebuild ${{ matrix.architecture }} (Android React Native) | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
architecture: | |
- arm64-v8a | |
- armeabi-v7a | |
- x86 | |
- x86_64 | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: npm | |
- name: Setup CMake | |
uses: jwlawson/actions-setup-cmake@v2 | |
with: | |
cmake-version: ${{ env.CMAKE_VERSION }} | |
- name: Install ninja | |
run: sudo apt-get install ninja-build | |
- name: Setup Ccache | |
uses: hendrikmuhs/ccache-action@v1 | |
with: | |
key: ${{ runner.os }}-android-${{ matrix.architecture }} | |
max-size: '2.0G' | |
# On CI, file timestamps change with every run so instead rely on file content hashing | |
# https://reactnative.dev/docs/build-speed#using-this-approach-on-a-ci | |
- name: Configure ccache | |
run: ccache --set-config="compiler_check=content" | |
- name: Setup Java | |
uses: actions/setup-java@v3 | |
with: | |
distribution: 'zulu' # See 'Supported distributions' for available options | |
java-version: '${{ env.JAVA_VERSION }}' | |
- name: Setup Android SDK | |
uses: android-actions/setup-android@v2 | |
- name: Install NDK | |
run: sdkmanager --install "ndk;${{ env.NDK_VERSION }}" | |
- name: Install dependencies | |
run: npm ci | |
- name: Build archive | |
run: npm run prebuild-android --workspace realm -- --architecture ${{ matrix.architecture }} --configuration Release | |
- name: Upload archive | |
uses: actions/upload-artifact@v4 | |
with: | |
name: android-${{ matrix.architecture }}-prebuild | |
# Including README.md to pin paths to the root of the repository | |
path: | | |
README.md | |
packages/realm/prebuilds/android/${{ matrix.architecture }}/ | |
if-no-files-found: error | |
merge-prebuilds: | |
runs-on: ubuntu-latest | |
needs: [prebuild-node, prebuild-apple, prebuild-android] | |
steps: | |
- name: Merge prebuild artifacts into a single artifact | |
uses: actions/upload-artifact/merge@v4 | |
with: | |
name: prebuilds | |
pattern: '*-prebuild' | |
integration-tests: | |
name: Test ${{ matrix.variant.environment }} on ${{ matrix.variant.os }} (${{matrix.variant.target}}) | |
needs: [generate-jsi, build-ts, prebuild-node, prebuild-apple, prebuild-android] | |
if: ${{ success() || failure() }} | |
env: | |
REALM_DISABLE_ANALYTICS: 1 | |
MOCHA_REMOTE_TIMEOUT: 60000 | |
LONG_TIMEOUT: 300000 # 5 minutes | |
MOCHA_REMOTE_REPORTER: mocha-github-actions-reporter | |
MOCHA_REMOTE_EXIT_ON_ERROR: true | |
SPAWN_LOGCAT: true | |
BAAS_BRANCH: master | |
# Pin the Xcode version | |
DEVELOPER_DIR: /Applications/Xcode_14.3.1.app | |
IOS_DEVICE_NAME: iPhone 14 | |
runs-on: ${{ matrix.variant.runner }} | |
strategy: | |
fail-fast: false | |
matrix: | |
variant: | |
- { os: linux, target: "test:ci", runner: ubuntu-latest, environment: node } | |
- { os: linux, target: "test:ci:main", runner: ubuntu-latest, environment: electron } | |
- { os: linux, target: "test:ci:renderer", runner: ubuntu-latest, environment: electron } | |
# - { os: windows, target: "test:ci", runner: windows-latest, environment: node} | |
# - { os: windows, target: "test:ci:main", runner: windows-latest, environment: electron } | |
# - { os: windows, target: "test:ci:renderer", runner: windows-latest, environment: electron } | |
- { os: darwin, target: "test:ci:main", runner: macos-latest, environment: electron } | |
- { os: darwin, target: "test:ci:renderer", runner: macos-latest, environment: electron } | |
- { os: darwin, target: "test:ci", runner: macos-latest, environment: node } | |
- { os: android, target: "test:ci:android", runner: macos-latest-large, environment: react-native-test-app, arch: "armeabi-v7a" } | |
- { os: ios, target: "test:ci:ios", runner: macos-latest-xlarge, environment: react-native-test-app, arch: "ios" } | |
#- { os: ios, target: "test:ci:catalyst", runner: macos-latest, environment: react-native-test-app, arch: "catalyst" } | |
timeout-minutes: 60 | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: "recursive" | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: npm | |
- name: Get NPM cache directory | |
id: npm-cache-dir | |
shell: bash | |
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT | |
- name: Restore NPM cache | |
id: npm-cache | |
uses: actions/cache@v4 | |
with: | |
path: ${{ steps.npm-cache-dir.outputs.dir }} | |
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
- name: Restore React Native cache | |
if: ${{ matrix.variant.environment == 'react-native-test-app' }} | |
uses: actions/cache@v4 | |
with: | |
path: '**/Pods' | |
key: ${{ runner.os }}-${{matrix.variant.environment}}-${{ hashFiles('**/Podfile.lock', './src/**', './vendor/**') }} | |
restore-keys: | | |
${{ runner.os }}-${{matrix.variant.environment}}- | |
- name: Setup Java | |
if: ${{ matrix.variant.os == 'android' }} | |
uses: actions/setup-java@v3 | |
with: | |
distribution: 'zulu' # See 'Supported distributions' for available options | |
java-version: '${{ env.JAVA_VERSION }}' | |
- name: Setup Android SDK | |
if: ${{ matrix.variant.os == 'android' }} | |
uses: android-actions/setup-android@v2 | |
- name: Install NDK | |
if: ${{ matrix.variant.os == 'android' }} | |
run: sdkmanager --install "ndk;${{ env.NDK_VERSION }}" | |
- name: MSVC Setup | |
if: ${{ runner.os == 'Windows' }} | |
uses: ilammy/msvc-dev-cmd@v1 | |
# we use a different version for Android, and it is specified below | |
- name: Setup CMake | |
if: ${{ matrix.variant.os != 'android' }} | |
uses: jwlawson/actions-setup-cmake@v2 | |
with: | |
cmake-version: ${{ env.CMAKE_VERSION }} | |
- name: ccache | |
uses: hendrikmuhs/ccache-action@v1 | |
if: ${{ matrix.variant.environment == 'react-native-test-app' }} | |
with: | |
key: ${{ runner.os }}-${{ matrix.variant.os }}-${{ matrix.variant.arch }} | |
max-size: '2.0G' | |
# in CI file timestamps change with every run so instead rely on file content hashing | |
# https://reactnative.dev/docs/build-speed#using-this-approach-on-a-ci | |
- name: Configure ccache | |
if: ${{ matrix.variant.environment == 'react-native-test-app' }} | |
run: ccache --set-config="compiler_check=content" | |
# Hermes doesn't work with Cocoapods 1.15.0 | |
# https://forums.developer.apple.com/forums/thread/745518 | |
- name: Install older Cocoapods version | |
if: ${{ matrix.variant.os == 'ios' }} | |
uses: maxim-lobanov/setup-cocoapods@v1 | |
with: | |
version: 1.14.3 | |
- name: Install IOS tools | |
if: ${{ matrix.variant.os == 'ios' }} | |
run: | | |
npm install -g ios-deploy | |
- name: Set xvfb wrapper for Linux / electron tests | |
if: ${{ matrix.variant.os == 'linux' && matrix.variant.environment == 'electron' }} | |
run: | | |
sudo apt-get install xvfb | |
echo "wrapper=xvfb-run" >> $GITHUB_ENV | |
- name: Download JSI | |
uses: actions/download-artifact@v4 | |
if: ${{ matrix.variant.environment == 'react-native-test-app' }} | |
with: | |
name: jsi-binding-source | |
- name: Download TypeScript build | |
uses: actions/download-artifact@v4 | |
with: | |
name: ts-build | |
- name: Download Node prebuilds | |
if: ${{ matrix.variant.environment == 'node' || matrix.variant.environment == 'electron' }} | |
uses: actions/download-artifact@v4 | |
with: | |
# TODO: This pattern could be narrowed further with the architecture | |
pattern: node-${{ matrix.variant.os }}-*-prebuild | |
merge-multiple: true | |
- name: Download Apple prebuild | |
if: ${{ matrix.variant.os == 'ios' }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: apple-prebuild | |
- name: Download Android prebuild | |
if: ${{ matrix.variant.os == 'android' }} | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: android-*-prebuild | |
merge-multiple: true | |
- name: Install dependencies | |
run: npm ci | |
env: | |
# Ensure we install the prebuild built in the previous job | |
npm_config_realm_local_prebuilds: ${{github.workspace}}/packages/realm/prebuilds | |
# The following makes subsequent "open -a Simulator" calls work | |
- name: Invoke the simulator | |
if: ${{ matrix.variant.os == 'ios' }} | |
run: open -a ${{ env.DEVELOPER_DIR }}/Contents/Developer/Applications/Simulator.app | |
- name: Boot the simulator | |
if: ${{ matrix.variant.os == 'ios' }} | |
run: xcrun simctl boot '${{ env.IOS_DEVICE_NAME }}' | |
- name: Start BaaS test server | |
id: baas | |
uses: ./.github/actions/baas-test-server | |
with: | |
branch: ${{ env.BAAS_BRANCH }} | |
env: | |
BAASAAS_KEY: ${{ secrets.BAASAAS_KEY }} | |
- name: Create Mocha Remote Context | |
id: mocha-env | |
run: echo "context=syncLogLevel=warn,longTimeoutMs=${{ env.LONG_TIMEOUT }},baseUrl=${{ steps.baas.outputs.baas-url }}" >> $GITHUB_OUTPUT | |
- name: Run ${{matrix.variant.target}} (${{ matrix.variant.os}} / ${{ matrix.variant.environment }}) | |
if: ${{ matrix.variant.os != 'android' && matrix.variant.os != 'ios' }} | |
env: | |
MOCHA_REMOTE_CONTEXT: ${{ steps.mocha-env.outputs.context }} | |
# The non react native environments should not take so long | |
timeout-minutes: 60 | |
run: ${{ env.wrapper }} npm run ${{ matrix.variant.target}} --prefix integration-tests/environments/${{ matrix.variant.environment }} | |
- name: Run ${{matrix.variant.target}} (${{ matrix.variant.os}} / ${{ matrix.variant.environment }}) | |
if: ${{ matrix.variant.os == 'ios' }} | |
env: | |
WIREIT_LOGGER: simple | |
USE_CCACHE: 1 | |
USE_BRIDGELESS: 0 # Disabling for now | |
RCT_NEW_ARCH_ENABLED: 0 # Disabled for now | |
MOCHA_REMOTE_CONTEXT: ${{ steps.mocha-env.outputs.context }} | |
timeout-minutes: 75 | |
run: npm run ${{ matrix.variant.target}} --prefix integration-tests/environments/${{ matrix.variant.environment }} | |
- name: Setup Java Gradle cache for android test app | |
if: ${{ matrix.variant.os == 'android' }} | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.gradle/caches | |
~/.gradle/wrapper | |
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
restore-keys: | | |
${{ runner.os }}-gradle- | |
- name: Setup Android Emulator cache | |
if: ${{ matrix.variant.os == 'android' }} | |
uses: actions/cache@v4 | |
id: avd-cache | |
with: | |
path: | | |
~/.android/avd/* | |
~/.android/adb* | |
key: avd-29 | |
- name: Run ${{matrix.variant.target}} (${{ matrix.variant.os}} / ${{ matrix.variant.environment }}) | |
if: ${{ matrix.variant.os == 'android' }} | |
env: | |
MOCHA_REMOTE_CONTEXT: ${{ steps.mocha-env.outputs.context }} | |
# TODO: Consider passing ORG_GRADLE_PROJECT_reactNativeArchitectures=x86 to limit increase build speed | |
timeout-minutes: 75 | |
uses: reactivecircus/android-emulator-runner@v2 | |
with: | |
api-level: 29 | |
force-avd-creation: false | |
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none | |
disable-animations: true | |
arch: x86 | |
ndk: ${{ env.NDK_VERSION }} | |
cmake: 3.22.1 | |
script: npm run ${{ matrix.variant.target}} --prefix integration-tests/environments/${{ matrix.variant.environment }} |