Skip to content

prepare changelog and docs for release 1.8.0 #631

prepare changelog and docs for release 1.8.0

prepare changelog and docs for release 1.8.0 #631

name: Build macOS Universal
on:
push:
branches:
- main
tags:
- "*"
pull_request:
branches:
- "**"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
version:
name: Resolve Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set-version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Checkout raygeo source
uses: actions/checkout@v6
with:
repository: barebaric/raygeo
path: external/raygeo
- name: Set Version
id: set-version
shell: bash
run: |
if [[ "${{ github.ref_type }}" == "tag" ]]; then
VERSION=${{ github.ref_name }}
else
SHORT_SHA=$(git rev-parse --short HEAD)
if git describe --tags --abbrev=0 >/dev/null 2>&1; then
BASE_VERSION=$(git describe --tags --abbrev=0)
else
BASE_VERSION="v0.0.0"
fi
VERSION="${BASE_VERSION}-${SHORT_SHA}"
fi
if [ -z "$VERSION" ]; then
echo "Error: No git version number found"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Version: $VERSION"
build-intel:
name: Build macOS Intel Bundle
needs: version
runs-on: macos-26-intel
env:
VERSION: ${{ needs.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Checkout raygeo source
uses: actions/checkout@v6
with:
repository: barebaric/raygeo
path: external/raygeo
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: requirements.txt
- name: Install macOS dependencies
run: bash scripts/mac/mac_setup.sh --install
- name: Build macOS artifacts
run: |
printf "5\n" | bash scripts/mac/mac_build.sh --version "${VERSION}"
- name: Smoke test Intel app
run: |
APP_BIN="dist/Rayforge.app/Contents/MacOS/Rayforge"
if [ ! -x "$APP_BIN" ]; then
echo "Rayforge executable not found at $APP_BIN"
exit 1
fi
"$APP_BIN" --version
"$APP_BIN" --exit
- name: Package Intel app
run: |
APP_PATH="dist/Rayforge.app"
if [ ! -d "$APP_PATH" ]; then
echo "App bundle not found at $APP_PATH"
exit 1
fi
ZIP_NAME="rayforge-${VERSION}-macos-intel-app.zip"
ditto -c -k --keepParent "$APP_PATH" "$ZIP_NAME"
- name: Upload Intel app artifact
uses: actions/upload-artifact@v4
with:
name: rayforge-${{ env.VERSION }}-macos-intel-app.zip
path: rayforge-${{ env.VERSION }}-macos-intel-app.zip
compression-level: 9
build-arm:
name: Build macOS Apple Silicon Bundle
needs: version
runs-on: macos-26
env:
VERSION: ${{ needs.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Checkout raygeo source
uses: actions/checkout@v6
with:
repository: barebaric/raygeo
path: external/raygeo
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: requirements.txt
- name: Install macOS dependencies
run: bash scripts/mac/mac_setup.sh --install
- name: Build macOS artifacts
run: |
printf "5\n" | bash scripts/mac/mac_build.sh --version "${VERSION}"
- name: Smoke test ARM app
run: |
APP_BIN="dist/Rayforge.app/Contents/MacOS/Rayforge"
if [ ! -x "$APP_BIN" ]; then
echo "Rayforge executable not found at $APP_BIN"
exit 1
fi
"$APP_BIN" --version
"$APP_BIN" --exit
- name: Package ARM app
run: |
APP_PATH="dist/Rayforge.app"
if [ ! -d "$APP_PATH" ]; then
echo "App bundle not found at $APP_PATH"
exit 1
fi
ZIP_NAME="rayforge-${VERSION}-macos-arm-app.zip"
ditto -c -k --keepParent "$APP_PATH" "$ZIP_NAME"
- name: Upload ARM app artifact
uses: actions/upload-artifact@v4
with:
name: rayforge-${{ env.VERSION }}-macos-arm-app.zip
path: rayforge-${{ env.VERSION }}-macos-arm-app.zip
compression-level: 9
merge-universal:
name: Merge Universal App and DMG
needs: [version, build-intel, build-arm]
runs-on: macos-26
env:
VERSION: ${{ needs.version.outputs.version }}
steps:
- name: Download Intel app artifact
uses: actions/download-artifact@v4
with:
name: rayforge-${{ env.VERSION }}-macos-intel-app.zip
path: artifacts/intel
- name: Download ARM app artifact
uses: actions/download-artifact@v4
with:
name: rayforge-${{ env.VERSION }}-macos-arm-app.zip
path: artifacts/arm
- name: Create universal app
shell: bash
run: |
mkdir -p build-universal
ditto -x -k "artifacts/intel/rayforge-${VERSION}-macos-intel-app.zip" \
artifacts/intel/unpacked
ditto -x -k "artifacts/arm/rayforge-${VERSION}-macos-arm-app.zip" \
artifacts/arm/unpacked
INTEL_APP="artifacts/intel/unpacked/Rayforge.app"
ARM_APP="artifacts/arm/unpacked/Rayforge.app"
UNI_APP="build-universal/Rayforge.app"
if [ ! -d "$INTEL_APP" ] || [ ! -d "$ARM_APP" ]; then
echo "Intel or ARM app bundle not found after extraction"
exit 1
fi
cp -R "$ARM_APP" "$UNI_APP"
rsync -a --ignore-existing "$INTEL_APP/" "$UNI_APP/"
find "$ARM_APP" -type f | while read -r arm_file; do
rel="${arm_file#"$ARM_APP"/}"
intel_file="$INTEL_APP/$rel"
uni_file="$UNI_APP/$rel"
if [ ! -f "$intel_file" ]; then
continue
fi
arm_type=$(file -b "$arm_file")
intel_type=$(file -b "$intel_file")
if [[ "$arm_type" != *"Mach-O"* ]] || \
[[ "$intel_type" != *"Mach-O"* ]]; then
continue
fi
lipo -create -output "$uni_file" "$arm_file" "$intel_file"
if [ -x "$arm_file" ]; then
chmod +x "$uni_file"
fi
done
- name: Set architecture priority
shell: bash
run: |
PLIST="build-universal/Rayforge.app/Contents/Info.plist"
if [ -f "$PLIST" ]; then
/usr/libexec/PlistBuddy -c "Delete :LSArchitecturePriority" \
"$PLIST" >/dev/null 2>&1 || true
/usr/libexec/PlistBuddy -c "Add :LSArchitecturePriority array" \
"$PLIST"
/usr/libexec/PlistBuddy \
-c "Add :LSArchitecturePriority:0 string arm64" "$PLIST"
/usr/libexec/PlistBuddy \
-c "Add :LSArchitecturePriority:1 string x86_64" "$PLIST"
fi
- name: Re-sign universal app
shell: bash
run: |
APP_PATH="$(pwd)/build-universal/Rayforge.app"
if [ ! -d "$APP_PATH" ]; then
echo "Universal app bundle not found at $APP_PATH"
exit 1
fi
chmod -R u+w "$APP_PATH"
rm -rf "$APP_PATH/Contents/_CodeSignature"
if ! codesign --force --deep --sign - "$APP_PATH"; then
echo "Initial deep re-sign failed, retrying..."
sleep 1
codesign --force --deep --sign - "$APP_PATH"
fi
if ! codesign --verify --deep --strict --verbose=2 "$APP_PATH"; then
echo "Warning: codesign verification failed for $APP_PATH"
fi
spctl --assess --type execute --verbose=2 "$APP_PATH" || true
"$APP_PATH/Contents/MacOS/Rayforge" --version
"$APP_PATH/Contents/MacOS/Rayforge" --exit
- name: Package universal app
shell: bash
run: |
APP_ZIP="rayforge-${VERSION}-macos-universal-app.zip"
ditto -c -k --keepParent "build-universal/Rayforge.app" "$APP_ZIP"
TMP_DIR=$(mktemp -d)
ditto -x -k "$APP_ZIP" "$TMP_DIR"
"$TMP_DIR/Rayforge.app/Contents/MacOS/Rayforge" --version
"$TMP_DIR/Rayforge.app/Contents/MacOS/Rayforge" --exit
rm -rf "$TMP_DIR"
- name: Build universal DMG with retry
shell: bash
run: |
mkdir -p build-universal/dmg
cp -R "build-universal/Rayforge.app" "build-universal/dmg/"
ln -sfn /Applications "build-universal/dmg/Applications"
DMG_NAME="rayforge-${VERSION}-macos-universal.dmg"
tries=0
max_tries=10
until hdiutil create -volname "Rayforge" \
-srcfolder "build-universal/dmg" -ov -format ULMO "$DMG_NAME"
do
tries=$((tries + 1))
if [ "$tries" -ge "$max_tries" ]; then
echo "Error: hdiutil failed after ${max_tries} attempts"
exit 1
fi
sleep 2
done
- name: Upload universal app artifact
uses: actions/upload-artifact@v4
with:
name: rayforge-${{ env.VERSION }}-macos-universal-app.zip
path: rayforge-${{ env.VERSION }}-macos-universal-app.zip
compression-level: 9
- name: Upload universal DMG artifact
uses: actions/upload-artifact@v4
with:
name: rayforge-${{ env.VERSION }}-macos-universal-dmg
path: rayforge-${{ env.VERSION }}-macos-universal.dmg
release:
name: Create GitHub Release (Universal)
needs: [version, merge-universal]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'barebaric/rayforge'
permissions:
contents: write
outputs:
is_prerelease: ${{ steps.release_info.outputs.is_prerelease }}
steps:
- name: Determine release type
id: release_info
shell: bash
run: |
TAG="${{ github.ref_name }}"
if [[ "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+- ]]; then
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
else
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
fi
- name: Download Intel app artifact
uses: actions/download-artifact@v4
with:
name: rayforge-${{ needs.version.outputs.version }}-macos-intel-app.zip
- name: Download ARM app artifact
uses: actions/download-artifact@v4
with:
name: rayforge-${{ needs.version.outputs.version }}-macos-arm-app.zip
- name: Download universal app artifact
uses: actions/download-artifact@v4
with:
name: rayforge-${{ needs.version.outputs.version }}-macos-universal-app.zip
- name: Download universal DMG artifact
uses: actions/download-artifact@v4
with:
name: rayforge-${{ needs.version.outputs.version }}-macos-universal-dmg
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
rayforge-${{ needs.version.outputs.version }}-macos-intel-app.zip
rayforge-${{ needs.version.outputs.version }}-macos-arm-app.zip
rayforge-${{ needs.version.outputs.version }}-macos-universal-app.zip
rayforge-${{ needs.version.outputs.version }}-macos-universal.dmg
draft: false
prerelease: ${{ steps.release_info.outputs.is_prerelease }}
name: Release ${{ needs.version.outputs.version }}
tag_name: ${{ github.ref_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}