Skip to content

fix: free disk space after build before DMG creation #4

fix: free disk space after build before DMG creation

fix: free disk space after build before DMG creation #4

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
env:
APP_NAME: Transcripted
SCHEME: Transcripted
BUNDLE_ID: com.transcripted.app
jobs:
build-and-release:
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Select Xcode 26.3
run: sudo xcode-select --switch /Applications/Xcode_26.3.app/Contents/Developer
- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
- name: Install Apple certificate
env:
DEVELOPER_ID_CERT: ${{ secrets.DEVELOPER_ID_CERT }}
DEVELOPER_ID_PASSWORD: ${{ secrets.DEVELOPER_ID_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ github.run_id }}
run: |
# Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
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
CERT_PATH=$RUNNER_TEMP/certificate.p12
echo -n "$DEVELOPER_ID_CERT" | base64 --decode -o $CERT_PATH
security import $CERT_PATH -P "$DEVELOPER_ID_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Build Release
run: |
xcodebuild -project ${{ env.APP_NAME }}.xcodeproj \
-scheme ${{ env.SCHEME }} \
-configuration Release \
-derivedDataPath build \
-destination "generic/platform=macOS" \
ARCHS=arm64 \
ONLY_ACTIVE_ARCH=NO \
CODE_SIGN_STYLE=Manual \
CODE_SIGN_IDENTITY="Developer ID Application" \
DEVELOPMENT_TEAM=${{ secrets.APPLE_TEAM_ID }} \
MARKETING_VERSION=${{ steps.version.outputs.version }} \
CURRENT_PROJECT_VERSION=${{ steps.version.outputs.version }}
- name: Locate app bundle
id: app
run: |
APP_PATH=$(find build/Build/Products/Release -name "*.app" -maxdepth 1 | head -1)
echo "path=$APP_PATH" >> $GITHUB_OUTPUT
echo "Found app at: $APP_PATH"
- name: Free disk space
run: |
echo "Disk before cleanup:"
df -h /
# Remove build intermediates (keep only the final .app)
rm -rf build/Build/Intermediates*
rm -rf build/SourcePackages
rm -rf ~/Library/Developer/Xcode/DerivedData
rm -rf ~/Library/Caches/org.swift.swiftpm
echo "Disk after cleanup:"
df -h /
- name: Create ZIP for Sparkle
run: |
ditto -c -k --sequesterRsrc --keepParent \
"${{ steps.app.outputs.path }}" \
"${{ env.APP_NAME }}.zip"
- name: Create DMG
run: |
chmod +x scripts/create-dmg.sh
./scripts/create-dmg.sh "${{ steps.app.outputs.path }}" .
- name: Notarize DMG
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
chmod +x scripts/notarize.sh
DMG_FILE=$(ls *.dmg | head -1)
./scripts/notarize.sh "$DMG_FILE" "$APPLE_ID" "$APPLE_TEAM_ID" "$APPLE_APP_PASSWORD"
- name: Notarize ZIP
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
chmod +x scripts/notarize.sh
./scripts/notarize.sh "${{ env.APP_NAME }}.zip" "$APPLE_ID" "$APPLE_TEAM_ID" "$APPLE_APP_PASSWORD"
- name: Sign update with Sparkle EdDSA
env:
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
run: |
# Download Sparkle tools
SPARKLE_VERSION="2.8.0"
curl -sL "https://github.com/sparkle-project/Sparkle/releases/download/${SPARKLE_VERSION}/Sparkle-${SPARKLE_VERSION}.tar.xz" | tar xJ -C /tmp/sparkle
# Sign the ZIP and capture signature + length
SIGN_OUTPUT=$(echo "$SPARKLE_PRIVATE_KEY" | /tmp/sparkle/bin/sign_update "${{ env.APP_NAME }}.zip" --ed-key-file -)
echo "sparkle_signature=$(echo "$SIGN_OUTPUT" | grep 'sparkle:edSignature' | sed 's/.*"\(.*\)".*/\1/')" >> $GITHUB_OUTPUT
echo "sparkle_length=$(wc -c < "${{ env.APP_NAME }}.zip" | tr -d ' ')" >> $GITHUB_OUTPUT
id: sparkle
- name: Update appcast on website
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
DATE=$(date -u +"%a, %d %b %Y %H:%M:%S %z")
ZIP_URL="https://github.com/${{ github.repository }}/releases/download/v${VERSION}/${{ env.APP_NAME }}.zip"
SIGNATURE="${{ steps.sparkle.outputs.sparkle_signature }}"
LENGTH="${{ steps.sparkle.outputs.sparkle_length }}"
# Clone the webapp repo
git clone https://x-access-token:${GH_TOKEN}@github.com/r3dbars/transcripted-webapp.git /tmp/webapp
# Update appcast.xml with new release item
python3 << 'PYEOF'
import os
version = os.environ["VERSION"]
date = os.environ["DATE"]
zip_url = os.environ["ZIP_URL"]
sig = os.environ["SIGNATURE"]
length = os.environ["LENGTH"]
item = f""" <item>
<title>Version {version}</title>
<pubDate>{date}</pubDate>
<sparkle:version>{version}</sparkle:version>
<sparkle:shortVersionString>{version}</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.2</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>What's New in {version}</h2><p>See full release notes on GitHub.</p>]]></description>
<enclosure
url="{zip_url}"
sparkle:edSignature="{sig}"
length="{length}"
type="application/octet-stream" />
</item>"""
appcast = open("/tmp/webapp/public/appcast.xml").read()
appcast = appcast.replace("</channel>", item + "\n </channel>")
open("/tmp/webapp/public/appcast.xml", "w").write(appcast)
print(f"Updated appcast.xml with v{version}")
PYEOF
# Copy DMG to webapp for direct download
DMG_FILE=$(ls $GITHUB_WORKSPACE/*.dmg | head -1)
cp "$DMG_FILE" /tmp/webapp/public/download/Transcripted.dmg
# Commit and push to webapp repo (triggers Cloudflare deploy)
cd /tmp/webapp
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add public/appcast.xml public/download/Transcripted.dmg
git commit -m "release: v${VERSION} — update appcast + DMG"
git push origin main
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
DMG_FILE=$(ls *.dmg | head -1)
gh release create "v${VERSION}" \
--title "Transcripted v${VERSION}" \
--generate-notes \
"$DMG_FILE" \
"${{ env.APP_NAME }}.zip"
- name: Cleanup keychain
if: always()
run: security delete-keychain $RUNNER_TEMP/app-signing.keychain-db 2>/dev/null || true