diff --git a/.github/workflows/benchmark-targets.yml b/.github/workflows/benchmark-targets.yml
index 9434e4d39..390537937 100644
--- a/.github/workflows/benchmark-targets.yml
+++ b/.github/workflows/benchmark-targets.yml
@@ -28,8 +28,6 @@ jobs:
include:
- name: linux / ubuntu-22.04
runs_on: ubuntu-22.04
- - name: macos / apple-silicon
- runs_on: macos-latest
- name: windows / x86_64
runs_on: windows-latest
- name: windows / arm64
diff --git a/.github/workflows/build-release-artifacts.yml b/.github/workflows/build-release-artifacts.yml
index 3fe8507c6..e012aebf5 100644
--- a/.github/workflows/build-release-artifacts.yml
+++ b/.github/workflows/build-release-artifacts.yml
@@ -19,18 +19,6 @@ on:
secrets:
AZURE_CREDENTIALS:
required: false
- MACOS_SIGNING_IDENTITY:
- required: false
- MACOS_SIGNING_CERT_BASE64:
- required: false
- MACOS_SIGNING_CERT_PASSWORD:
- required: false
- MACOS_NOTARY_KEY_ID:
- required: false
- MACOS_NOTARY_ISSUER_ID:
- required: false
- MACOS_NOTARY_API_KEY_P8:
- required: false
workflow_dispatch:
inputs:
tag:
@@ -534,201 +522,11 @@ jobs:
if-no-files-found: error
retention-days: 7
- build_macos:
- name: Build macOS artifacts (${{ matrix.target_platform }})
- runs-on: ${{ matrix.runs_on }}
- timeout-minutes: 120
- needs: prepare
- strategy:
- fail-fast: false
- matrix:
- include:
- - target_platform: aarch64-darwin
- arch: arm64
- runs_on: macos-latest
- - target_platform: x86_64-darwin
- arch: x86_64
- runs_on: macos-15-intel
- env:
- TAG: ${{ needs.prepare.outputs.tag }}
- VERSION: ${{ needs.prepare.outputs.version }}
- ARCH: ${{ matrix.arch }}
- MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
- MACOS_SIGNING_CERT_BASE64: ${{ secrets.MACOS_SIGNING_CERT_BASE64 }}
- MACOS_SIGNING_CERT_PASSWORD: ${{ secrets.MACOS_SIGNING_CERT_PASSWORD }}
- MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
- MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
- MACOS_NOTARY_API_KEY_P8: ${{ secrets.MACOS_NOTARY_API_KEY_P8 }}
- steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- with:
- ref: ${{ needs.prepare.outputs.tag }}
- fetch-depth: 0
-
- - name: Install Rust toolchain
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
-
- - name: Cache Rust artifacts
- uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
- with:
- cache-targets: false
-
- - name: Determine macOS signing mode
- id: macos_signing_mode
- run: |
- set -euo pipefail
-
- required=(
- MACOS_SIGNING_IDENTITY
- MACOS_SIGNING_CERT_BASE64
- MACOS_SIGNING_CERT_PASSWORD
- MACOS_NOTARY_KEY_ID
- MACOS_NOTARY_ISSUER_ID
- MACOS_NOTARY_API_KEY_P8
- )
- present=()
- missing=()
-
- for name in "${required[@]}"; do
- if [ -n "${!name:-}" ]; then
- present+=("$name")
- else
- missing+=("$name")
- fi
- done
-
- if [ "${#present[@]}" -eq 0 ]; then
- echo "enabled=false" >> "$GITHUB_OUTPUT"
- echo "macOS signing is not configured; building unsigned macOS artifacts."
- exit 0
- fi
-
- if [ "${#missing[@]}" -gt 0 ]; then
- echo "::error title=Incomplete macOS signing configuration::Missing required secret(s): ${missing[*]}"
- echo "::error title=Partial macOS signing configuration::Either provide all macOS signing and notarization secrets or leave them all unset to build unsigned artifacts."
- exit 1
- fi
-
- echo "enabled=true" >> "$GITHUB_OUTPUT"
-
- - name: Prepare macOS signing and notarization credentials
- if: ${{ steps.macos_signing_mode.outputs.enabled == 'true' }}
- id: macos_signing
- run: |
- set -euo pipefail
-
- keychain_path="${RUNNER_TEMP}/gitcomet-signing.keychain-db"
- keychain_password="$(openssl rand -hex 24)"
- cert_path="${RUNNER_TEMP}/gitcomet-signing-cert.p12"
- api_key_path="${RUNNER_TEMP}/AuthKey_${MACOS_NOTARY_KEY_ID}.p8"
- default_keychain="$(security default-keychain -d user | tr -d '"' | xargs)"
-
- if base64 --help 2>&1 | grep -q -- '--decode'; then
- printf '%s' "$MACOS_SIGNING_CERT_BASE64" | base64 --decode > "$cert_path"
- else
- printf '%s' "$MACOS_SIGNING_CERT_BASE64" | base64 -D > "$cert_path"
- fi
-
- security create-keychain -p "$keychain_password" "$keychain_path"
- security set-keychain-settings -lut 21600 "$keychain_path"
- security unlock-keychain -p "$keychain_password" "$keychain_path"
- security import "$cert_path" \
- -k "$keychain_path" \
- -P "$MACOS_SIGNING_CERT_PASSWORD" \
- -T /usr/bin/codesign \
- -T /usr/bin/security
- security set-key-partition-list -S apple-tool:,apple: -s -k "$keychain_password" "$keychain_path"
- security default-keychain -d user -s "$keychain_path"
-
- security find-identity -v -p codesigning "$keychain_path"
-
- printf '%s' "$MACOS_NOTARY_API_KEY_P8" > "$api_key_path"
- chmod 600 "$api_key_path"
-
- echo "keychain_path=$keychain_path" >> "$GITHUB_OUTPUT"
- echo "api_key_path=$api_key_path" >> "$GITHUB_OUTPUT"
- echo "default_keychain=$default_keychain" >> "$GITHUB_OUTPUT"
-
- - name: Show macOS disk usage before packaging
- run: |
- set -euo pipefail
- df -h || true
- for path in target "$HOME/.cargo/registry" "$HOME/.cargo/git" dist "$RUNNER_TEMP"; do
- if [ -e "$path" ]; then
- du -sh "$path" || true
- else
- echo "missing: $path"
- fi
- done
-
- - name: Package macOS release assets
- env:
- GITCOMET_MACOS_PACKAGE_CLEAN_TARGET: "1"
- run: |
- set -euo pipefail
- package_args=(
- --version "${VERSION}"
- --arch "${ARCH}"
- --release
- --out-dir dist
- )
-
- if [ "${{ steps.macos_signing_mode.outputs.enabled }}" = "true" ]; then
- package_args+=(
- --codesign-identity "${MACOS_SIGNING_IDENTITY}"
- --codesign-keychain "${{ steps.macos_signing.outputs.keychain_path }}"
- )
- else
- echo "Building unsigned macOS artifacts because signing is not configured."
- fi
-
- scripts/package-macos.sh "${package_args[@]}"
-
- - name: Notarize and verify macOS artifacts
- if: ${{ steps.macos_signing_mode.outputs.enabled == 'true' }}
- run: |
- set -euo pipefail
- scripts/notarize-macos.sh \
- --version "${VERSION}" \
- --arch "${ARCH}" \
- --out-dir dist \
- --api-key "${{ steps.macos_signing.outputs.api_key_path }}" \
- --key-id "${MACOS_NOTARY_KEY_ID}" \
- --issuer "${MACOS_NOTARY_ISSUER_ID}"
-
- - name: Cleanup macOS signing keychain
- if: ${{ always() && steps.macos_signing_mode.outputs.enabled == 'true' }}
- env:
- KEYCHAIN_PATH: ${{ steps.macos_signing.outputs.keychain_path }}
- DEFAULT_KEYCHAIN_PATH: ${{ steps.macos_signing.outputs.default_keychain }}
- API_KEY_PATH: ${{ steps.macos_signing.outputs.api_key_path }}
- run: |
- set -euo pipefail
- if [ -n "${DEFAULT_KEYCHAIN_PATH:-}" ]; then
- security default-keychain -d user -s "$DEFAULT_KEYCHAIN_PATH" || true
- fi
- if [ -n "${KEYCHAIN_PATH:-}" ] && [ -f "$KEYCHAIN_PATH" ]; then
- security delete-keychain "$KEYCHAIN_PATH" || true
- fi
- if [ -n "${API_KEY_PATH:-}" ] && [ -f "$API_KEY_PATH" ]; then
- rm -f "$API_KEY_PATH"
- fi
-
- - name: Upload macOS artifacts
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
- with:
- name: macos-release-artifacts-${{ matrix.target_platform }}
- path: |
- dist/*.tar.gz
- dist/*.dmg
- if-no-files-found: error
- retention-days: 7
-
publish_release_assets:
name: Attach assets and checksums to GitHub release
runs-on: ubuntu-22.04
timeout-minutes: 30
- needs: [prepare, build_windows, build_linux, build_macos]
+ needs: [prepare, build_windows, build_linux]
env:
TAG: ${{ needs.prepare.outputs.tag }}
VERSION: ${{ needs.prepare.outputs.version }}
@@ -752,19 +550,12 @@ jobs:
path: dist/linux
merge-multiple: true
- - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
- with:
- pattern: macos-release-artifacts-*
- path: dist/macos
- merge-multiple: true
-
- name: Assemble release payload
run: |
set -euo pipefail
mkdir -p dist/release
find dist/windows -maxdepth 1 -type f -exec cp -f {} dist/release/ \;
find dist/linux -maxdepth 1 -type f -exec cp -f {} dist/release/ \;
- find dist/macos -maxdepth 1 -type f -exec cp -f {} dist/release/ \;
file_count="$(find dist/release -maxdepth 1 -type f | wc -l | tr -d '[:space:]')"
if [ "${file_count}" = "0" ]; then
echo "::error title=No release artifacts::No files were assembled into dist/release."
@@ -777,23 +568,17 @@ jobs:
set -euo pipefail
linux_arm_appimage="gitcomet-v${VERSION}-linux-arm64.AppImage"
linux_intel_appimage="gitcomet-v${VERSION}-linux-x86_64.AppImage"
- arm_dmg="gitcomet-v${VERSION}-macos-arm64.dmg"
- intel_dmg="gitcomet-v${VERSION}-macos-x86_64.dmg"
linux_arm_appimage_path="dist/release/${linux_arm_appimage}"
linux_intel_appimage_path="dist/release/${linux_intel_appimage}"
- arm_dmg_path="dist/release/${arm_dmg}"
- intel_dmg_path="dist/release/${intel_dmg}"
- if [ ! -f "${linux_arm_appimage_path}" ] || [ ! -f "${linux_intel_appimage_path}" ] || [ ! -f "${arm_dmg_path}" ] || [ ! -f "${intel_dmg_path}" ]; then
- echo "::error title=Missing release assets::Expected ${linux_arm_appimage}, ${linux_intel_appimage}, ${arm_dmg}, and ${intel_dmg} in dist/release."
+ if [ ! -f "${linux_arm_appimage_path}" ] || [ ! -f "${linux_intel_appimage_path}" ]; then
+ echo "::error title=Missing release assets::Expected ${linux_arm_appimage} and ${linux_intel_appimage} in dist/release."
exit 1
fi
scripts/generate-homebrew-cask.sh \
--version "${VERSION}" \
--github-repo "${GITHUB_REPOSITORY}" \
- --arm-dmg "${arm_dmg_path}" \
- --intel-dmg "${intel_dmg_path}" \
--linux-arm-appimage "${linux_arm_appimage_path}" \
--linux-intel-appimage "${linux_intel_appimage_path}" \
--output "dist/release/gitcomet.rb"
diff --git a/.github/workflows/cross-platform-tests.yml b/.github/workflows/cross-platform-tests.yml
index 09621e8ef..4436732d6 100644
--- a/.github/workflows/cross-platform-tests.yml
+++ b/.github/workflows/cross-platform-tests.yml
@@ -172,62 +172,6 @@ jobs:
- name: Run UI smoke test under selected profile
run: cargo test -p gitcomet-ui-gpui smoke_tests::smoke_view_renders_without_panicking -- --exact
- macos-tests:
- name: macOS Tests (${{ matrix.name }})
- runs-on: ${{ matrix.runs_on }}
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- include:
- - target_platform: aarch64-darwin
- name: macbook-m1 / macos-15
- runs_on: macos-15
- - target_platform: aarch64-darwin
- name: latest-macos / macos-26
- runs_on: macos-26
- - target_platform: x86_64-darwin
- name: intel (macos-15-intel)
- runs_on: macos-15-intel
- steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- - name: Show Git version
- run: git --version
- - name: Install Rust toolchain
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
- - name: Cache Rust artifacts
- uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
- - name: Show host target
- run: rustc -vV
- - name: Assert Apple Silicon runner
- if: matrix.target_platform == 'aarch64-darwin'
- run: |
- set -euo pipefail
- test "$(uname -m)" = "arm64"
- rust_host="$(rustc -vV | sed -n 's/^host: //p')"
- test "$rust_host" = "aarch64-apple-darwin"
- - name: Run headless test suite
- run: |
- cargo test --workspace \
- --exclude gitcomet-ui-gpui \
- $APP_FEATURES \
- --locked \
- --verbose
- - name: Gatekeeper and code-signing check (informational)
- run: |
- set -euo pipefail
- cargo_config_output="$(scripts/macos-cargo-config.sh "$(uname -m)" release)"
- set --
- if [[ -n "$cargo_config_output" ]]; then
- while IFS= read -r arg; do
- set -- "$@" "$arg"
- done <<<"$cargo_config_output"
- fi
- set -- "$@" -p gitcomet $APP_FEATURES --release --locked
- cargo build "$@"
- codesign --verify --verbose target/release/gitcomet || true
- spctl --assess --type execute --verbose target/release/gitcomet || true
-
windows-tests:
name: Windows Tests (${{ matrix.target_platform }})
runs-on: ${{ matrix.runs_on }}
diff --git a/.github/workflows/deployment-ci.yml b/.github/workflows/deployment-ci.yml
index a62162f71..ff49816d2 100644
--- a/.github/workflows/deployment-ci.yml
+++ b/.github/workflows/deployment-ci.yml
@@ -13,8 +13,6 @@ on:
- ".github/workflows/release-manual-main.yml"
- "scripts/update-aur.sh"
- "scripts/cargo-flatten-dupes.sh"
- - "scripts/package-macos.sh"
- - "scripts/macos-cargo-config.sh"
- "scripts/generate-homebrew-cask.sh"
- "scripts/build-apt-repo.sh"
- "scripts/windows/verify-signed-artifact.ps1"
@@ -30,8 +28,6 @@ on:
- ".github/workflows/release-manual-main.yml"
- "scripts/update-aur.sh"
- "scripts/cargo-flatten-dupes.sh"
- - "scripts/package-macos.sh"
- - "scripts/macos-cargo-config.sh"
- "scripts/generate-homebrew-cask.sh"
- "scripts/build-apt-repo.sh"
- "scripts/windows/verify-signed-artifact.ps1"
@@ -55,9 +51,6 @@ jobs:
run: |
bash -n scripts/cargo-flatten-dupes.sh
bash -n scripts/update-aur.sh
- bash -n scripts/package-macos.sh
- bash -n scripts/notarize-macos.sh
- bash -n scripts/macos-cargo-config.sh
bash -n scripts/generate-homebrew-cask.sh
bash -n scripts/build-apt-repo.sh
@@ -120,7 +113,8 @@ jobs:
grep -Fq 'dbus-launch --sh-syntax' .github/workflows/deploy-microsoft-store.yml
grep -Fq 'gnome-keyring-daemon --start --components=secrets' .github/workflows/deploy-microsoft-store.yml
grep -Fq 'libsecret-1-0' .github/workflows/deploy-microsoft-store.yml
- grep -Fq 'microsoft/microsoft-store-apppublisher@v1.4' .github/workflows/deploy-microsoft-store.yml
+ grep -Fq 'microsoft/microsoft-store-apppublisher@' .github/workflows/deploy-microsoft-store.yml
+ grep -Fq '# v1.4' .github/workflows/deploy-microsoft-store.yml
grep -Fq 'gh release view' .github/workflows/deploy-microsoft-store.yml
grep -Fq 'msstore submission update' .github/workflows/deploy-microsoft-store.yml
grep -Fq 'msstore submission updateMetadata' .github/workflows/deploy-microsoft-store.yml
@@ -158,29 +152,25 @@ jobs:
mkdir -p dist/deployment-ci
printf 'linux-arm-appimage-test' > dist/deployment-ci/gitcomet-v0.0.0-ci-linux-arm64.AppImage
printf 'linux-appimage-test' > dist/deployment-ci/gitcomet-v0.0.0-ci-linux-x86_64.AppImage
- printf 'arm64-dmg-test' > dist/deployment-ci/gitcomet-v0.0.0-ci-macos-arm64.dmg
- printf 'intel-dmg-test' > dist/deployment-ci/gitcomet-v0.0.0-ci-macos-x86_64.dmg
scripts/generate-homebrew-cask.sh \
--version "0.0.0-ci" \
--github-repo "Auto-Explore/GitComet" \
- --arm-dmg "dist/deployment-ci/gitcomet-v0.0.0-ci-macos-arm64.dmg" \
- --intel-dmg "dist/deployment-ci/gitcomet-v0.0.0-ci-macos-x86_64.dmg" \
--linux-arm-appimage "dist/deployment-ci/gitcomet-v0.0.0-ci-linux-arm64.AppImage" \
--linux-intel-appimage "dist/deployment-ci/gitcomet-v0.0.0-ci-linux-x86_64.AppImage" \
--output "dist/deployment-ci/gitcomet.rb"
ruby -c dist/deployment-ci/gitcomet.rb
grep -q 'cask "gitcomet" do' dist/deployment-ci/gitcomet.rb
- grep -q 'os macos: "macos", linux: "linux"' dist/deployment-ci/gitcomet.rb
+ grep -q 'os linux: "linux"' dist/deployment-ci/gitcomet.rb
grep -q 'on_linux do' dist/deployment-ci/gitcomet.rb
- grep -q 'on_macos do' dist/deployment-ci/gitcomet.rb
- grep -q 'app "GitComet.app"' dist/deployment-ci/gitcomet.rb
- grep -q 'binary "#{appdir}/GitComet.app/Contents/MacOS/gitcomet", target: "gitcomet"' dist/deployment-ci/gitcomet.rb
grep -q 'container type: :naked' dist/deployment-ci/gitcomet.rb
grep -q 'binary "gitcomet-v#{version}-linux-#{arch}.AppImage", target: "gitcomet"' dist/deployment-ci/gitcomet.rb
grep -q 'gitcomet-v#{version}-linux-#{arch}.AppImage' dist/deployment-ci/gitcomet.rb
- grep -q 'depends_on macos:' dist/deployment-ci/gitcomet.rb
+ if grep -qi 'macos\|\.dmg\|GitComet.app' dist/deployment-ci/gitcomet.rb; then
+ echo "::error title=Unexpected macOS cask content::The Homebrew cask must be Linux-only."
+ exit 1
+ fi
- name: Validate Homebrew tap publish detection
run: |
@@ -441,71 +431,3 @@ jobs:
-o Dir::Etc::sourceparts="${source_dir}" \
-o Dir::State::lists="${lists_dir}" \
| grep -q '0.0.0~ci1'
-
- macos-packaging-smoke:
- name: macOS packaging smoke (${{ matrix.target_platform }})
- runs-on: ${{ matrix.runs_on }}
- timeout-minutes: 90
- strategy:
- fail-fast: false
- matrix:
- include:
- - target_platform: aarch64-darwin
- arch: arm64
- runs_on: macos-latest
- - target_platform: x86_64-darwin
- arch: x86_64
- runs_on: macos-15-intel
- steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
-
- - name: Install Rust toolchain
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
-
- - name: Cache Rust artifacts
- uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
-
- - name: Build release binary
- run: |
- set -euo pipefail
- cargo_config_output="$(scripts/macos-cargo-config.sh "${{ matrix.arch }}" release)"
- set --
- if [[ -n "$cargo_config_output" ]]; then
- while IFS= read -r arg; do
- set -- "$@" "$arg"
- done <<<"$cargo_config_output"
- fi
- set -- "$@" -p gitcomet --release --locked --features ui-gpui,gix --bins
- cargo build "$@"
-
- - name: Package macOS artifacts
- run: |
- set -euo pipefail
- scripts/package-macos.sh \
- --version 0.0.0-ci \
- --arch "${{ matrix.arch }}" \
- --release \
- --no-build \
- --out-dir dist
-
- - name: Verify tarball contents
- run: |
- set -euo pipefail
- tarball="dist/gitcomet-v0.0.0-ci-macos-${{ matrix.arch }}.tar.gz"
- test -f "$tarball"
- tar -tzf "$tarball" | grep -q "GitComet.app/Contents/MacOS/gitcomet$"
-
- - name: Verify DMG launches binary
- run: |
- set -euo pipefail
- dmg="dist/gitcomet-v0.0.0-ci-macos-${{ matrix.arch }}.dmg"
- test -f "$dmg"
-
- mount_point="$(hdiutil attach "$dmg" | awk '/\/Volumes\// {print $3; exit}')"
- if [ -z "$mount_point" ]; then
- echo "Failed to determine DMG mount point." >&2
- exit 1
- fi
-
- "${mount_point}/GitComet.app/Contents/MacOS/gitcomet" --help >/dev/null
- hdiutil detach "$mount_point"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9dd755cce..47776ff2b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -71,21 +71,11 @@ This writes:
### Release packaging
-macOS packaging is handled by:
-
-```bash
-scripts/package-macos.sh --version 0.2.0 --arch arm64 --release
-scripts/package-macos.sh --version 0.2.0 --arch x86_64 --release
-```
-
-Use `--skip-dmg` when running in restricted/sandboxed environments where `hdiutil create` is unavailable.
-
The release workflow `.github/workflows/build-release-artifacts.yml` builds and publishes:
- Windows: portable ZIP + MSI
- Linux: tar.gz + AppImage + .deb
-- macOS: DMG + tar.gz for `arm64` and `x86_64`
-- Homebrew cask asset: `gitcomet.rb` (generated from macOS DMG artifacts and Linux AppImages plus their SHA256 values)
+- Homebrew cask asset: `gitcomet.rb` (Linux-only, generated from the Linux AppImages plus their SHA256 values)
### Homebrew deployment
diff --git a/README.md b/README.md
index 9bbb1971a..21323a413 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
GitComet is built for teams that want fast Git operations with local-first privacy, familiar workflows, and open source freedom.
-Available for Linux, Windows, and macOS.
+Available for Linux and Windows.
@@ -34,7 +34,7 @@ Install from the Microsoft Store:
-Homebrew (macOS / Linux)
+Homebrew (Linux)
App and `gitcomet` command from tap:
diff --git a/docs/macos-release-signing.md b/docs/macos-release-signing.md
deleted file mode 100644
index 9406392ee..000000000
--- a/docs/macos-release-signing.md
+++ /dev/null
@@ -1,158 +0,0 @@
-# macOS Release Signing
-
-This repository already contains the basic macOS release flow:
-
-- [`scripts/package-macos.sh`](../scripts/package-macos.sh) builds the macOS app bundle, signs the bundled executable and app when a signing identity is provided, and emits the macOS `.tar.gz` and `.dmg` artifacts.
-- [`scripts/notarize-macos.sh`](../scripts/notarize-macos.sh) submits the packaged DMG to Apple's notary service, staples the resulting ticket to the staged `.app` bundle and DMG, validates the stapled artifacts, and rebuilds the tarball so the archived `.app` bundle is current.
-- [`.github/workflows/build-release-artifacts.yml`](../.github/workflows/build-release-artifacts.yml) wires the same process into release CI.
-
-## What You Need
-
-For outside-the-App-Store distribution you need:
-
-1. An Apple Developer Program team.
-2. A `Developer ID Application` certificate with the private key available to `codesign`.
-3. A notarization credential for `notarytool`.
- Recommended in this repo: an App Store Connect API key.
- Local alternative: a stored `notarytool` keychain profile.
-
-Check whether the current shell can see a usable signing identity:
-
-```bash
-security find-identity -v -p codesigning
-```
-
-For release signing, this must show a valid `Developer ID Application: ...` identity. If it shows `0 valid identities found`, fix the certificate/private-key installation in Keychain Access before trying to sign.
-
-## Local Release Flow
-
-First, verify that macOS can see the correct signing identity:
-
-```bash
-security find-identity -v -p codesigning
-```
-
-You should see a valid `Developer ID Application: ...` entry.
-
-Build and sign on each native architecture you ship:
-
-```bash
-scripts/package-macos.sh \
- --version 0.2.0 \
- --arch arm64 \
- --release \
- --codesign-identity "Developer ID Application: Example, Inc. (TEAMID)"
-```
-
-Then notarize and staple the generated artifacts:
-
-```bash
-scripts/notarize-macos.sh \
- --version 0.2.0 \
- --arch arm64 \
- --keychain-profile gitcomet-notary
-```
-
-If you prefer direct API-key authentication instead of a stored profile:
-
-```bash
-scripts/notarize-macos.sh \
- --version 0.2.0 \
- --arch arm64 \
- --api-key /path/to/AuthKey_ABC1234567.p8 \
- --key-id ABC1234567 \
- --issuer 00000000-0000-0000-0000-000000000000
-```
-
-To create a local keychain profile up front:
-
-```bash
-xcrun notarytool store-credentials gitcomet-notary \
- --key /path/to/AuthKey_ABC1234567.p8 \
- --key-id ABC1234567 \
- --issuer 00000000-0000-0000-0000-000000000000
-```
-
-Repeat the same packaging and notarization flow on Intel macOS for `--arch x86_64`.
-
-## Local Verification Checklist
-
-The packaging and notarization scripts already run the important checks for you:
-
-- [`scripts/package-macos.sh`](../scripts/package-macos.sh) signs with Hardened Runtime and runs `codesign --verify` on the app and standalone binary.
-- [`scripts/notarize-macos.sh`](../scripts/notarize-macos.sh) submits the DMG with `notarytool`, staples the `.app` and `.dmg`, validates stapling, then runs `codesign --verify` and `spctl --assess`.
-
-After a successful local run, you can manually spot-check the finished artifacts:
-
-```bash
-codesign --verify --deep --strict --verbose=2 dist/stage/gitcomet-v0.2.0-macos-arm64/GitComet.app
-spctl --assess --type open --context context:primary-signature --verbose=4 dist/stage/gitcomet-v0.2.0-macos-arm64/GitComet.app
-spctl --assess --type open --context context:primary-signature --verbose=4 dist/gitcomet-v0.2.0-macos-arm64.dmg
-xcrun stapler validate dist/stage/gitcomet-v0.2.0-macos-arm64/GitComet.app
-xcrun stapler validate dist/gitcomet-v0.2.0-macos-arm64.dmg
-```
-
-If all of those commands return success, the signed macOS app bundle and DMG are in good shape.
-
-## GitHub Setup
-
-Use repository-level or organization-level GitHub Actions secrets for the macOS signing values used by the reusable release workflow.
-
-1. Export the `Developer ID Application` identity from Keychain Access as a `.p12`.
-2. Choose an export password for that `.p12`.
-3. Base64-encode the `.p12` as a single line:
-
-```bash
-base64 -i gitcomet-signing.p12 | tr -d '\n'
-```
-
-4. In GitHub, add these Actions secrets:
-
-- `MACOS_SIGNING_IDENTITY`
- The exact identity string, for example `Developer ID Application: Example, Inc. (TEAMID)`.
-- `MACOS_SIGNING_CERT_BASE64`
- The single-line base64 output of the exported `.p12`.
-- `MACOS_SIGNING_CERT_PASSWORD`
- The password you set when exporting the `.p12`.
-- `MACOS_NOTARY_KEY_ID`
- The App Store Connect API key ID.
-- `MACOS_NOTARY_ISSUER_ID`
- The App Store Connect issuer UUID.
-- `MACOS_NOTARY_API_KEY_P8`
- The full contents of the downloaded `AuthKey_.p8` file.
-
-5. Trigger the release workflow from [`release-manual-main.yml`](../.github/workflows/release-manual-main.yml) on `main`.
-
-## App Store Connect Notary Key
-
-This repository's CI uses an App Store Connect API key for notarization.
-
-Create a Team API key, download the `.p8` file once, and store the key material securely. The key ID and issuer ID become GitHub secrets, and the `.p8` contents become `MACOS_NOTARY_API_KEY_P8`.
-
-For local testing you can either:
-
-- use the same `.p8` file directly with [`scripts/notarize-macos.sh`](../scripts/notarize-macos.sh), or
-- save the credentials into your macOS keychain with `xcrun notarytool store-credentials`.
-
-## CI Secrets
-
-Release CI enables macOS signing only when all of these secrets are present:
-
-- `MACOS_SIGNING_IDENTITY`
-- `MACOS_SIGNING_CERT_BASE64`
-- `MACOS_SIGNING_CERT_PASSWORD`
-- `MACOS_NOTARY_KEY_ID`
-- `MACOS_NOTARY_ISSUER_ID`
-- `MACOS_NOTARY_API_KEY_P8`
-
-The workflow imports the `.p12` certificate into a temporary keychain, signs the macOS artifacts, notarizes the DMG, staples the `.app` and `.dmg`, and uploads the resulting release assets.
-
-## Artifact Expectations
-
-Treat the DMG as the canonical trusted macOS download.
-
-- The DMG is the notarized and stapled end-user artifact.
-- The tarball is rebuilt after stapling so the bundled `GitComet.app` is current.
-- The standalone `gitcomet` binary at the tarball root is only code-signed. Apple's notary service does not accept `.tar.gz` uploads directly, and that file is not inside the submitted DMG.
-
-If you want a separately trusted CLI-only macOS artifact, publish it in a notary-supported container such as a ZIP, DMG, or signed flat PKG and update downstream packaging accordingly.
diff --git a/scripts/generate-homebrew-cask.sh b/scripts/generate-homebrew-cask.sh
index 54c0261b5..c922a5b5c 100755
--- a/scripts/generate-homebrew-cask.sh
+++ b/scripts/generate-homebrew-cask.sh
@@ -6,20 +6,16 @@ usage() {
Usage: scripts/generate-homebrew-cask.sh \
--version VERSION \
--github-repo OWNER/REPO \
- --arm-dmg PATH \
- --intel-dmg PATH \
--linux-arm-appimage PATH \
--linux-intel-appimage PATH \
--output PATH
-Generates a Homebrew cask for GitComet from macOS DMG and Linux AppImage artifacts.
+Generates a Linux-only Homebrew cask for GitComet from the Linux AppImage artifacts.
USAGE
}
version=""
github_repo=""
-arm_dmg=""
-intel_dmg=""
linux_arm_appimage=""
linux_intel_appimage=""
out_path=""
@@ -34,14 +30,6 @@ while [[ $# -gt 0 ]]; do
github_repo="${2:-}"
shift 2
;;
- --arm-dmg)
- arm_dmg="${2:-}"
- shift 2
- ;;
- --intel-dmg)
- intel_dmg="${2:-}"
- shift 2
- ;;
--linux-arm-appimage)
linux_arm_appimage="${2:-}"
shift 2
@@ -66,7 +54,7 @@ while [[ $# -gt 0 ]]; do
esac
done
-if [[ -z "$version" || -z "$github_repo" || -z "$arm_dmg" || -z "$intel_dmg" || -z "$linux_arm_appimage" || -z "$linux_intel_appimage" || -z "$out_path" ]]; then
+if [[ -z "$version" || -z "$github_repo" || -z "$linux_arm_appimage" || -z "$linux_intel_appimage" || -z "$out_path" ]]; then
echo "All arguments are required." >&2
usage
exit 2
@@ -77,16 +65,6 @@ if ! [[ "$github_repo" =~ ^[^/]+/[^/]+$ ]]; then
exit 2
fi
-if [[ ! -f "$arm_dmg" ]]; then
- echo "arm DMG not found: $arm_dmg" >&2
- exit 1
-fi
-
-if [[ ! -f "$intel_dmg" ]]; then
- echo "intel DMG not found: $intel_dmg" >&2
- exit 1
-fi
-
if [[ ! -f "$linux_arm_appimage" ]]; then
echo "linux arm AppImage not found: $linux_arm_appimage" >&2
exit 1
@@ -111,8 +89,6 @@ sha256_file() {
exit 1
}
-arm_sha="$(sha256_file "$arm_dmg")"
-intel_sha="$(sha256_file "$intel_dmg")"
linux_arm_sha="$(sha256_file "$linux_arm_appimage")"
linux_intel_sha="$(sha256_file "$linux_intel_appimage")"
@@ -122,23 +98,7 @@ cat > "$out_path" < [release|debug]
-
-Prints extra Cargo CLI args for GitComet macOS builds, one argument per line.
-
-Environment:
- GITCOMET_MACOS_X86_RELEASE_LTO
- Release LTO override for Intel macOS builds.
- Supported: thin, fat, false, off, inherit
- Default: thin
-EOF
-}
-
-if [[ $# -lt 1 || $# -gt 2 ]]; then
- usage >&2
- exit 2
-fi
-
-arch="$1"
-mode="${2:-release}"
-
-case "$arch" in
- arm64|aarch64)
- arch="arm64"
- ;;
- x86_64|amd64)
- arch="x86_64"
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- *)
- echo "Unsupported macOS arch: $arch" >&2
- exit 2
- ;;
-esac
-
-case "$mode" in
- release|debug) ;;
- *)
- echo "Unsupported build mode: $mode" >&2
- exit 2
- ;;
-esac
-
-if [[ "$mode" != "release" || "$arch" != "x86_64" ]]; then
- exit 0
-fi
-
-lto_mode="${GITCOMET_MACOS_X86_RELEASE_LTO:-thin}"
-
-case "$lto_mode" in
- ""|inherit)
- ;;
- thin|fat)
- printf '%s\n' --config "profile.release.lto=\"${lto_mode}\""
- ;;
- false|off)
- printf '%s\n' --config "profile.release.lto=false"
- ;;
- *)
- echo "Unsupported GITCOMET_MACOS_X86_RELEASE_LTO value: $lto_mode" >&2
- exit 2
- ;;
-esac
diff --git a/scripts/notarize-macos.sh b/scripts/notarize-macos.sh
deleted file mode 100755
index 2a30b243f..000000000
--- a/scripts/notarize-macos.sh
+++ /dev/null
@@ -1,243 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-usage() {
- cat <<'USAGE'
-Usage: scripts/notarize-macos.sh --version VERSION [--arch arm64|x86_64] [--out-dir PATH] [--timeout DURATION] [--keychain PATH] (--keychain-profile PROFILE | --api-key PATH --key-id ID [--issuer UUID])
-
-Submits an already-packaged macOS DMG to Apple's notary service, staples the
-resulting ticket to the staged .app bundle and DMG, and refreshes the macOS
-tarball so the archived app bundle also carries the stapled ticket.
-
-Expected inputs:
- - /gitcomet-v-macos-.dmg
- - /stage/gitcomet-v-macos-/GitComet.app
-
-Authentication:
- --keychain-profile PROFILE
- Use credentials previously saved with:
- xcrun notarytool store-credentials PROFILE ...
-
- --api-key PATH --key-id ID [--issuer UUID]
- Use an App Store Connect API key directly. This matches the CI workflow.
-
-Notes:
- - The macOS tarball is rebuilt after stapling so the bundled .app is up to date.
- - The standalone gitcomet binary at the tarball root is only code-signed.
- Apple's notary service does not accept .tar.gz uploads directly.
-
-Defaults:
- --arch matches the host architecture
- --out-dir ./dist
- --timeout 2h
-USAGE
-}
-
-version=""
-arch=""
-out_dir="dist"
-wait_timeout="2h"
-keychain_profile=""
-keychain_path=""
-api_key_path=""
-api_key_id=""
-api_issuer=""
-
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --version)
- version="${2:-}"
- shift 2
- ;;
- --arch)
- arch="${2:-}"
- shift 2
- ;;
- --out-dir)
- out_dir="${2:-}"
- shift 2
- ;;
- --timeout)
- wait_timeout="${2:-}"
- shift 2
- ;;
- --keychain-profile)
- keychain_profile="${2:-}"
- shift 2
- ;;
- --keychain)
- keychain_path="${2:-}"
- shift 2
- ;;
- --api-key)
- api_key_path="${2:-}"
- shift 2
- ;;
- --key-id)
- api_key_id="${2:-}"
- shift 2
- ;;
- --issuer)
- api_issuer="${2:-}"
- shift 2
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- *)
- echo "Unknown arg: $1" >&2
- usage
- exit 2
- ;;
- esac
-done
-
-if [[ -z "$version" ]]; then
- echo "--version is required (e.g. --version 0.2.0)." >&2
- exit 2
-fi
-
-host_arch_raw="$(uname -m)"
-case "$host_arch_raw" in
- arm64|aarch64) host_arch="arm64" ;;
- x86_64|amd64) host_arch="x86_64" ;;
- *)
- echo "Unsupported machine architecture: $host_arch_raw" >&2
- exit 1
- ;;
-esac
-
-if [[ -z "$arch" ]]; then
- arch="$host_arch"
-fi
-
-if [[ "$arch" != "arm64" && "$arch" != "x86_64" ]]; then
- echo "Unsupported --arch '$arch'. Expected arm64 or x86_64." >&2
- exit 2
-fi
-
-if [[ -n "$keychain_profile" ]]; then
- if [[ -n "$api_key_path" || -n "$api_key_id" || -n "$api_issuer" ]]; then
- echo "Use either --keychain-profile or --api-key/--key-id/--issuer, not both." >&2
- exit 2
- fi
-else
- if [[ -z "$api_key_path" || -z "$api_key_id" ]]; then
- echo "Provide either --keychain-profile or --api-key PATH --key-id ID." >&2
- exit 2
- fi
- if [[ -n "$keychain_path" ]]; then
- echo "--keychain only applies with --keychain-profile." >&2
- exit 2
- fi
-fi
-
-if [[ "$out_dir" = /* ]]; then
- mkdir -p "$out_dir"
- out_abs="$(cd "$out_dir" && pwd)"
-else
- repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
- mkdir -p "${repo_root}/${out_dir}"
- out_abs="$(cd "${repo_root}/${out_dir}" && pwd)"
-fi
-
-release_root="gitcomet-v${version}-macos-${arch}"
-stage_root="${out_abs}/stage"
-release_dir="${stage_root}/${release_root}"
-app_path="${release_dir}/GitComet.app"
-app_binary="${app_path}/Contents/MacOS/gitcomet"
-tarball_path="${out_abs}/${release_root}.tar.gz"
-dmg_path="${out_abs}/${release_root}.dmg"
-standalone_binary="${release_dir}/gitcomet"
-
-for tool in xcrun codesign spctl tar; do
- if ! command -v "$tool" >/dev/null 2>&1; then
- echo "Required tool not found: $tool" >&2
- exit 1
- fi
-done
-
-if [[ ! -f "$dmg_path" ]]; then
- echo "DMG not found: $dmg_path" >&2
- exit 1
-fi
-
-if [[ ! -d "$app_path" ]]; then
- echo "App bundle not found: $app_path" >&2
- exit 1
-fi
-
-if [[ ! -x "$app_binary" ]]; then
- echo "App binary not found or not executable: $app_binary" >&2
- exit 1
-fi
-
-notary_args=()
-if [[ -n "$keychain_profile" ]]; then
- notary_args+=(--keychain-profile "$keychain_profile")
- if [[ -n "$keychain_path" ]]; then
- notary_args+=(--keychain "$keychain_path")
- fi
-else
- if [[ ! -f "$api_key_path" ]]; then
- echo "API key file not found: $api_key_path" >&2
- exit 1
- fi
- notary_args+=(
- --key "$api_key_path"
- --key-id "$api_key_id"
- )
- if [[ -n "$api_issuer" ]]; then
- notary_args+=(--issuer "$api_issuer")
- fi
-fi
-
-echo "Submitting $dmg_path for notarization"
-submit_log="$(mktemp -t gitcomet-notary-submit.XXXXXX)"
-set +e
-xcrun notarytool submit "$dmg_path" "${notary_args[@]}" --wait --timeout "$wait_timeout" 2>&1 | tee "$submit_log"
-submit_status=${PIPESTATUS[0]}
-set -e
-
-if [[ $submit_status -ne 0 ]]; then
- submission_id="$(sed -n 's/^ id: //p' "$submit_log" | tail -n1)"
- if [[ -n "$submission_id" ]]; then
- echo "Submission did not complete successfully; current status for $submission_id:"
- xcrun notarytool info "$submission_id" "${notary_args[@]}" || true
- else
- echo "Submission did not complete successfully and no submission id could be parsed from notarytool output." >&2
- fi
- echo "Apple's notary service can hold uploads for additional analysis. If this stays in progress for many hours, treat it as an Apple-side queue or account issue rather than a local packaging failure." >&2
- rm -f "$submit_log"
- exit "$submit_status"
-fi
-rm -f "$submit_log"
-
-echo "Stapling notarization tickets"
-xcrun stapler staple "$app_path"
-xcrun stapler staple "$dmg_path"
-xcrun stapler validate "$app_path"
-xcrun stapler validate "$dmg_path"
-
-if [[ -f "$tarball_path" ]]; then
- echo "Refreshing $tarball_path with stapled app bundle"
- rm -f "$tarball_path"
- tar -C "$stage_root" -czf "$tarball_path" "$release_root"
-fi
-
-echo "Verifying signed macOS artifacts"
-codesign --verify --deep --strict --verbose=2 "$app_path"
-if [[ -f "$standalone_binary" ]]; then
- codesign --verify --strict --verbose=2 "$standalone_binary"
-fi
-spctl --assess --type open --context context:primary-signature --verbose=4 "$app_path"
-spctl --assess --type execute --verbose=4 "$app_binary"
-spctl --assess --type open --context context:primary-signature --verbose=4 "$dmg_path"
-
-echo "Notarized macOS artifacts:"
-echo " $app_path"
-echo " $dmg_path"
-if [[ -f "$tarball_path" ]]; then
- echo " $tarball_path"
-fi
diff --git a/scripts/package-macos.sh b/scripts/package-macos.sh
deleted file mode 100755
index 14730738d..000000000
--- a/scripts/package-macos.sh
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-usage() {
- cat <<'USAGE'
-Usage: scripts/package-macos.sh --version VERSION [--arch arm64|x86_64] [--release|--debug] [--no-build] [--skip-dmg] [--out-dir PATH] [--codesign-identity NAME] [--codesign-keychain PATH]
-
-Builds a macOS app bundle and release artifacts:
- - gitcomet-v-macos-.tar.gz
- - gitcomet-v-macos-.dmg
-
-Defaults:
- --release, build if needed, output to ./dist
-
-Environment:
- GITCOMET_MACOS_X86_RELEASE_LTO=thin|fat|false|off|inherit
- Overrides release LTO for Intel macOS builds. Default: thin.
- GITCOMET_MACOS_PACKAGE_CLEAN_TARGET=1
- Deletes Cargo release build intermediates after staging artifacts. Intended
- for disk-constrained CI runners.
-USAGE
-}
-
-version=""
-arch=""
-mode="release"
-build=1
-create_dmg=1
-out_dir="dist"
-codesign_identity=""
-codesign_keychain=""
-
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --version)
- version="${2:-}"
- shift 2
- ;;
- --arch)
- arch="${2:-}"
- shift 2
- ;;
- --release)
- mode="release"
- shift
- ;;
- --debug)
- mode="debug"
- shift
- ;;
- --no-build)
- build=0
- shift
- ;;
- --skip-dmg)
- create_dmg=0
- shift
- ;;
- --out-dir)
- out_dir="${2:-}"
- shift 2
- ;;
- --codesign-identity)
- codesign_identity="${2:-}"
- shift 2
- ;;
- --codesign-keychain)
- codesign_keychain="${2:-}"
- shift 2
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- *)
- echo "Unknown arg: $1" >&2
- usage
- exit 2
- ;;
- esac
-done
-
-if [[ -z "$version" ]]; then
- echo "--version is required (e.g. --version 0.2.0)." >&2
- exit 2
-fi
-
-host_arch_raw="$(uname -m)"
-case "$host_arch_raw" in
- arm64|aarch64) host_arch="arm64" ;;
- x86_64|amd64) host_arch="x86_64" ;;
- *)
- echo "Unsupported machine architecture: $host_arch_raw" >&2
- exit 1
- ;;
-esac
-
-if [[ -z "$arch" ]]; then
- arch="$host_arch"
-fi
-
-if [[ "$arch" != "arm64" && "$arch" != "x86_64" ]]; then
- echo "Unsupported --arch '$arch'. Expected arm64 or x86_64." >&2
- exit 2
-fi
-
-if [[ "$arch" != "$host_arch" ]]; then
- echo "Requested --arch '$arch' does not match host architecture '$host_arch'." >&2
- echo "Use a native runner for each architecture." >&2
- exit 1
-fi
-
-repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-bin_src="${repo_root}/target/${mode}/gitcomet"
-
-if [[ $build -eq 1 && ! -x "$bin_src" ]]; then
- cargo_config_output=""
- cargo_config_output="$("${repo_root}/scripts/macos-cargo-config.sh" "$arch" "$mode")"
- (
- cd "$repo_root"
- set --
- if [[ -n "$cargo_config_output" ]]; then
- while IFS= read -r arg; do
- set -- "$@" "$arg"
- done <<<"$cargo_config_output"
- fi
- if [[ "$mode" == "release" ]]; then
- set -- "$@" --release
- fi
- set -- "$@" -p gitcomet --locked --features ui-gpui,gix --bin gitcomet
- cargo build "$@"
- )
-fi
-
-if [[ ! -x "$bin_src" ]]; then
- echo "Binary not found or not executable: $bin_src" >&2
- echo "Build first or omit --no-build." >&2
- exit 1
-fi
-
-if [[ "$out_dir" = /* ]]; then
- mkdir -p "$out_dir"
- out_abs="$(cd "$out_dir" && pwd)"
-else
- mkdir -p "${repo_root}/${out_dir}"
- out_abs="$(cd "${repo_root}/${out_dir}" && pwd)"
-fi
-
-show_disk_usage() {
- local label="$1"
- local cargo_home="${CARGO_HOME:-${HOME:-}/.cargo}"
-
- echo "macOS packaging disk usage ($label):"
- df -h || true
- for path in \
- "${repo_root}/target" \
- "${cargo_home}/registry" \
- "${cargo_home}/git" \
- "$out_abs" \
- "${RUNNER_TEMP:-}"
- do
- if [[ -z "$path" ]]; then
- continue
- fi
- if [[ -e "$path" ]]; then
- du -sh "$path" || true
- else
- echo "missing: $path"
- fi
- done
-}
-
-dmg_size_for_source() {
- local source_dir="$1"
- local source_kib
- source_kib="$(du -sk "$source_dir" | awk '{print $1}')"
-
- # hdiutil's inferred size for -srcfolder can be too small for signed app
- # bundles. Add 30% plus 64 MiB for filesystem metadata and small-file slack.
- echo $(( (source_kib * 13 / 10 + 65536 + 1023) / 1024 ))
-}
-
-clean_target_intermediates_for_ci() {
- if [[ "${GITCOMET_MACOS_PACKAGE_CLEAN_TARGET:-0}" != "1" ]]; then
- return
- fi
-
- local target_dir="${repo_root}/target/${mode}"
- if [[ ! -d "$target_dir" ]]; then
- return
- fi
-
- echo "Cleaning Cargo ${mode} build intermediates before creating macOS archives."
- for path in \
- "${target_dir}/.fingerprint" \
- "${target_dir}/build" \
- "${target_dir}/deps" \
- "${target_dir}/examples" \
- "${target_dir}/incremental"
- do
- if [[ -e "$path" ]]; then
- rm -rf "$path"
- fi
- done
-}
-
-stage_root="${out_abs}/stage"
-release_root="gitcomet-v${version}-macos-${arch}"
-release_dir="${stage_root}/${release_root}"
-app_bundle="${release_dir}/GitComet.app"
-contents_dir="${app_bundle}/Contents"
-macos_dir="${contents_dir}/MacOS"
-resources_dir="${contents_dir}/Resources"
-
-rm -rf "$release_dir"
-mkdir -p "$macos_dir" "$resources_dir"
-
-install -m755 "$bin_src" "${macos_dir}/gitcomet"
-install -m755 "$bin_src" "${release_dir}/gitcomet"
-install -m644 "${repo_root}/README.md" "${release_dir}/README.md"
-install -m644 "${repo_root}/LICENSE-AGPL-3.0" "${release_dir}/LICENSE-AGPL-3.0"
-install -m644 "${repo_root}/NOTICE" "${release_dir}/NOTICE"
-
-icon_png="${repo_root}/assets/gitcomet-512.png"
-icon_icns="${resources_dir}/GitComet.icns"
-
-if [[ ! -f "$icon_png" ]]; then
- echo "Missing macOS icon source: $icon_png" >&2
- exit 1
-fi
-if ! command -v sips >/dev/null 2>&1; then
- echo "sips is required to build the macOS app icon." >&2
- exit 1
-fi
-sips -s format icns "$icon_png" --out "$icon_icns" >/dev/null
-
-cat > "${contents_dir}/Info.plist" <
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleDisplayName
- GitComet
- CFBundleExecutable
- gitcomet
- CFBundleIdentifier
- ai.autoexplore.gitcomet
- CFBundleIconFile
- GitComet.icns
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- GitComet
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${version}
- CFBundleVersion
- ${version}
- LSMinimumSystemVersion
- 13.0
- NSHighResolutionCapable
-
-
-
-PLIST
-
-if [[ -n "$codesign_identity" ]]; then
- if ! command -v codesign >/dev/null 2>&1; then
- echo "codesign is required when --codesign-identity is set." >&2
- exit 1
- fi
-
- sign_args=(--force --timestamp --options runtime --sign "$codesign_identity")
- if [[ -n "$codesign_keychain" ]]; then
- sign_args+=(--keychain "$codesign_keychain")
- fi
-
- echo "Signing macOS artifacts with identity: $codesign_identity"
- codesign "${sign_args[@]}" "${macos_dir}/gitcomet"
- codesign "${sign_args[@]}" "${release_dir}/gitcomet"
- codesign "${sign_args[@]}" "$app_bundle"
-
- codesign --verify --strict --verbose=2 "${release_dir}/gitcomet"
- codesign --verify --strict --verbose=2 "$app_bundle"
-fi
-
-if [[ "${GITCOMET_MACOS_PACKAGE_CLEAN_TARGET:-0}" == "1" ]]; then
- show_disk_usage "before target cleanup"
- clean_target_intermediates_for_ci
- show_disk_usage "after target cleanup"
-fi
-
-# Create a deterministic tarball root directory per version/arch.
-tarball_path="${out_abs}/${release_root}.tar.gz"
-rm -f "$tarball_path"
-tar -C "$stage_root" -czf "$tarball_path" "$release_root"
-
-dmg_path="${out_abs}/${release_root}.dmg"
-if [[ $create_dmg -eq 1 ]]; then
- # Build a drag-and-drop DMG with an /Applications shortcut.
- dmg_stage="${out_abs}/dmg-stage-${arch}"
- rm -rf "$dmg_stage"
- mkdir -p "$dmg_stage"
- cp -R "$app_bundle" "${dmg_stage}/GitComet.app"
- ln -s /Applications "${dmg_stage}/Applications"
- dmg_size_mib="$(dmg_size_for_source "$dmg_stage")"
- echo "Creating macOS DMG with ${dmg_size_mib} MiB filesystem."
-
- # Preserve compatibility with older macOS tooling.
- rm -f "$dmg_path"
- hdiutil create \
- -volname "GitComet" \
- -srcfolder "$dmg_stage" \
- -fs HFS+ \
- -size "${dmg_size_mib}m" \
- -ov \
- -format UDZO \
- "$dmg_path" >/dev/null
-
- rm -rf "$dmg_stage"
-
- if [[ -n "$codesign_identity" ]]; then
- codesign "${sign_args[@]}" "$dmg_path"
- codesign --verify --strict --verbose=2 "$dmg_path"
- fi
-fi
-
-echo "Packaged macOS artifacts:"
-echo " $tarball_path"
-if [[ $create_dmg -eq 1 ]]; then
- echo " $dmg_path"
-else
- echo " (skipped DMG creation via --skip-dmg)"
-fi