compat-check #3
This file contains hidden or 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
| # 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 |