99 NPM_TAG : " next"
1010 XCODE_VERSION : " ^15.0"
1111
12+ # The runtime xcframeworks are no longer shipped inside the npm packages. Each
13+ # build publishes them as GitHub Release assets and points the SwiftPM manifest
14+ # (github.com/NativeScript/ios-spm) at them via binaryTarget(url:checksum:). The
15+ # slim npm package only carries the Xcode project template + metadata generator.
16+ #
17+ # Flow: setup → build (ios, visionos) → test → github-release (assets) →
18+ # spm-update (stamp + tag ios-spm) → publish (npm) → verify-spm
1219jobs :
20+ setup :
21+ name : Resolve version
22+ runs-on : ubuntu-latest
23+ outputs :
24+ npm_version : ${{ steps.out.outputs.NPM_VERSION }}
25+ npm_tag : ${{ steps.out.outputs.NPM_TAG }}
26+ steps :
27+ - name : Harden the runner (Audit all outbound calls)
28+ uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
29+ with :
30+ egress-policy : audit
31+ - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
32+ with :
33+ fetch-depth : 0
34+ persist-credentials : false
35+ - uses : actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
36+ with :
37+ node-version : 22
38+ - name : Install deps for version scripts
39+ run : npm install --no-audit --no-fund
40+ - name : Compute version and tag
41+ id : out
42+ run : |
43+ NPM_VERSION=$(node -e "console.log(require('./package.json').version);")
44+ if [ "${GITHUB_REF#refs/tags/}" = "$GITHUB_REF" ]; then
45+ # not a tag build -> dev/prerelease version
46+ NPM_VERSION=$(node ./scripts/get-next-version.js)
47+ fi
48+ NPM_TAG=$(NPM_VERSION=$NPM_VERSION node ./scripts/get-npm-tag.js)
49+ echo "NPM_VERSION=$NPM_VERSION" >> $GITHUB_OUTPUT
50+ echo "NPM_TAG=$NPM_TAG" >> $GITHUB_OUTPUT
51+ echo "Resolved $NPM_VERSION (tag: $NPM_TAG)"
52+
1353 build :
14- name : Build
54+ name : Build ${{ matrix.target }}
1555 runs-on : macos-14
16- outputs :
17- npm_version : ${{ steps.npm_version_output.outputs.NPM_VERSION }}
18- npm_tag : ${{ steps.npm_version_output.outputs.NPM_TAG }}
56+ needs : setup
57+ strategy :
58+ fail-fast : false
59+ matrix :
60+ target : [ios, visionos]
61+ env :
62+ NPM_VERSION : ${{ needs.setup.outputs.npm_version }}
1963 steps :
2064 - name : Harden the runner (Audit all outbound calls)
2165 uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
@@ -55,34 +99,26 @@ jobs:
5599 sudo mkdir -p /usr/local/bin
56100 sudo ln -sf "$(command -v cmake)" /usr/local/bin/cmake
57101 fi
58- - name : Get Current Version
59- run : |
60- NPM_VERSION=$(node -e "console.log(require('./package.json').version);")
61- echo NPM_VERSION=$NPM_VERSION >> $GITHUB_ENV
62- - name : Bump version for dev release
63- if : ${{ !contains(github.ref, 'refs/tags/') }}
64- run : |
65- NPM_VERSION=$(node ./scripts/get-next-version.js)
66- echo NPM_VERSION=$NPM_VERSION >> $GITHUB_ENV
67- npm version $NPM_VERSION --no-git-tag-version
68- - name : Output NPM Version and tag
69- id : npm_version_output
70- run : |
71- NPM_TAG=$(node ./scripts/get-npm-tag.js)
72- echo NPM_VERSION=$NPM_VERSION >> $GITHUB_OUTPUT
73- echo NPM_TAG=$NPM_TAG >> $GITHUB_OUTPUT
74- - name : Build
75- run : npm run build-ios
102+ - name : Set package version
103+ run : npm version $NPM_VERSION --no-git-tag-version --allow-same-version
104+ - name : Build (${{ matrix.target }})
105+ run : npm run build-${{ matrix.target }}
76106 - name : Upload npm package artifact
77107 uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
78108 with :
79- name : npm-package
80- path : dist/nativescript-ios-${{steps.npm_version_output.outputs.NPM_VERSION}}.tgz
109+ name : npm-package-${{ matrix.target }}
110+ path : dist/nativescript-*-${{ env.NPM_VERSION }}.tgz
111+ - name : Upload SwiftPM artifacts (xcframework zips + checksums)
112+ uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
113+ with :
114+ name : spm-artifacts-${{ matrix.target }}
115+ path : dist/artifacts/*
81116 - name : Upload dSYMs artifact
82117 uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
83118 with :
84- name : NativeScript- dSYMs
119+ name : dSYMs-${{ matrix.target }}
85120 path : dist/dSYMs
121+
86122 test :
87123 name : Test
88124 runs-on : macos-14
@@ -153,18 +189,144 @@ jobs:
153189 with :
154190 name : test-results
155191 path : ${{env.TEST_FOLDER}}/test_results.xcresult
192+
193+ # Publish the xcframework zips + dSYMs as a GitHub Release asset for EVERY
194+ # version (prerelease unless 'latest'), because the SwiftPM binaryTarget url
195+ # must resolve for `next`/`pr` consumers too — not only tagged releases.
196+ github-release :
197+ name : GitHub Release (SPM assets)
198+ runs-on : ubuntu-latest
199+ permissions :
200+ contents : write
201+ needs :
202+ - setup
203+ - build
204+ - test
205+ env :
206+ NPM_VERSION : ${{ needs.setup.outputs.npm_version }}
207+ NPM_TAG : ${{ needs.setup.outputs.npm_tag }}
208+ steps :
209+ - name : Harden the runner (Audit all outbound calls)
210+ uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
211+ with :
212+ egress-policy : audit
213+ - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
214+ with :
215+ fetch-depth : 0
216+ persist-credentials : false
217+ - uses : actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
218+ with :
219+ node-version : 22
220+ - name : Setup
221+ run : npm install --no-audit --no-fund
222+ - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
223+ with :
224+ pattern : spm-artifacts-*
225+ path : spm-artifacts
226+ merge-multiple : true
227+ - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
228+ with :
229+ pattern : dSYMs-*
230+ path : dist/dSYMs
231+ merge-multiple : true
232+ - name : Zip dSYMs
233+ working-directory : dist/dSYMs
234+ run : find . -maxdepth 1 -name '*.dSYM' -print | xargs -I@ zip -r @.zip @ || true
235+ - name : Partial Changelog
236+ run : npx conventional-changelog -p angular -r2 > body.md
237+ - name : Create / update release with SPM artifacts
238+ uses : ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0
239+ with :
240+ tag : " v${{ env.NPM_VERSION }}"
241+ name : " v${{ env.NPM_VERSION }}"
242+ commit : ${{ github.sha }}
243+ artifacts : " spm-artifacts/*.xcframework.zip,dist/dSYMs/*.zip"
244+ bodyFile : " body.md"
245+ prerelease : ${{ needs.setup.outputs.npm_tag != 'latest' }}
246+ allowUpdates : true
247+
248+ # Stamp + tag github.com/NativeScript/ios-spm to point at this release's assets.
249+ # Requires a cross-repo token (GITHUB_TOKEN cannot write to ios-spm). Enable by
250+ # setting repo variable ENABLE_SPM_UPDATE=true and secret IOS_SPM_TOKEN.
251+ spm-update :
252+ name : Update ios-spm manifest
253+ runs-on : ubuntu-latest
254+ if : ${{ vars.ENABLE_SPM_UPDATE == 'true' }}
255+ needs :
256+ - setup
257+ - build
258+ - test
259+ - github-release
260+ env :
261+ NPM_VERSION : ${{ needs.setup.outputs.npm_version }}
262+ NPM_TAG : ${{ needs.setup.outputs.npm_tag }}
263+ steps :
264+ - name : Harden the runner (Audit all outbound calls)
265+ uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
266+ with :
267+ egress-policy : audit
268+ - name : Checkout ios (for stamping script)
269+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
270+ with :
271+ path : ios
272+ persist-credentials : false
273+ - name : Checkout ios-spm
274+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
275+ with :
276+ repository : NativeScript/ios-spm
277+ token : ${{ secrets.IOS_SPM_TOKEN }}
278+ path : ios-spm
279+ - uses : actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
280+ with :
281+ node-version : 22
282+ - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
283+ with :
284+ pattern : spm-artifacts-*
285+ path : spm-artifacts
286+ merge-multiple : true
287+ - name : Stamp Package.swift
288+ run : |
289+ STRICT=""
290+ if [ "$NPM_TAG" = "latest" ]; then STRICT="--strict"; fi
291+ CHECKSUM_ARGS=""
292+ for f in spm-artifacts/checksums-*.env; do
293+ [ -f "$f" ] && CHECKSUM_ARGS="$CHECKSUM_ARGS --checksums $f"
294+ done
295+ echo "Using checksum files:$CHECKSUM_ARGS"
296+ if [ -z "$CHECKSUM_ARGS" ]; then echo "No checksum files found" >&2; exit 1; fi
297+ node ios/scripts/stamp-spm-release.mjs \
298+ --package ios-spm/Package.swift \
299+ --version "$NPM_VERSION" \
300+ $CHECKSUM_ARGS $STRICT
301+ - name : Commit and tag ios-spm
302+ working-directory : ios-spm
303+ run : |
304+ git config user.name "NativeScript Bot"
305+ git config user.email "oss@nativescript.org"
306+ git add Package.swift
307+ git commit -m "release: $NPM_VERSION" || echo "no changes to commit"
308+ git tag -f "$NPM_VERSION"
309+ git push origin HEAD:main
310+ git push -f origin "refs/tags/$NPM_VERSION"
311+
156312 publish :
313+ name : Publish ${{ matrix.target }}
157314 runs-on : ubuntu-latest
158315 environment : npm-publish
159316 needs :
317+ - setup
160318 - build
161319 - test
162320 permissions :
163321 contents : read
164322 id-token : write
323+ strategy :
324+ fail-fast : false
325+ matrix :
326+ target : [ios, visionos]
165327 env :
166- NPM_VERSION : ${{needs.build .outputs.npm_version}}
167- NPM_TAG : ${{needs.build .outputs.npm_tag}}
328+ NPM_VERSION : ${{ needs.setup .outputs.npm_version }}
329+ NPM_TAG : ${{ needs.setup .outputs.npm_tag }}
168330 steps :
169331 - name : Harden the runner (Audit all outbound calls)
170332 uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
@@ -176,73 +338,77 @@ jobs:
176338 registry-url : " https://registry.npmjs.org"
177339 - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
178340 with :
179- name : npm-package
341+ name : npm-package-${{ matrix.target }}
180342 path : dist
181343 - name : Update npm (required for OIDC trusted publishing)
182344 run : |
183345 corepack enable npm
184346 corepack install -g npm@11.5.1
185347 test "$(npm --version)" = "11.5.1"
186348 test "$(npx --version)" = "11.5.1"
349+ - name : Resolve package name
350+ run : |
351+ if [ "${{ matrix.target }}" = "ios" ]; then echo "PKG=ios" >> $GITHUB_ENV; else echo "PKG=visionos" >> $GITHUB_ENV; fi
187352 - name : Publish package (OIDC trusted publishing)
188353 if : ${{ vars.USE_NPM_TOKEN != 'true' }}
189354 run : |
190- echo "Publishing @nativescript/ios @$NPM_VERSION to NPM with tag $NPM_TAG via OIDC trusted publishing..."
355+ echo "Publishing @nativescript/$PKG @$NPM_VERSION to NPM with tag $NPM_TAG via OIDC trusted publishing..."
191356 unset NODE_AUTH_TOKEN
192357 if [ -n "${NPM_CONFIG_USERCONFIG:-}" ]; then
193358 rm -f "$NPM_CONFIG_USERCONFIG"
194359 fi
195- npm publish ./dist/nativescript-ios -${{env. NPM_VERSION} }.tgz --tag $NPM_TAG --access public --provenance
360+ npm publish ./dist/nativescript-${PKG} -${NPM_VERSION}.tgz --tag $NPM_TAG --access public --provenance
196361 env :
197362 NODE_AUTH_TOKEN : " "
198-
199363 - name : Publish package (granular token)
200364 if : ${{ vars.USE_NPM_TOKEN == 'true' }}
201365 run : |
202- echo "Publishing @nativescript/ios @$NPM_VERSION to NPM with tag $NPM_TAG via granular token..."
203- npm publish ./dist/nativescript-ios -${{env. NPM_VERSION} }.tgz --tag $NPM_TAG --access public --provenance
366+ echo "Publishing @nativescript/$PKG @$NPM_VERSION to NPM with tag $NPM_TAG via granular token..."
367+ npm publish ./dist/nativescript-${PKG} -${NPM_VERSION}.tgz --tag $NPM_TAG --access public --provenance
204368 env :
205369 NODE_AUTH_TOKEN : ${{ secrets.NPM_PUBLISH_TOKEN }}
206- github-release :
207- runs-on : ubuntu-latest
208- # only runs on tagged commits
209- if : ${{ contains(github.ref, 'refs/tags/') }}
210- permissions :
211- contents : write
370+
371+ # Post-publish smoke test: resolve ios-spm at the released tag and verify the
372+ # iOS binary artifact downloads + checksum-validates against the real Release.
373+ verify-spm :
374+ name : Verify SPM resolution
375+ runs-on : macos-14
376+ if : ${{ vars.ENABLE_SPM_UPDATE == 'true' }}
212377 needs :
213- - build
214- - test
378+ - setup
379+ - spm-update
215380 env :
216- NPM_VERSION : ${{needs.build .outputs.npm_version}}
381+ NPM_VERSION : ${{ needs.setup .outputs.npm_version }}
217382 steps :
218383 - name : Harden the runner (Audit all outbound calls)
219384 uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
220385 with :
221386 egress-policy : audit
222- - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
223- with :
224- fetch-depth : 0
225387 - uses : actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
226388 with :
227389 node-version : 22
228- - name : Setup
229- run : npm install
230- - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
231- with :
232- name : npm-package
233- path : dist
234- - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
235- with :
236- name : NativeScript-dSYMs
237- path : dist/dSYMs
238- - name : Zip dSYMs
239- working-directory : dist/dSYMs
240- run : find . -maxdepth 1 -name '*.dSYM' -print | xargs -I@ zip -r @.zip @
241- - name : Partial Changelog
242- run : npx conventional-changelog -p angular -r2 > body.md
243- - uses : ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0
244- with :
245- artifacts : " dist/nativescript-ios-*.tgz,dist/dSYMs/*.zip"
246- bodyFile : " body.md"
247- prerelease : ${{needs.build.outputs.npm_tag != 'latest'}}
248- allowUpdates : true
390+ - name : Generate a probe package that depends on ios-spm
391+ run : |
392+ node -e '
393+ const fs = require("fs");
394+ const v = process.env.NPM_VERSION;
395+ fs.mkdirSync("spmverify/Sources/Probe", { recursive: true });
396+ fs.writeFileSync("spmverify/Package.swift",
397+ "// swift-tools-version: 5.10\n" +
398+ "import PackageDescription\n" +
399+ "let package = Package(\n" +
400+ " name: \"Probe\",\n" +
401+ " platforms: [.iOS(.v13)],\n" +
402+ " dependencies: [.package(url: \"https://github.com/NativeScript/ios-spm.git\", exact: \"" + v + "\")],\n" +
403+ " targets: [.target(name: \"Probe\", dependencies: [.product(name: \"NativeScript\", package: \"ios-spm\")])]\n" +
404+ ")\n");
405+ fs.writeFileSync("spmverify/Sources/Probe/Probe.swift", "// probe\n");
406+ '
407+ - name : Resolve (downloads the xcframework zip and verifies its checksum)
408+ working-directory : spmverify
409+ run : |
410+ # Resolution fetches the binary artifacts for the NativeScript product
411+ # and verifies each checksum against the stamped manifest; a mismatch or
412+ # a missing release asset fails the release here.
413+ swift package resolve
414+ echo "ios-spm@$NPM_VERSION resolved and checksum-verified."
0 commit comments