A GitHub Action that builds and caches prebuilt SwiftSyntax for nightly and non-Xcode Swift toolchains, eliminating the 3–5 minute rebuild penalty on every CI run.
Apple only publishes prebuilt SwiftSyntax binaries for specific Xcode compiler tags. If you use a nightly toolchain (swift-DEVELOPMENT-SNAPSHOT-*) or open-source release (swift-6.1-RELEASE), SwiftPM falls back to building swift-syntax from source every time.
This action:
- Detects your Swift compiler tag and host platform
- Resolves the swift-syntax version from
Package.resolved - Restores from GitHub Actions cache
- Restores published GitHub Release assets on cache miss
- Builds locally only when no cached or published artifact exists
- Signs the manifest with JWS-compatible certificates
- Exports flags for
swift buildto use local prebuilts
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: swiftwasm/setup-swift-syntax-prebuilts@v1
id: prebuilts
- name: Build
run: swift build ${{ steps.prebuilts.outputs.swift-flags }} - uses: swiftwasm/setup-swift-syntax-prebuilts@v1
id: prebuilts
with:
swift-syntax-version: '600.0.1' - uses: swiftwasm/setup-swift-syntax-prebuilts@v1
id: prebuilts
with:
package-resolved-path: my-project/Package.resolved - uses: swiftwasm/setup-swift-syntax-prebuilts@v1
id: prebuilts
with:
signing-leaf-cert: path/to/leaf.cer
signing-intermediate-cert: path/to/intermediate-ca.cer
signing-root-cert: path/to/root-ca.cer
signing-private-key: path/to/leaf-key.pem| Input | Required | Default | Description |
|---|---|---|---|
swift-syntax-version |
No | (auto-detect) | swift-syntax version to prebuild. Auto-detected from Package.resolved if omitted. |
package-resolved-path |
No | Package.resolved |
Path to Package.resolved for version auto-detection. Useful when the project is checked out in a non-cwd directory. |
cache-backend |
No | github |
github or s3 |
restore-from-release |
No | true |
Restore published prebuilts from GitHub Releases before building locally. |
release-owner |
No | swiftwasm |
GitHub owner that publishes prebuilt release assets. |
release-repo |
No | setup-swift-syntax-prebuilts |
GitHub repo that publishes prebuilt release assets. |
s3-bucket |
No | S3 bucket name (when cache-backend=s3) |
|
s3-prefix |
No | swift-syntax-prebuilts |
S3 key prefix |
signing-leaf-cert |
No | (bundled) | Path to leaf certificate (DER format) for manifest signing |
signing-intermediate-cert |
No | (bundled) | Path to intermediate CA certificate (DER format) |
signing-root-cert |
No | (bundled) | Path to root CA certificate (DER format) |
signing-private-key |
No | (bundled) | Path to RSA private key (PEM format) for signing |
| Output | Description |
|---|---|
swift-flags |
Flags to pass to swift build |
prebuilts-path |
Filesystem path to the prebuilts directory |
swift-syntax-version |
The resolved version that was prebuilt |
cache-hit |
true if restored from cache |
restore-source |
github-cache, github-release, local-build, or none |
- First run with a published release asset: cache miss → download release asset (~10 sec) → save cache
- First run without a published release asset: cache miss → build swift-syntax (~4 min) → save cache
- Subsequent runs (same snapshot): cache hit → restore (~10 sec)
- New snapshot: cache miss → rebuild → save. Old entries auto-evict after 7 days.
swift-syntax-prebuilt-v1-{compiler_tag}-{platform}-{syntax_version}
This ensures prebuilts are never reused across incompatible toolchains.
The action generates manifests for both SwiftPM versions:
- Main branch (nightly ≥ 6.3-dev): per-platform manifest files — fully tested and working
- 6.1/6.2 (stable releases): v1 format with per-platform artifact entries — manifests are generated but prebuilt consumption may not work due to JWS signature byte-matching requirements in SwiftPM 6.1/6.2
Note: The primary target audience is nightly toolchain users, where prebuilts provide the most value (no official prebuilts exist for nightly snapshots).
Manifests are signed using JWS (RFC 7515, RS256). The action ships its own self-signed certificate chain by default. You can provide your own certificates via the signing-* inputs.
The --experimental-prebuilts-root-cert flag tells SwiftPM to trust the signing CA.
In GitHub Actions, prebuilts are stored under $RUNNER_TEMP/swift-syntax-prebuilts/ (a per-job temp directory that persists across steps). Outside GitHub Actions, falls back to os.tmpdir().
- Run before any
swiftcommands. If SwiftPM runs without prebuilt flags first, it creates sentinel files that prevent later prebuilt discovery. - The action cleans
.build/prebuilts/if it exists to avoid this poisoning. - macOS builds use
macos_universal; Linux uses{distro}_{codename}_{arch}(e.g.ubuntu_noble_x86_64).
npm install
npm run build # Compile with ncc
npm run typecheck # Type-check only
npm test # Unit tests
npm run test:e2e # End-to-end test (requires Swift toolchain)
npm run test:all # BothThe compiled dist/index.js must be committed to the repository.
MIT