diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..82ca889 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,135 @@ +name: Release + +on: + push: + tags: + - '[0-9]*.[0-9]*.[0-9]*' + +permissions: + contents: write + +jobs: + build: + runs-on: macos-latest + outputs: + asset-url: ${{ steps.package.outputs.asset-url }} + sha256: ${{ steps.package.outputs.sha256 }} + steps: + - uses: actions/checkout@v4 + + - name: Select Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + # This project requires Xcode 26+ (see README Requirements). Pin an exact + # version here if `latest-stable` ever resolves below that floor. + xcode-version: latest-stable + + - name: Build universal release binary + id: build + run: | + set -euo pipefail + flags=(--configuration release --arch arm64 --arch x86_64) + swift build "${flags[@]}" --disable-sandbox + # Ask SwiftPM for the product directory instead of hardcoding + # .build/apple/Products/Release, which is an implementation detail that has + # moved across toolchain versions before. + echo "products=$(swift build "${flags[@]}" --show-bin-path)" >> "$GITHUB_OUTPUT" + + - name: Package + id: package + run: | + set -euo pipefail + version="${{ github.ref_name }}" + name="sourcekit-xcode-bsp-${version}-macos.tar.gz" + products="${{ steps.build.outputs.products }}" + staging="$RUNNER_TEMP/stage" + + mkdir -p "$staging" + cp "$products/sourcekit-xcode-bsp" "$products/SWBBuildServiceBundle" "$staging/" + # swift-build ships one resource bundle per supported platform; glob rather than + # hardcode names so a swift-build revision bump can't silently drop one. + cp -R "$products"/*.bundle "$staging/" + tar -czf "$name" -C "$staging" . + + # Extract to a directory other than $staging to prove the tarball is relocatable, + # not just runnable in place. + verify="$RUNNER_TEMP/verify" + mkdir -p "$verify" + tar -xzf "$name" -C "$verify" + + # --help returns before Serve.run(), so it never exercises the co-located + # SWBBuildServiceBundle lookup and wouldn't catch a single-arch artifact. + # Check architectures directly instead. + for bin in sourcekit-xcode-bsp SWBBuildServiceBundle; do + archs="$(lipo -info "$verify/$bin" | awk -F': ' '{print $NF}')" + for arch in arm64 x86_64; do + if [[ "$archs" != *"$arch"* ]]; then + echo "::error::$bin is missing $arch (found: $archs)" + exit 1 + fi + done + done + "$verify/sourcekit-xcode-bsp" --help >/dev/null + + sha=$(shasum -a 256 "$name" | awk '{print $1}') + echo "sha256=$sha" >> "$GITHUB_OUTPUT" + echo "asset-url=https://github.com/${{ github.repository }}/releases/download/${version}/${name}" >> "$GITHUB_OUTPUT" + echo "ASSET_PATH=$name" >> "$GITHUB_ENV" + + - name: Publish release + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + tag="${{ github.ref_name }}" + # Tolerate a rerun after update-tap failed on a prior attempt: the release + # already exists, so upload to it instead of erroring out of gh release create. + if gh release view "$tag" --repo "${{ github.repository }}" >/dev/null 2>&1; then + gh release upload "$tag" "$ASSET_PATH" --clobber + else + gh release create "$tag" "$ASSET_PATH" --title "$tag" --generate-notes + fi + + update-tap: + needs: build + runs-on: ubuntu-latest + steps: + - name: Checkout tap + uses: actions/checkout@v4 + with: + repository: slime-studio/homebrew-tap + token: ${{ secrets.TAP_GITHUB_TOKEN }} + + - name: Update formula + run: | + set -euo pipefail + version="${{ github.ref_name }}" + asset_url="${{ needs.build.outputs.asset-url }}" + sha="${{ needs.build.outputs.sha256 }}" + # `0,/pattern/s` limits the substitution to the first match, so the `head do` + # block's source url/sha256 (if the formula has one) is left untouched. + sed -i "0,/^ url \".*\"\$/s|^ url \".*\"\$| url \"${asset_url}\"|" Formula/sourcekit-xcode-bsp.rb + sed -i "0,/^ sha256 \".*\"\$/s|^ sha256 \".*\"\$| sha256 \"${sha}\"|" Formula/sourcekit-xcode-bsp.rb + + - name: Open PR + env: + GH_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} + run: | + version="${{ github.ref_name }}" + branch="update/sourcekit-xcode-bsp-${version}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git config --global credential.helper "" + git checkout -b "$branch" + git add Formula/sourcekit-xcode-bsp.rb + git commit -m "Update sourcekit-xcode-bsp to ${version}" + git push "https://x-access-token:${GH_TOKEN}@github.com/slime-studio/homebrew-tap.git" "$branch" + gh pr create \ + --repo slime-studio/homebrew-tap \ + --title "Update sourcekit-xcode-bsp to ${version}" \ + --body "Automated formula update for version \`${version}\`. + + - Prebuilt asset: \`${{ needs.build.outputs.asset-url }}\` + - SHA-256: \`${{ needs.build.outputs.sha256 }}\`" \ + --base main \ + --head "$branch" diff --git a/.github/workflows/update-homebrew-tap.yml b/.github/workflows/update-homebrew-tap.yml deleted file mode 100644 index 934459b..0000000 --- a/.github/workflows/update-homebrew-tap.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Update Homebrew Tap - -on: - push: - tags: - - '[0-9]*.[0-9]*.[0-9]*' - -jobs: - update-tap: - runs-on: ubuntu-latest - steps: - - name: Compute SHA256 - id: sha - run: | - sha=$(curl -sL "https://github.com/${{ github.repository }}/archive/refs/tags/${{ github.ref_name }}.tar.gz" | shasum -a 256 | awk '{print $1}') - echo "value=$sha" >> $GITHUB_OUTPUT - - - name: Checkout tap - uses: actions/checkout@v4 - with: - repository: slime-studio/homebrew-tap - token: ${{ secrets.TAP_GITHUB_TOKEN }} - - - name: Update formula - run: | - version="${{ github.ref_name }}" - sha="${{ steps.sha.outputs.value }}" - sed -i "s|url \".*\"|url \"https://github.com/${{ github.repository }}/archive/refs/tags/${version}.tar.gz\"|" Formula/sourcekit-xcode-bsp.rb - sed -i "s|sha256 \".*\"|sha256 \"${sha}\"|" Formula/sourcekit-xcode-bsp.rb - - - name: Open PR - env: - GH_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} - run: | - version="${{ github.ref_name }}" - branch="update/sourcekit-xcode-bsp-${version}" - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git config --global credential.helper "" - git checkout -b "$branch" - git add Formula/sourcekit-xcode-bsp.rb - git commit -m "Update sourcekit-xcode-bsp to ${version}" - git push "https://x-access-token:${GH_TOKEN}@github.com/slime-studio/homebrew-tap.git" "$branch" - gh pr create \ - --repo slime-studio/homebrew-tap \ - --title "Update sourcekit-xcode-bsp to ${version}" \ - --body "Automated formula update for version \`${version}\`. - - - URL: \`https://github.com/${{ github.repository }}/archive/refs/tags/${version}.tar.gz\` - - SHA-256: \`${{ steps.sha.outputs.value }}\`" \ - --base main \ - --head "$branch"