Skip to content

compat-check

compat-check #3

Workflow file for this run

# Verifies pinned combinations of CLI version, Node.js major, runtime version
# and toolchain versions by building a freshly created app. The matrix comes
# from public feeds (npm, nodejs.org, xcodereleases.com, the Android SDK
# repository, Adoptium) minus every combination that already has a file under
# data/verified/. The first run is large; later runs only contain what new
# releases create. Results land in a PR that adds result files.
name: compat-check
on:
schedule:
- cron: "0 6 * * 1"
workflow_dispatch:
# Leave every field empty for a normal feed-driven run. Fill them in to
# verify one specific combination by hand.
inputs:
platform:
description: "feed-driven: normal run. ios / android: verify one combination from the fields below."
type: choice
options: ["feed-driven", "ios", "android"]
default: "feed-driven"
cli:
description: "nativescript CLI version, e.g. 9.1.1"
type: string
node:
description: "Node.js major, e.g. 24"
type: string
runtime:
description: "Runtime version, e.g. 9.1.0"
type: string
xcode:
description: "Xcode line for iOS, e.g. 26.3"
type: string
compileSdk:
description: "Android API level, e.g. 36"
type: string
jdk:
description: "JDK major for Android, e.g. 21"
type: string
force:
description: "Rebuild even if this combination is already recorded"
type: boolean
default: false
concurrency:
group: compat-check
cancel-in-progress: false
permissions:
contents: read
jobs:
matrix:
name: Build matrix
runs-on: ubuntu-latest
outputs:
ios: ${{ steps.matrix.outputs.ios }}
android: ${{ steps.matrix.outputs.android }}
has_ios: ${{ steps.matrix.outputs.has_ios }}
has_android: ${{ steps.matrix.outputs.has_android }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
# Results still waiting in an unmerged results PR count as recorded, so a
# re-run while that PR is open does not rebuild them.
- name: Include pending results
run: |
if git fetch origin ci/verified-results 2>/dev/null; then
git checkout origin/ci/verified-results -- data/verified
echo "included pending results from ci/verified-results"
fi
- id: matrix
env:
MANUAL_PLATFORM: ${{ inputs.platform }}
MANUAL_CLI: ${{ inputs.cli }}
MANUAL_NODE: ${{ inputs.node }}
MANUAL_RUNTIME: ${{ inputs.runtime }}
MANUAL_XCODE: ${{ inputs.xcode }}
MANUAL_COMPILE_SDK: ${{ inputs.compileSdk }}
MANUAL_JDK: ${{ inputs.jdk }}
MANUAL_FORCE: ${{ inputs.force }}
run: node scripts/build-matrix.mjs --github
ios:
name: iOS ${{ matrix.runtime }} · Xcode ${{ matrix.xcode }} · CLI ${{ matrix.cli }} · Node ${{ matrix.node }}
needs: matrix
if: needs.matrix.outputs.has_ios == 'true'
# Chosen per Xcode line by the matrix job from the runner images' readmes.
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.matrix.outputs.ios) }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Select Xcode ${{ matrix.xcode }}
run: |
app=$(ls -d /Applications/Xcode_${{ matrix.xcode }}*.app 2>/dev/null | sort -V | tail -1)
if [ -z "$app" ]; then
echo "::warning::Xcode ${{ matrix.xcode }} is not installed on ${{ matrix.runner }}"
exit 1
fi
sudo xcode-select -s "$app/Contents/Developer"
xcodebuild -version
- name: Build the compat app
id: build
env:
NS_SKIP_ENV_CHECK: "1"
run: |
npm install -g nativescript@${{ matrix.cli }}
ns create compat --tsc --disableAnalytics
cd compat
npm install @nativescript/ios@${{ matrix.runtime }} --save-dev
ns build ios --disableAnalytics
- name: Record result
# A pinned combination that failed is as final as one that passed: record it so it is never rebuilt.
if: always() && steps.build.outcome != 'skipped'
run: |
node scripts/report-verification.mjs --package @nativescript/ios --version ${{ matrix.runtime }} \
--toolchain xcode=${{ matrix.xcode }} --toolchain cocoapods="$(pod --version)" \
--with nativescript=${{ matrix.cli }} --with node=${{ matrix.node }} \
--resolved node="$(node --version | tr -d v)" --resolved xcode="$(xcodebuild -version | head -1 | cut -d' ' -f2)" \
--outcome ${{ steps.build.outcome }} \
--evidence "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
- uses: actions/upload-artifact@v4
if: always() && steps.build.outcome != 'skipped'
with:
name: result-ios-${{ matrix.runtime }}-xcode-${{ matrix.xcode }}-cli-${{ matrix.cli }}-node-${{ matrix.node }}
path: data/verified/
android:
name: Android ${{ matrix.runtime }} · SDK ${{ matrix.compileSdk }} · JDK ${{ matrix.jdk }} · CLI ${{ matrix.cli }} · Node ${{ matrix.node }}
needs: matrix
if: needs.matrix.outputs.has_android == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.matrix.outputs.android) }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{ matrix.jdk }}
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Install ${{ matrix.platform }} and build-tools ${{ matrix.buildTools }}
run: |
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
"platforms;${{ matrix.platform }}" "build-tools;${{ matrix.buildTools }}" >/dev/null
- name: Build the compat app
id: build
env:
NS_SKIP_ENV_CHECK: "1"
run: |
npm install -g nativescript@${{ matrix.cli }}
ns create compat --tsc --disableAnalytics
cd compat
npm install @nativescript/android@${{ matrix.runtime }} --save-dev
ns build android --compileSdk ${{ matrix.compileSdk }} --disableAnalytics
- name: Record result
if: always() && steps.build.outcome != 'skipped'
run: |
node scripts/report-verification.mjs --package @nativescript/android --version ${{ matrix.runtime }} \
--toolchain compileSdk=${{ matrix.compileSdk }} --toolchain buildTools=${{ matrix.buildTools }} --toolchain jdk=${{ matrix.jdk }} \
--with nativescript=${{ matrix.cli }} --with node=${{ matrix.node }} \
--resolved node="$(node --version | tr -d v)" --resolved jdk="$(java -version 2>&1 | head -1 | cut -d'"' -f2)" \
--outcome ${{ steps.build.outcome }} \
--evidence "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
- uses: actions/upload-artifact@v4
if: always() && steps.build.outcome != 'skipped'
with:
name: result-android-${{ matrix.runtime }}-sdk-${{ matrix.compileSdk }}-jdk-${{ matrix.jdk }}-cli-${{ matrix.cli }}-node-${{ matrix.node }}
path: data/verified/
collect:
name: Record results
needs: [matrix, ios, android]
# Runs even when some builds failed: every outcome is a recorded cell.
if: always() && needs.matrix.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
# Each artifact is a data/verified/ tree holding that job's result file,
# so dropping them all onto the checkout is the whole merge.
- uses: actions/download-artifact@v4
with:
pattern: result-*
path: data/verified
merge-multiple: true
- name: Commit results
run: |
git add data/verified
if git diff --cached --quiet; then
echo "no new results"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
count=$(git diff --cached --name-only | wc -l | tr -d ' ')
git commit -m "data: record $count compatibility results" \
-m "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
# Another run or a maintainer may have pushed meanwhile; results only add files, so a rebase never conflicts.
for attempt in 1 2 3; do
git push && exit 0
git pull --rebase
done
exit 1