Skip to content

Fix Sparkle key generation command syntax #18

Fix Sparkle key generation command syntax

Fix Sparkle key generation command syntax #18

name: Build and Release A6Cutter
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., v1.0.0)'
required: false
type: string
jobs:
build-and-release:
runs-on: macos-latest
permissions:
contents: write
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Cache Xcode DerivedData
uses: actions/cache@v4
with:
path: ~/Library/Developer/Xcode/DerivedData
key: ${{ runner.os }}-deriveddata-${{ hashFiles('**/*.swift') }}
restore-keys: |
${{ runner.os }}-deriveddata-
- name: Get version and hash info
id: version_info
run: |
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ -n "${{ github.event.inputs.version }}" ]]; then
VERSION=${{ github.event.inputs.version }}
else
VERSION=dev-$(date +%Y%m%d-%H%M%S)
fi
# Get git hash
GIT_HASH=$(git rev-parse HEAD)
GIT_HASH_SHORT=$(git rev-parse --short HEAD)
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_OUTPUT
echo "GIT_HASH_SHORT=$GIT_HASH_SHORT" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
echo "Git Hash: $GIT_HASH_SHORT"
- name: Update Info.plist with version and hash
run: |
# Find the Info.plist file
INFO_PLIST=$(find . -name "Info.plist" -path "*/A6Cutter.app/Contents/Info.plist" | head -1)
if [ -z "$INFO_PLIST" ]; then
# If not found, create a temporary one for build
INFO_PLIST="A6Cutter/Info.plist"
mkdir -p A6Cutter
cat > "$INFO_PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PList 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>${{ steps.version_info.outputs.VERSION }}</string>
<key>CFBundleVersion</key>
<string>${{ github.run_number }}</string>
<key>GitHash</key>
<string>${{ steps.version_info.outputs.GIT_HASH }}</string>
</dict>
</plist>
EOF
fi
# Update existing Info.plist or create new one
if [ -f "$INFO_PLIST" ]; then
# Use plutil to update the plist
plutil -replace CFBundleShortVersionString -string "${{ steps.version_info.outputs.VERSION }}" "$INFO_PLIST"
plutil -replace CFBundleVersion -string "${{ github.run_number }}" "$INFO_PLIST"
plutil -replace GitHash -string "${{ steps.version_info.outputs.GIT_HASH }}" "$INFO_PLIST"
else
# Create new Info.plist
cat > "$INFO_PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD Plist 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>${{ steps.version_info.outputs.VERSION }}</string>
<key>CFBundleVersion</key>
<string>${{ github.run_number }}</string>
<key>GitHash</key>
<string>${{ steps.version_info.outputs.GIT_HASH }}</string>
</dict>
</plist>
EOF
fi
echo "Updated Info.plist with version ${{ steps.version_info.outputs.VERSION }} and hash ${{ steps.version_info.outputs.GIT_HASH_SHORT }}"
- name: Download Sparkle tools
run: |
echo "📦 Downloading Sparkle tools..."
# Try to get the latest Sparkle release URL with better parsing
SPARKLE_URL=$(curl -s https://api.github.com/repos/sparkle-project/Sparkle/releases/latest | jq -r '.assets[] | select(.name | endswith(".tar.xz")) | .browser_download_url' | head -1)
# Fallback to a known working version if API fails
if [ -z "$SPARKLE_URL" ] || [ "$SPARKLE_URL" = "null" ]; then
echo "Using fallback URL for Sparkle 2.6.0"
SPARKLE_URL="https://github.com/sparkle-project/Sparkle/releases/download/2.6.0/Sparkle-2.6.0.tar.xz"
fi
echo "Downloading from: $SPARKLE_URL"
curl -L -o sparkle.tar.xz "$SPARKLE_URL"
# Verify the download
if [ ! -f "sparkle.tar.xz" ] || [ ! -s "sparkle.tar.xz" ]; then
echo "❌ Failed to download Sparkle tools"
exit 1
fi
echo "✅ Downloaded $(ls -lh sparkle.tar.xz | awk '{print $5}')"
# Extract with verbose output for debugging
echo "🔍 Extracting Sparkle tools..."
tar -xvf sparkle.tar.xz
# List contents to see what was extracted
echo "📁 Contents after extraction:"
ls -la
# Check if bin directory exists in current directory (Sparkle source extraction)
if [ -d "./bin" ]; then
echo "✅ Found Sparkle bin directory in current directory"
SPARKLE_BIN_DIR="./bin"
else
# Look for any directory with bin subdirectory
SPARKLE_DIR=$(find . -maxdepth 2 -name "bin" -type d | head -1 | dirname)
if [ -z "$SPARKLE_DIR" ]; then
echo "🔍 Looking for any extracted directories..."
find . -maxdepth 1 -type d -name "*" | grep -v "^\.$"
echo "❌ Failed to find Sparkle bin directory after extraction"
exit 1
fi
echo "✅ Found Sparkle directory: $SPARKLE_DIR"
SPARKLE_BIN_DIR="$SPARKLE_DIR/bin"
fi
echo "📁 Contents of $SPARKLE_BIN_DIR:"
ls -la "$SPARKLE_BIN_DIR"
# Check if bin directory exists and has tools
if [ ! -d "$SPARKLE_BIN_DIR" ]; then
echo "❌ No bin directory found at $SPARKLE_BIN_DIR"
echo "📁 Available directories:"
find . -type d -name "*bin*"
exit 1
fi
# Check if there are any executable files in bin (macOS compatible)
EXECUTABLE_FILES=$(find "$SPARKLE_BIN_DIR" -type f -perm +111 2>/dev/null || find "$SPARKLE_BIN_DIR" -type f -perm +x 2>/dev/null || ls -la "$SPARKLE_BIN_DIR" | grep -E '^-rwx' | wc -l)
if [ "$EXECUTABLE_FILES" -eq 0 ]; then
echo "❌ No executable files found in $SPARKLE_BIN_DIR"
echo "📁 Contents:"
ls -la "$SPARKLE_BIN_DIR"
exit 1
fi
echo "✅ Found $EXECUTABLE_FILES executable files in $SPARKLE_BIN_DIR"
# Check if we're already in the right directory
if [ "$SPARKLE_BIN_DIR" = "./bin" ]; then
echo "✅ Sparkle tools already in correct location: ./bin"
chmod +x ./bin/*
else
echo "📁 Copying tools from $SPARKLE_BIN_DIR to ./bin"
chmod +x "$SPARKLE_BIN_DIR"/*
mkdir -p bin
cp "$SPARKLE_BIN_DIR"/* ./bin/
fi
echo "✅ Sparkle tools ready in ./bin/"
echo "📁 Final bin contents:"
ls -la ./bin/
- name: Generate Sparkle keys (if not exist)
run: |
if [ ! -f "keys/ed25519_private_key.pem" ]; then
echo "🔑 Generating Sparkle keys..."
mkdir -p keys
# List available tools for debugging
echo "📁 Available Sparkle tools:"
ls -la ./bin/
# Use generate_keys tool with correct syntax
./bin/generate_keys -x keys/ed25519_private_key.pem
# Extract public key from private key
./bin/generate_keys -x keys/ed25519_private_key.pem -p > keys/ed25519_public_key.pem
PUBLIC_KEY=$(grep -v "BEGIN\|END" keys/ed25519_public_key.pem | tr -d '\n')
echo "Public key: $PUBLIC_KEY"
# Update Info.plist with public key
plutil -replace SUPublicEDSAKey -string "$PUBLIC_KEY" A6Cutter/Info.plist
else
echo "🔑 Sparkle keys already exist"
fi
- name: Build A6Cutter
run: |
xcodebuild -scheme A6Cutter -configuration Release -destination "platform=macOS" clean build
- name: Create DMG
run: |
# Create DMG directory structure
mkdir -p dmg/A6Cutter.app
# Copy the built app
cp -R /Users/runner/Library/Developer/Xcode/DerivedData/A6Cutter-*/Build/Products/Release/A6Cutter.app dmg/
# Create DMG
hdiutil create -volname "A6Cutter" -srcfolder dmg -ov -format UDZO A6Cutter.dmg
- name: Generate appcast.xml
run: |
echo "📡 Generating appcast.xml..."
mkdir -p releases
cp A6Cutter.dmg releases/A6Cutter-${{ steps.version_info.outputs.VERSION }}.dmg
# Generate appcast.xml
./bin/generate_appcast \
--ed-key-file keys/ed25519_private_key.pem \
--download-url-prefix "https://github.com/devopsmariocom/A6Cutter/releases/download/" \
--full-release-notes-url "https://github.com/devopsmariocom/A6Cutter/releases" \
releases/
# Move appcast.xml to root
if [ -f "releases/appcast.xml" ]; then
mv releases/appcast.xml .
echo "✅ appcast.xml generated successfully!"
else
echo "❌ Failed to generate appcast.xml"
exit 1
fi
- name: Get version from tag
id: get_version
run: |
# Use the version from the previous step
echo "VERSION=${{ steps.version_info.outputs.VERSION }}" >> $GITHUB_OUTPUT
- name: Generate Release Notes
id: release_notes
run: |
# Get the previous tag
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
# Generate changelog from commits
if [ -n "$PREVIOUS_TAG" ]; then
COMMITS=$(git log --pretty=format:"- %s" $PREVIOUS_TAG..HEAD)
else
COMMITS=$(git log --pretty=format:"- %s" --max-count=20)
fi
# Create release notes
cat > release_notes.md << EOF
## What's New in ${{ steps.get_version.outputs.VERSION }}
### Changes
$COMMITS
### Installation
1. Download the DMG file below
2. Open the DMG and drag A6Cutter to Applications
3. Right-click and select "Open" if you get security warnings
### System Requirements
- macOS 14.0 or later
- Apple Silicon or Intel processor
### Features
- PDF cutting into A6-sized tiles
- Customizable settings with live preview
- Page rotation and skipping
- Preset management
- Direct printing integration
EOF
# Output the release notes
echo "RELEASE_NOTES<<EOF" >> $GITHUB_OUTPUT
cat release_notes.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create Release
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
uses: softprops/action-gh-release@v2
with:
files: |
A6Cutter.dmg
appcast.xml
name: A6Cutter ${{ steps.get_version.outputs.VERSION }}
body: ${{ steps.release_notes.outputs.RELEASE_NOTES }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Build Artifacts
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: A6Cutter-${{ steps.get_version.outputs.VERSION }}
path: A6Cutter.dmg