Build Prebuilts #26
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
| name: Build Prebuilts | |
| # Build SwiftSyntax prebuilt artifacts for all platforms and publish | |
| # them as a GitHub Release. The release tag lives on the orphan | |
| # 'gh-releases' branch so it doesn't pollute main history. | |
| # | |
| # Release tag format: prebuilt-{syntaxVersion}-{compilerTag} | |
| # Each release contains manifests + artifacts for all platforms. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| swift-syntax-version: | |
| description: 'swift-syntax version (git tag, e.g. 600.0.1)' | |
| required: true | |
| type: string | |
| compiler-tag: | |
| description: 'Swift compiler tag (e.g. swift-6.1-RELEASE)' | |
| required: true | |
| type: string | |
| swift-major-minor: | |
| description: 'Swift major.minor for V1 manifest (e.g. 6.1). Leave empty to skip V1.' | |
| required: false | |
| type: string | |
| default: '' | |
| swift-download-url: | |
| description: 'Optional fallback Linux Swift toolchain tarball URL.' | |
| required: false | |
| type: string | |
| default: '' | |
| ubuntu-22-download-url: | |
| description: 'Optional Swift toolchain tarball URL for ubuntu-22.04.' | |
| required: false | |
| type: string | |
| default: '' | |
| ubuntu-24-download-url: | |
| description: 'Optional Swift toolchain tarball URL for ubuntu-24.04.' | |
| required: false | |
| type: string | |
| default: '' | |
| include-ubuntu-22: | |
| description: 'Build Ubuntu 22.04 artifacts.' | |
| required: false | |
| type: boolean | |
| default: true | |
| include-ubuntu-24: | |
| description: 'Build Ubuntu 24.04 artifacts.' | |
| required: false | |
| type: boolean | |
| default: true | |
| include-macos: | |
| description: 'Build macOS artifacts too.' | |
| required: false | |
| type: boolean | |
| default: true | |
| jobs: | |
| build: | |
| name: Build (${{ matrix.platform }}) | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-22.04 | |
| platform: ubuntu_jammy_x86_64 | |
| swift-version: '' | |
| - runner: ubuntu-24.04 | |
| platform: ubuntu_noble_x86_64 | |
| swift-version: '' | |
| # - runner: ubuntu-24.04-arm | |
| # platform: ubuntu_noble_aarch64 | |
| # swift-version: '' | |
| - runner: macos-15 | |
| platform: macos_universal | |
| swift-version: '' | |
| steps: | |
| - name: Select platform | |
| id: platform | |
| run: | | |
| enabled=true | |
| download_url="" | |
| case "${{ matrix.platform }}" in | |
| ubuntu_jammy_x86_64) | |
| if [ "${{ inputs['include-ubuntu-22'] }}" != "true" ]; then | |
| enabled=false | |
| fi | |
| download_url="${{ inputs['ubuntu-22-download-url'] || inputs['swift-download-url'] }}" | |
| ;; | |
| ubuntu_noble_x86_64) | |
| if [ "${{ inputs['include-ubuntu-24'] }}" != "true" ]; then | |
| enabled=false | |
| fi | |
| download_url="${{ inputs['ubuntu-24-download-url'] || inputs['swift-download-url'] }}" | |
| ;; | |
| macos_universal) | |
| if [ "${{ inputs.include-macos }}" != "true" ]; then | |
| enabled=false | |
| fi | |
| ;; | |
| esac | |
| echo "enabled=$enabled" >> "$GITHUB_OUTPUT" | |
| echo "download-url=$download_url" >> "$GITHUB_OUTPUT" | |
| - uses: actions/checkout@v4 | |
| if: steps.platform.outputs.enabled == 'true' | |
| - uses: actions/setup-node@v4 | |
| if: steps.platform.outputs.enabled == 'true' | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Determine Swift version to install | |
| id: swift-version | |
| if: steps.platform.outputs.enabled == 'true' && steps.platform.outputs['download-url'] == '' | |
| run: | | |
| TAG="${{ inputs.compiler-tag }}" | |
| # Extract installable version from compiler tag | |
| # swift-6.1-RELEASE -> 6.1 | |
| # swift-6.1.2-RELEASE -> 6.1.2 | |
| # swift-DEVELOPMENT-SNAPSHOT-2025-06-01-a -> main-snapshot-2025-06-01-a | |
| if [[ "$TAG" =~ ^swift-([0-9]+\.[0-9]+(\.[0-9]+)?)-RELEASE$ ]]; then | |
| echo "version=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" | |
| elif [[ "$TAG" =~ ^swift-DEVELOPMENT-SNAPSHOT-(.+)$ ]]; then | |
| echo "version=main-snapshot-${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" | |
| elif [[ "$TAG" =~ ^swift-([0-9]+\.[0-9]+(\.[0-9]+)?)-DEVELOPMENT-SNAPSHOT-(.+)$ ]]; then | |
| echo "version=${BASH_REMATCH[1]}-snapshot-${BASH_REMATCH[3]}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "::error::Cannot parse compiler tag: $TAG" | |
| exit 1 | |
| fi | |
| - name: Install Swift from tarball | |
| if: steps.platform.outputs.enabled == 'true' && steps.platform.outputs['download-url'] != '' | |
| run: | | |
| sudo apt-get -q update | |
| sudo apt-get install -y \ | |
| binutils \ | |
| git \ | |
| gnupg2 \ | |
| libc6-dev \ | |
| libcurl4-openssl-dev \ | |
| libedit2 \ | |
| libgcc-9-dev \ | |
| libpython3.8 \ | |
| libsqlite3-0 \ | |
| libstdc++-9-dev \ | |
| libxml2-dev \ | |
| libz3-dev \ | |
| pkg-config \ | |
| tzdata \ | |
| unzip \ | |
| zlib1g-dev \ | |
| curl | |
| curl -fL "${{ steps.platform.outputs['download-url'] }}" | sudo tar xfz - --strip-components=2 -C /usr/local | |
| - uses: swift-actions/setup-swift@v3 | |
| if: steps.platform.outputs.enabled == 'true' && steps.platform.outputs['download-url'] == '' | |
| id: setup-swift | |
| continue-on-error: true | |
| with: | |
| swift-version: ${{ steps.swift-version.outputs.version }} | |
| skip-verify-signature: ${{ runner.os == 'Linux' }} | |
| - name: Verify Swift installation | |
| if: steps.platform.outputs.enabled == 'true' | |
| run: swift --version | |
| - run: npm ci | |
| if: steps.platform.outputs.enabled == 'true' | |
| - name: Build dist | |
| if: steps.platform.outputs.enabled == 'true' | |
| run: npm run build | |
| - name: Build prebuilt | |
| if: steps.platform.outputs.enabled == 'true' | |
| run: | | |
| mkdir -p ./prebuilt-output | |
| node dist/cli-build/index.js \ | |
| --syntax-version "${{ inputs.swift-syntax-version }}" \ | |
| --compiler-tag "${{ inputs.compiler-tag }}" \ | |
| --swift-major-minor "${{ inputs.swift-major-minor }}" \ | |
| --platform "${{ matrix.platform }}" \ | |
| --output-dir ./prebuilt-output \ | |
| > ./prebuilt-output/summary.json | |
| timeout-minutes: 15 | |
| - name: Upload platform artifacts | |
| if: steps.platform.outputs.enabled == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: prebuilt-${{ matrix.platform }} | |
| path: ./prebuilt-output/ | |
| retention-days: 1 | |
| release: | |
| name: Create Release | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - run: npm ci | |
| - name: Build dist | |
| run: npm run build | |
| - name: Download all platform artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./all-platforms/ | |
| pattern: prebuilt-* | |
| - name: List downloaded artifacts | |
| run: find ./all-platforms/ -type f | sort | |
| - name: Merge V1 manifests (if applicable) | |
| if: inputs.swift-major-minor != '' | |
| run: | | |
| node dist/cli-merge-v1-manifest/index.js \ | |
| --swift-major-minor "${{ inputs.swift-major-minor }}" \ | |
| --input-dir ./all-platforms \ | |
| --output-dir ./merged-v1 | |
| - name: Prepare release assets | |
| id: assets | |
| run: | | |
| mkdir -p ./release-assets | |
| # Collect main branch manifests + artifacts from each platform | |
| for dir in ./all-platforms/prebuilt-*/; do | |
| platform=$(basename "$dir" | sed 's/^prebuilt-//') | |
| TAG="${{ inputs.compiler-tag }}" | |
| # Main branch manifest | |
| cp "${dir}${TAG}-${platform}.json" ./release-assets/ 2>/dev/null || true | |
| # Main branch artifact | |
| cp "${dir}${TAG}-${platform}-MacroSupport.tar.gz" ./release-assets/ 2>/dev/null || true | |
| # V1 artifact (per-platform) | |
| MAJOR_MINOR="${{ inputs.swift-major-minor }}" | |
| if [ -n "$MAJOR_MINOR" ]; then | |
| cp "${dir}${MAJOR_MINOR}-MacroSupport-${platform}.tar.gz" ./release-assets/ 2>/dev/null || true | |
| fi | |
| # Root CA cert (same for all, just copy once) | |
| cp "${dir}root-ca.cer" ./release-assets/ 2>/dev/null || true | |
| done | |
| # Merged V1 manifest (all platforms in one file) | |
| MAJOR_MINOR="${{ inputs.swift-major-minor }}" | |
| if [ -n "$MAJOR_MINOR" ] && [ -f "./merged-v1/${MAJOR_MINOR}-manifest.json" ]; then | |
| cp "./merged-v1/${MAJOR_MINOR}-manifest.json" ./release-assets/ | |
| fi | |
| echo "Release assets:" | |
| ls -la ./release-assets/ | |
| - name: Ensure orphan branch exists | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if ! git ls-remote --heads origin gh-releases | grep -q gh-releases; then | |
| # Create the orphan branch via the GitHub API (no local checkout needed) | |
| REPO="${{ github.repository }}" | |
| # Get the tree SHA for an empty tree | |
| EMPTY_TREE=$(git hash-object -t tree /dev/null) | |
| # Create a commit with no parents | |
| COMMIT_SHA=$(gh api "repos/$REPO/git/commits" \ | |
| -f message="Release branch for prebuilt artifacts" \ | |
| -f "tree=$EMPTY_TREE" \ | |
| --jq '.sha') | |
| # Create the branch ref | |
| gh api "repos/$REPO/git/refs" \ | |
| -f "ref=refs/heads/gh-releases" \ | |
| -f "sha=$COMMIT_SHA" | |
| echo "Created gh-releases branch at $COMMIT_SHA" | |
| fi | |
| - name: Create GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="prebuilt-${{ inputs.swift-syntax-version }}-${{ inputs.compiler-tag }}" | |
| TITLE="swift-syntax ${{ inputs.swift-syntax-version }} / ${{ inputs.compiler-tag }}" | |
| # Fetch the gh-releases branch SHA for the tag target | |
| TARGET_SHA=$(git ls-remote origin gh-releases | cut -f1) | |
| # Delete existing release if it exists (to allow re-runs) | |
| gh release delete "$TAG" --yes 2>/dev/null || true | |
| git push origin :refs/tags/"$TAG" 2>/dev/null || true | |
| # Create release on the gh-releases branch | |
| BODY="Prebuilt SwiftSyntax artifacts. | |
| - swift-syntax: ${{ inputs.swift-syntax-version }} | |
| - Compiler: ${{ inputs.compiler-tag }} | |
| - Platforms: $(ls ./release-assets/*-MacroSupport.tar.gz 2>/dev/null | sed 's/.*\///' | sed 's/-MacroSupport.tar.gz//' | tr '\n' ', ' | sed 's/,$//')" | |
| gh release create "$TAG" \ | |
| --target "$TARGET_SHA" \ | |
| --title "$TITLE" \ | |
| --notes "$BODY" \ | |
| ./release-assets/* | |
| echo "✅ Release created: $TAG" | |
| echo " URL: https://github.com/${{ github.repository }}/releases/tag/$TAG" |