From 7d7e52beab7ce27067f9b8decc60549f7d7f7844 Mon Sep 17 00:00:00 2001 From: Dimitri Kennedy Date: Wed, 2 Sep 2026 11:02:53 -0400 Subject: [PATCH] fix(release): stop publishing macOS app --- .github/workflows/release-macos-app.yml | 500 ------------------------ .github/workflows/release.yml | 9 - .releaserc.json | 3 +- apps/macos/README.md | 4 +- scripts/prepare-release.ts | 18 - tests/macos-ghostty-source.test.ts | 12 +- tests/release-boundary.test.ts | 27 ++ 7 files changed, 32 insertions(+), 541 deletions(-) delete mode 100644 .github/workflows/release-macos-app.yml create mode 100644 tests/release-boundary.test.ts diff --git a/.github/workflows/release-macos-app.yml b/.github/workflows/release-macos-app.yml deleted file mode 100644 index 19b39fc3..00000000 --- a/.github/workflows/release-macos-app.yml +++ /dev/null @@ -1,500 +0,0 @@ -name: Release macOS App - -# Disabled until GitHub secrets are configured for code signing -# To enable: add APPLE_CERTIFICATE_P12, APPLE_CERTIFICATE_PASSWORD, -# APPLE_ID, APPLE_ID_PASSWORD, APPLE_TEAM_ID secrets -on: - workflow_dispatch: - inputs: - tag: - description: 'Release tag to attach artifact to (e.g., v0.1.0)' - required: true - # Uncomment to auto-trigger on release: - # release: - # types: [published] - workflow_call: - inputs: - tag: - description: 'Release tag to attach artifact to' - required: true - type: string - secrets: - APPLE_CERTIFICATE_P12: - required: true - APPLE_CERTIFICATE_PASSWORD: - required: true - APPLE_ID: - required: true - APPLE_ID_PASSWORD: - required: true - APPLE_TEAM_ID: - required: true - SPARKLE_EDDSA_PRIVATE_KEY: - required: true - -env: - APP_NAME: "Hack Desktop" - SCHEME: HackDesktop - PROJECT_PATH: apps/macos - -jobs: - build-and-notarize: - runs-on: blacksmith-6vcpu-macos-15 - permissions: - contents: write - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - - name: Setup Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: "latest-stable" - - - name: Resolve release metadata - id: meta - run: | - set -euo pipefail - TAG="${{ inputs.tag }}" - VERSION="${TAG#v}" - ARCH="$(uname -m)" - if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then - ARCH="x86_64" - elif [ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]; then - ARCH="arm64" - else - echo "Unsupported architecture: $ARCH" - exit 1 - fi - - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "version=$VERSION" >> "$GITHUB_OUTPUT" - echo "arch=$ARCH" >> "$GITHUB_OUTPUT" - - # Important: do this before `xcodegen generate`. XcodeGen snapshots resources at generation time, - # and we populate BundledCLI dynamically from the release tarball. - - name: Bundle CLI into app resources - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RELEASE_TAG: ${{ steps.meta.outputs.tag }} - VERSION: ${{ steps.meta.outputs.version }} - ARCH: ${{ steps.meta.outputs.arch }} - run: | - set -euo pipefail - TARBALL="hack-$VERSION-darwin-$ARCH.tar.gz" - - mkdir -p "$RUNNER_TEMP/cli" - gh release download "$RELEASE_TAG" -p "$TARBALL" --dir "$RUNNER_TEMP/cli" - - mkdir -p "$RUNNER_TEMP/cli/extract" - tar -xzf "$RUNNER_TEMP/cli/$TARBALL" -C "$RUNNER_TEMP/cli/extract" - - RELEASE_DIR="$RUNNER_TEMP/cli/extract/hack-$VERSION-release" - if [ ! -d "$RELEASE_DIR" ]; then - echo "Missing release dir: $RELEASE_DIR" - exit 1 - fi - - BUNDLE_DIR="apps/macos/App/BundledCLI" - mkdir -p "$BUNDLE_DIR" - rm -rf "$BUNDLE_DIR/hack" "$BUNDLE_DIR/assets" "$BUNDLE_DIR/binaries" - - cp "$RELEASE_DIR/hack" "$BUNDLE_DIR/hack" - if [ -d "$RELEASE_DIR/assets" ]; then - cp -R "$RELEASE_DIR/assets" "$BUNDLE_DIR/assets" - fi - if [ -d "$RELEASE_DIR/binaries" ]; then - cp -R "$RELEASE_DIR/binaries" "$BUNDLE_DIR/binaries" - fi - - - name: Install Zig (0.15.2) - run: | - set -euo pipefail - ZIG_VERSION="0.15.2" - - HOST_ARCH="$(uname -m)" - if [ "$HOST_ARCH" = "arm64" ] || [ "$HOST_ARCH" = "aarch64" ]; then - ZIG_ARCH="aarch64" - elif [ "$HOST_ARCH" = "x86_64" ] || [ "$HOST_ARCH" = "amd64" ]; then - ZIG_ARCH="x86_64" - else - echo "Unsupported host arch: $HOST_ARCH" - exit 1 - fi - - URL="https://ziglang.org/download/${ZIG_VERSION}/zig-${ZIG_ARCH}-macos-${ZIG_VERSION}.tar.xz" - curl -fsSL "$URL" -o "$RUNNER_TEMP/zig.tar.xz" - mkdir -p "$RUNNER_TEMP/zig" - tar -xf "$RUNNER_TEMP/zig.tar.xz" -C "$RUNNER_TEMP/zig" - - ZIG_BIN="$(find "$RUNNER_TEMP/zig" -maxdepth 2 -type f -name zig | head -n 1)" - if [ -z "$ZIG_BIN" ]; then - echo "Failed to locate zig binary after extracting." - exit 1 - fi - - ZIG_DIR="$(dirname "$ZIG_BIN")" - export PATH="$ZIG_DIR:$PATH" - echo "$ZIG_DIR" >> "$GITHUB_PATH" - "$ZIG_BIN" version - - - name: Build Ghostty VT dylib (universal) - run: | - set -euo pipefail - - VENDOR_DIR="apps/macos/vendor/ghostty" - BRIDGE_DIR="apps/macos/Experiments/GhosttyVTBridge" - REVISION_FILE="$BRIDGE_DIR/GHOSTTY_REVISION" - OUT_DIR="apps/macos/App/GhosttyVT/ghostty/lib" - OUT_LIB="$OUT_DIR/libhack_ghostty_vt.dylib" - GHOSTTY_REVISION="$(tr -d '[:space:]' < "$REVISION_FILE")" - - if [ ! -d "$VENDOR_DIR" ]; then - mkdir -p "$(dirname "$VENDOR_DIR")" - git clone --filter=blob:none --no-checkout https://github.com/ghostty-org/ghostty "$VENDOR_DIR" - fi - - git -C "$VENDOR_DIR" fetch --depth 1 origin "$GHOSTTY_REVISION" - git -C "$VENDOR_DIR" checkout --detach --force FETCH_HEAD - - ACTUAL_GHOSTTY_REVISION="$(git -C "$VENDOR_DIR" rev-parse HEAD)" - if [ "$ACTUAL_GHOSTTY_REVISION" != "$GHOSTTY_REVISION" ]; then - echo "Expected Ghostty $GHOSTTY_REVISION, checked out $ACTUAL_GHOSTTY_REVISION" - exit 1 - fi - echo "Ghostty revision: $ACTUAL_GHOSTTY_REVISION" - - mkdir -p "$OUT_DIR" - - # Patch Ghostty's lib_vt.zig for our C ABI bridge. - python3 - <<'PY' - import pathlib - - lib_vt = pathlib.Path("apps/macos/vendor/ghostty/src/lib_vt.zig") - text = lib_vt.read_text(encoding="utf-8") - guard = 'if (@import("root") == lib) {' - patched = 'if (@import("root") == lib and terminal.options.c_abi) {' - if guard in text and patched not in text: - text = text.replace(guard, patched) - if "@export(&" in text: - text = text.replace("@export(&", "@export(") - lib_vt.write_text(text, encoding="utf-8") - PY - - mkdir -p "$RUNNER_TEMP/ghosttyvt/arm64" "$RUNNER_TEMP/ghosttyvt/x86_64" - - pushd "$BRIDGE_DIR" >/dev/null - GHOSTTY_DIR="$GITHUB_WORKSPACE/$VENDOR_DIR" - - zig build -Dghostty="$GHOSTTY_DIR" -Doptimize=ReleaseSafe -Dtarget=aarch64-macos --prefix "$RUNNER_TEMP/ghosttyvt/arm64" - zig build -Dghostty="$GHOSTTY_DIR" -Doptimize=ReleaseSafe -Dtarget=x86_64-macos --prefix "$RUNNER_TEMP/ghosttyvt/x86_64" - popd >/dev/null - - ARM_LIB="$RUNNER_TEMP/ghosttyvt/arm64/lib/libhack_ghostty_vt.dylib" - X64_LIB="$RUNNER_TEMP/ghosttyvt/x86_64/lib/libhack_ghostty_vt.dylib" - - if [ ! -f "$ARM_LIB" ] || [ ! -f "$X64_LIB" ]; then - echo "Missing built libs: $ARM_LIB / $X64_LIB" - ls -la "$RUNNER_TEMP/ghosttyvt/arm64/lib" || true - ls -la "$RUNNER_TEMP/ghosttyvt/x86_64/lib" || true - exit 1 - fi - - lipo -create "$ARM_LIB" "$X64_LIB" -output "$OUT_LIB" - - - name: Install xcodegen - run: brew install xcodegen - - - name: Generate Xcode project - working-directory: ${{ env.PROJECT_PATH }} - run: xcodegen generate - - - name: Import certificate - env: - CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }} - CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - run: | - # Create temporary keychain - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - KEYCHAIN_PASSWORD=$(openssl rand -base64 32) - - security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" - security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - - # Import certificate - echo "$CERTIFICATE_P12" | base64 --decode > $RUNNER_TEMP/certificate.p12 - security import $RUNNER_TEMP/certificate.p12 \ - -P "$CERTIFICATE_PASSWORD" \ - -A \ - -t cert \ - -f pkcs12 \ - -k "$KEYCHAIN_PATH" - - # Allow codesign to access keychain - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - - # Add to search list - security list-keychain -d user -s "$KEYCHAIN_PATH" - - echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> $GITHUB_ENV - - - name: Resolve codesign identity - run: | - set -euo pipefail - LINE="$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep 'Developer ID Application' | head -n 1 || true)" - if [ -z "$LINE" ]; then - echo "No Developer ID Application identity found in keychain: $KEYCHAIN_PATH" - security find-identity -v -p codesigning "$KEYCHAIN_PATH" || true - exit 1 - fi - - IDENTITY_HASH="$(echo "$LINE" | awk '{print $2}')" - IDENTITY_NAME="$(echo "$LINE" | awk -F '\"' '{print $2}')" - - if [ -z "$IDENTITY_HASH" ] || [ -z "$IDENTITY_NAME" ]; then - echo "Failed to parse identity from line: $LINE" - exit 1 - fi - - echo "CODESIGN_IDENTITY_HASH=$IDENTITY_HASH" >> "$GITHUB_ENV" - echo "CODESIGN_IDENTITY_NAME=$IDENTITY_NAME" >> "$GITHUB_ENV" - - - name: Codesign bundled CLI - env: - BUNDLED_HACK: apps/macos/App/BundledCLI/hack - run: | - set -euo pipefail - if [ ! -f "$BUNDLED_HACK" ]; then - echo "Missing bundled hack binary: $BUNDLED_HACK" - exit 1 - fi - - codesign --force --options runtime --timestamp \ - --entitlements "apps/macos/App/HackCLIBundled.entitlements" \ - --sign "$CODESIGN_IDENTITY_HASH" \ - --keychain "$KEYCHAIN_PATH" \ - "$BUNDLED_HACK" - - codesign -vvv "$BUNDLED_HACK" - - - name: Codesign Ghostty VT dylib - env: - GHOSTTY_VT: apps/macos/App/GhosttyVT/ghostty/lib/libhack_ghostty_vt.dylib - run: | - set -euo pipefail - if [ ! -f "$GHOSTTY_VT" ]; then - echo "Missing Ghostty VT dylib: $GHOSTTY_VT" - exit 1 - fi - - codesign --force --options runtime --timestamp \ - --sign "$CODESIGN_IDENTITY_HASH" \ - --keychain "$KEYCHAIN_PATH" \ - "$GHOSTTY_VT" - - codesign -vvv "$GHOSTTY_VT" - - - name: Build and archive - working-directory: ${{ env.PROJECT_PATH }} - env: - TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - run: | - xcodebuild archive \ - -scheme "$SCHEME" \ - -configuration Release \ - -archivePath "$RUNNER_TEMP/HackDesktop.xcarchive" \ - CODE_SIGN_STYLE=Manual \ - CODE_SIGN_IDENTITY="$CODESIGN_IDENTITY_NAME" \ - DEVELOPMENT_TEAM="$TEAM_ID" \ - OTHER_CODE_SIGN_FLAGS="--keychain $KEYCHAIN_PATH --timestamp" - - - name: Export app - env: - TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - run: | - cat > $RUNNER_TEMP/ExportOptions.plist << EOF - - - - - method - developer-id - teamID - $TEAM_ID - signingStyle - manual - signingCertificate - $CODESIGN_IDENTITY_NAME - - - EOF - - xcodebuild -exportArchive \ - -archivePath "$RUNNER_TEMP/HackDesktop.xcarchive" \ - -exportPath "$RUNNER_TEMP/export" \ - -exportOptionsPlist "$RUNNER_TEMP/ExportOptions.plist" - - - name: Notarize app - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - run: | - # Create ZIP for notarization - ditto -c -k --keepParent "$RUNNER_TEMP/export/$APP_NAME.app" "$RUNNER_TEMP/app.zip" - - # Submit for notarization - xcrun notarytool submit "$RUNNER_TEMP/app.zip" \ - --apple-id "$APPLE_ID" \ - --password "$APPLE_ID_PASSWORD" \ - --team-id "$APPLE_TEAM_ID" \ - --wait - - # Staple the notarization ticket - xcrun stapler staple "$RUNNER_TEMP/export/$APP_NAME.app" - - - name: Create DMG - run: | - # Install create-dmg - brew install create-dmg - - # Create DMG - create-dmg \ - --volname "$APP_NAME" \ - --window-pos 200 120 \ - --window-size 600 400 \ - --icon-size 100 \ - --icon "$APP_NAME.app" 150 190 \ - --app-drop-link 450 190 \ - --hide-extension "$APP_NAME.app" \ - "$RUNNER_TEMP/HackDesktop.dmg" \ - "$RUNNER_TEMP/export/$APP_NAME.app" || true - - # Fallback if create-dmg fails (it returns non-zero even on success sometimes) - if [ ! -f "$RUNNER_TEMP/HackDesktop.dmg" ]; then - hdiutil create -volname "$APP_NAME" \ - -srcfolder "$RUNNER_TEMP/export/$APP_NAME.app" \ - -ov -format UDZO \ - "$RUNNER_TEMP/HackDesktop.dmg" - fi - - - name: Notarize DMG - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - run: | - xcrun notarytool submit "$RUNNER_TEMP/HackDesktop.dmg" \ - --apple-id "$APPLE_ID" \ - --password "$APPLE_ID_PASSWORD" \ - --team-id "$APPLE_TEAM_ID" \ - --wait - - xcrun stapler staple "$RUNNER_TEMP/HackDesktop.dmg" - - - name: Get version - id: version - run: | - VERSION=$(defaults read "$RUNNER_TEMP/export/$APP_NAME.app/Contents/Info.plist" CFBundleShortVersionString) - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Rename artifacts - env: - VERSION: ${{ steps.version.outputs.version }} - run: | - mv "$RUNNER_TEMP/HackDesktop.dmg" "$RUNNER_TEMP/HackDesktop-$VERSION-macOS.dmg" - - # Also create a ZIP of the app - ditto -c -k --keepParent \ - "$RUNNER_TEMP/export/$APP_NAME.app" \ - "$RUNNER_TEMP/HackDesktop-$VERSION-macOS.zip" - - - name: Generate Sparkle appcast - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }} - VERSION: ${{ steps.version.outputs.version }} - SPARKLE_EDDSA_PRIVATE_KEY: ${{ secrets.SPARKLE_EDDSA_PRIVATE_KEY }} - run: | - set -euo pipefail - - mkdir -p "$RUNNER_TEMP/sparkle" - gh release download 2.8.1 -R sparkle-project/Sparkle -p "Sparkle-2.8.1.tar.xz" --dir "$RUNNER_TEMP/sparkle" - tar -xf "$RUNNER_TEMP/sparkle/Sparkle-2.8.1.tar.xz" -C "$RUNNER_TEMP/sparkle" - - ZIP_PATH="$RUNNER_TEMP/HackDesktop-$VERSION-macOS.zip" - if [ ! -f "$ZIP_PATH" ]; then - echo "Missing ZIP: $ZIP_PATH" - exit 1 - fi - - SIGN_LINE="$(printf '%s' "$SPARKLE_EDDSA_PRIVATE_KEY" | "$RUNNER_TEMP/sparkle/bin/sign_update" --ed-key-file - "$ZIP_PATH")" - ED_SIGNATURE="$(echo "$SIGN_LINE" | sed -n 's/.*sparkle:edSignature=\"\([^\"]*\)\".*/\1/p')" - LENGTH="$(echo "$SIGN_LINE" | sed -n 's/.*length=\"\([0-9]*\)\".*/\1/p')" - - if [ -z "$ED_SIGNATURE" ] || [ -z "$LENGTH" ]; then - echo "Failed to parse signature output: $SIGN_LINE" - exit 1 - fi - - PUB_DATE="$(date -u +"%a, %d %b %Y %H:%M:%S %z")" - DOWNLOAD_URL="https://github.com/hack-dance/hack/releases/download/$RELEASE_TAG/HackDesktop-$VERSION-macOS.zip" - NOTES_URL="https://github.com/hack-dance/hack/releases/tag/$RELEASE_TAG" - - cat > "$RUNNER_TEMP/appcast.xml" << EOF - - - - Hack Desktop - https://github.com/hack-dance/hack - Hack Desktop updates - en - - Version $VERSION - $NOTES_URL - $PUB_DATE - - - - - EOF - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: macos-app - path: | - ${{ runner.temp }}/HackDesktop-*.dmg - ${{ runner.temp }}/HackDesktop-*.zip - ${{ runner.temp }}/appcast.xml - - - name: Upload to release - if: github.event_name == 'release' || inputs.tag != '' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }} - VERSION: ${{ steps.version.outputs.version }} - run: | - gh release upload "$RELEASE_TAG" \ - "$RUNNER_TEMP/HackDesktop-$VERSION-macOS.dmg" \ - "$RUNNER_TEMP/HackDesktop-$VERSION-macOS.zip" \ - "$RUNNER_TEMP/appcast.xml" \ - --clobber - - - name: Cleanup keychain - if: always() - run: | - if [ -n "$KEYCHAIN_PATH" ] && [ -f "$KEYCHAIN_PATH" ]; then - security delete-keychain "$KEYCHAIN_PATH" || true - fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd886908..47943bfa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -145,15 +145,6 @@ jobs: done done - macos-app: - needs: [create-release, build] - permissions: - contents: write - uses: ./.github/workflows/release-macos-app.yml - with: - tag: ${{ needs.create-release.outputs.tag }} - secrets: inherit - update-homebrew-tap: needs: [create-release, build] runs-on: blacksmith-4vcpu-ubuntu-2404 diff --git a/.releaserc.json b/.releaserc.json index 26c199a4..1f8ae3f2 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -23,8 +23,7 @@ "packages/cli/package.json", "packages/db/package.json", "services/auth-broker/package.json", - "bun.lock", - "apps/macos/Config/Base.xcconfig" + "bun.lock" ], "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}" } diff --git a/apps/macos/README.md b/apps/macos/README.md index 178bc771..36921750 100644 --- a/apps/macos/README.md +++ b/apps/macos/README.md @@ -2,7 +2,9 @@ Native macOS app for managing local hack projects, runtime status, and quick actions. -Hack v3 keeps the app intentionally small and local-first. +The source is retained for possible future work, but the app is currently unsupported and is not +built, signed, or published by Hack's CI/release pipeline. The commands below are local development +tools only. ## Requirements diff --git a/scripts/prepare-release.ts b/scripts/prepare-release.ts index c06d1b39..eea51fd3 100644 --- a/scripts/prepare-release.ts +++ b/scripts/prepare-release.ts @@ -62,24 +62,6 @@ async function main({ args }: { readonly args: Args }): Promise { rootPackageJson: pkg, }); - // Update macOS app version in Base.xcconfig - const xconfigPath = resolve(repoRoot, "apps/macos/Config/Base.xcconfig"); - try { - const xconfigContent = await Bun.file(xconfigPath).text(); - const updatedXconfig = xconfigContent.replace( - /^MARKETING_VERSION = .*/m, - `MARKETING_VERSION = ${nextVersion}` - ); - if (updatedXconfig !== xconfigContent) { - await Bun.write(xconfigPath, updatedXconfig); - process.stdout.write( - `Updated Base.xcconfig: MARKETING_VERSION → ${nextVersion}\n` - ); - } - } catch { - // macOS config may not exist, that's fine - } - return 0; } diff --git a/tests/macos-ghostty-source.test.ts b/tests/macos-ghostty-source.test.ts index de97446d..0b633386 100644 --- a/tests/macos-ghostty-source.test.ts +++ b/tests/macos-ghostty-source.test.ts @@ -5,7 +5,7 @@ const repoRoot = path.resolve(import.meta.dir, ".."); const bridgeDir = path.join(repoRoot, "apps/macos/Experiments/GhosttyVTBridge"); describe("Ghostty source pin", () => { - test("uses one immutable revision in local and release builds", async () => { + test("uses one immutable revision in local builds", async () => { const revision = ( await Bun.file(path.join(bridgeDir, "GHOSTTY_REVISION")).text() ).trim(); @@ -15,10 +15,6 @@ describe("Ghostty source pin", () => { const bundleScript = await Bun.file( path.join(repoRoot, "scripts/macos-ghostty-bundle.ts") ).text(); - const releaseWorkflow = await Bun.file( - path.join(repoRoot, ".github/workflows/release-macos-app.yml") - ).text(); - expect(revision).toMatch(/^[0-9a-f]{40}$/); expect(setupScript).toContain('path.join(bridgeDir, "GHOSTTY_REVISION")'); expect(bundleScript).toContain('path.join(bridgeDir, "GHOSTTY_REVISION")'); @@ -26,12 +22,6 @@ describe("Ghostty source pin", () => { expect(bundleScript).toContain( "git -C ${vendorDir} reset --hard ${ghosttyRevision}" ); - expect(releaseWorkflow).toContain( - 'REVISION_FILE="$BRIDGE_DIR/GHOSTTY_REVISION"' - ); expect(setupScript).not.toContain("fetch --depth 1 origin main"); - expect(releaseWorkflow).not.toContain( - "git clone --depth 1 https://github.com/ghostty-org/ghostty" - ); }); }); diff --git a/tests/release-boundary.test.ts b/tests/release-boundary.test.ts new file mode 100644 index 00000000..317d2dfd --- /dev/null +++ b/tests/release-boundary.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, test } from "bun:test"; +import path from "node:path"; + +const repoRoot = path.resolve(import.meta.dir, ".."); + +describe("release product boundary", () => { + test("does not build or publish the retained macOS app", async () => { + const releaseWorkflow = await Bun.file( + path.join(repoRoot, ".github/workflows/release.yml") + ).text(); + const macosReleaseWorkflow = Bun.file( + path.join(repoRoot, ".github/workflows/release-macos-app.yml") + ); + const releaseConfig = await Bun.file( + path.join(repoRoot, ".releaserc.json") + ).json(); + const prepareRelease = await Bun.file( + path.join(repoRoot, "scripts/prepare-release.ts") + ).text(); + + expect(releaseWorkflow).not.toContain("release-macos-app"); + expect(releaseWorkflow).not.toContain("macos-app:"); + expect(await macosReleaseWorkflow.exists()).toBe(false); + expect(JSON.stringify(releaseConfig)).not.toContain("apps/macos"); + expect(prepareRelease).not.toContain("Base.xcconfig"); + }); +});