From baee138b97bb53c7b53fa4e0c21caa1e6f7c4a00 Mon Sep 17 00:00:00 2001 From: Charlie <144284500+Charlie284@users.noreply.github.com> Date: Wed, 29 Jul 2026 21:51:41 -0500 Subject: [PATCH] Add DMG release artifacts --- .github/workflows/ci.yml | 13 ++++--- .github/workflows/release.yml | 26 +++++++------- CHANGELOG.md | 6 ++++ README.md | 6 ++-- RELEASE.md | 2 +- Scripts/package-unsigned-release.sh | 54 +++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 21 deletions(-) create mode 100755 Scripts/package-unsigned-release.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48d2580..5b97dca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,16 +62,19 @@ jobs: - name: Package unsigned app run: | - mkdir -p build/artifacts - ditto \ - -c -k --sequesterRsrc --keepParent \ + ./Scripts/package-unsigned-release.sh \ build/DerivedData/Build/Products/Release/Startle.app \ - build/artifacts/Startle-macOS-unsigned.zip + build/artifacts \ + Startle-macOS-unsigned - name: Upload unsigned app uses: actions/upload-artifact@v7 with: name: Startle-${{ github.sha }}-macOS-unsigned - path: build/artifacts/Startle-macOS-unsigned.zip + path: | + build/artifacts/Startle-macOS-unsigned.dmg + build/artifacts/Startle-macOS-unsigned.dmg.sha256 + build/artifacts/Startle-macOS-unsigned.zip + build/artifacts/Startle-macOS-unsigned.zip.sha256 if-no-files-found: error retention-days: 14 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 23946c0..1e6f0c1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -70,34 +70,34 @@ jobs: - name: Package release assets run: | release_version=${GITHUB_REF_NAME#v} - archive_name="Startle-${release_version}-macOS-unsigned.zip" - mkdir -p dist - ditto \ - -c -k --sequesterRsrc --keepParent \ + ./Scripts/package-unsigned-release.sh \ build/DerivedData/Build/Products/Release/Startle.app \ - "dist/$archive_name" - cd dist - shasum -a 256 "$archive_name" > "$archive_name.sha256" + dist \ + "Startle-${release_version}-macOS-unsigned" - name: Publish prerelease env: GH_TOKEN: ${{ github.token }} run: | release_version=${GITHUB_REF_NAME#v} - archive_name="Startle-${release_version}-macOS-unsigned.zip" - release_notes="Unsigned preview build. macOS will identify this app as coming from an unidentified developer. Review the installation notes in the repository before opening it." + asset_name="Startle-${release_version}-macOS-unsigned" + release_notes="Unsigned preview build. Download the DMG, drag Startle to Applications, then review the first-launch instructions in the repository. macOS will identify this app as coming from an unidentified developer." if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then gh release upload \ "$GITHUB_REF_NAME" \ - "dist/$archive_name" \ - "dist/$archive_name.sha256" \ + "dist/$asset_name.dmg" \ + "dist/$asset_name.dmg.sha256" \ + "dist/$asset_name.zip" \ + "dist/$asset_name.zip.sha256" \ --clobber else gh release create \ "$GITHUB_REF_NAME" \ - "dist/$archive_name" \ - "dist/$archive_name.sha256" \ + "dist/$asset_name.dmg" \ + "dist/$asset_name.dmg.sha256" \ + "dist/$asset_name.zip" \ + "dist/$asset_name.zip.sha256" \ --verify-tag \ --prerelease \ --title "Startle $GITHUB_REF_NAME (unsigned)" \ diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a081f3..a569d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes will be documented here. The project follows [Semantic Versi ## Unreleased +## 1.0.1 - 2026-07-29 + +### Added + +- Compressed DMG release downloads with an Applications shortcut. + ## 1.0.0 - 2026-07-29 ### Added diff --git a/README.md b/README.md index 0d5ac79..bc30075 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,11 @@ The Xcode target enables App Sandbox and Hardened Runtime. Distribution still re ## Preview downloads -Version tags matching `v*` build a universal macOS app and publish it as a GitHub prerelease with a SHA-256 checksum. These downloads are unsigned because the project does not currently use a paid Apple Developer identity. +Version tags matching `v*` build a universal macOS app and publish it as a GitHub prerelease. The DMG is the recommended download; a ZIP is also available as a fallback. Each asset has a SHA-256 checksum. These downloads are unsigned because the project does not currently use a paid Apple Developer identity. -macOS will identify an unsigned download as coming from an unidentified developer. After verifying the checksum, extract the ZIP and use **Control-click → Open** for the first launch. Do not treat an unsigned preview as equivalent to a Developer ID-signed and notarized release. +[Download an unsigned preview](https://github.com/Charlie284/Startle/releases) + +After verifying the checksum, open the DMG and drag **Startle** to the **Applications** shortcut. macOS will identify the app as coming from an unidentified developer, so use **Control-click → Open** in Applications for the first launch. Do not treat an unsigned preview as equivalent to a Developer ID-signed and notarized release. ## Architecture diff --git a/RELEASE.md b/RELEASE.md index a2f13b0..a646b19 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -4,7 +4,7 @@ Startle is not ready to distribute merely because `swift test` passes. A release ## Unsigned preview releases -Pushing a version tag such as `v1.0.0` runs `.github/workflows/release.yml`. The workflow repeats the source and Xcode tests, builds a universal macOS app, verifies the unsigned bundle, and publishes a prerelease ZIP with its SHA-256 checksum. +Pushing a version tag such as `v1.0.1` runs `.github/workflows/release.yml`. The workflow repeats the source and Xcode tests, builds a universal macOS app, verifies the unsigned bundle, and publishes a compressed DMG and fallback ZIP with SHA-256 checksums. The DMG contains the app and an Applications shortcut. Unsigned previews are intended for development and evaluation. Gatekeeper will identify them as coming from an unidentified developer, and they do not satisfy the production release process below. diff --git a/Scripts/package-unsigned-release.sh b/Scripts/package-unsigned-release.sh new file mode 100755 index 0000000..c77144f --- /dev/null +++ b/Scripts/package-unsigned-release.sh @@ -0,0 +1,54 @@ +#!/bin/sh +set -eu + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 /path/to/Startle.app /path/to/output asset-name" >&2 + exit 64 +fi + +app_path=$1 +output_dir=$2 +asset_name=$3 + +if [ ! -d "$app_path" ] || [ ! -f "$app_path/Contents/Info.plist" ]; then + echo "Not a macOS application bundle: $app_path" >&2 + exit 66 +fi + +case "$asset_name" in + */* | "") + echo "The asset name must be a non-empty file name without slashes." >&2 + exit 64 + ;; +esac + +mkdir -p "$output_dir" +output_dir=$(CDPATH= cd "$output_dir" && pwd) +archive_path="$output_dir/$asset_name.zip" +dmg_path="$output_dir/$asset_name.dmg" +staging_root=$(mktemp -d "${TMPDIR:-/tmp}/startle-release.XXXXXX") +staging_dir="$staging_root/Startle" + +cleanup() { + rm -rf "$staging_root" +} +trap cleanup EXIT HUP INT TERM + +mkdir -p "$staging_dir" +ditto "$app_path" "$staging_dir/Startle.app" +ln -s /Applications "$staging_dir/Applications" + +ditto -c -k --sequesterRsrc --keepParent "$app_path" "$archive_path" +hdiutil create \ + -volname Startle \ + -srcfolder "$staging_dir" \ + -ov \ + -format UDZO \ + "$dmg_path" + +for asset_path in "$archive_path" "$dmg_path"; do + shasum -a 256 "$asset_path" > "$asset_path.sha256" +done + +echo "Packaged $archive_path" +echo "Packaged $dmg_path"