compat-check #2
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' | |
| runs-on: macos-15 | |
| 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 this runner image" | |
| 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: Merge results | |
| needs: [matrix, ios, android] | |
| # Runs even when some builds failed: every success is a verified cell. | |
| if: always() && needs.matrix.result == 'success' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| # Base the results branch on the current default branch, not the commit | |
| # this run started from, so the PR can only ever add result files. | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # Each artifact is a data/verified/ tree holding only that job's new | |
| # files, 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 | |
| - id: merge | |
| run: | | |
| git add -N data/verified | |
| if git diff --quiet data/verified; then | |
| echo "no new results" | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| git diff --stat data/verified | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: peter-evans/create-pull-request@v7 | |
| if: steps.merge.outputs.changed == 'true' | |
| with: | |
| branch: ci/verified-results | |
| title: "data: new compatibility results" | |
| commit-message: "data: record compatibility results" | |
| body: | | |
| Successful builds from the compat-check run | |
| ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}. | |
| Merging redeploys the site with these cells marked as verified by CI. | |
| add-paths: data/verified | |
| delete-branch: true |