Skip to content

Fix slogan localization and reorganize update menu #65

Fix slogan localization and reorganize update menu

Fix slogan localization and reorganize update menu #65

Workflow file for this run

name: Release macOS
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
jobs:
build-macos:
runs-on: macos-latest
env:
IOGRAPH_VERSION: ${{ github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller
CREATE_DMG_TAG="v1.2.2"
CREATE_DMG_DIR="${RUNNER_TEMP}/create-dmg"
git clone --depth 1 --branch "${CREATE_DMG_TAG}" https://github.com/create-dmg/create-dmg.git "${CREATE_DMG_DIR}"
echo "CREATE_DMG_BIN=${CREATE_DMG_DIR}/create-dmg" >> "${GITHUB_ENV}"
- name: Build app bundle
run: |
pyinstaller \
--noconfirm \
--windowed \
--name IOGraph \
--icon packaging/assets/dmg/IOGraphVolume.icns \
--add-data "iograph/resources:iograph/resources" \
--collect-all PyQt6 \
run_iograph.py
- name: Set app bundle version metadata
run: |
APP_PLIST="dist/IOGraph.app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${IOGRAPH_VERSION}" "$APP_PLIST" || /usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string ${IOGRAPH_VERSION}" "$APP_PLIST"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${GITHUB_RUN_NUMBER}" "$APP_PLIST" || /usr/libexec/PlistBuddy -c "Add :CFBundleVersion string ${GITHUB_RUN_NUMBER}" "$APP_PLIST"
/usr/libexec/PlistBuddy -c "Set :LSUIElement true" "$APP_PLIST" || /usr/libexec/PlistBuddy -c "Add :LSUIElement bool true" "$APP_PLIST"
- name: Validate signing and notarization secrets
env:
APPLE_CERT_P12_BASE64: ${{ secrets.APPLE_CERT_P12_BASE64 }}
APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
run: |
set -euo pipefail
for key in APPLE_CERT_P12_BASE64 APPLE_CERT_PASSWORD APPLE_TEAM_ID APPLE_API_KEY_ID APPLE_API_ISSUER_ID APPLE_API_KEY_P8; do
if [[ -z "${!key:-}" ]]; then
echo "::error::Missing required secret: ${key}"
exit 1
fi
done
- name: Import Developer ID certificate
env:
APPLE_CERT_P12_BASE64: ${{ secrets.APPLE_CERT_P12_BASE64 }}
APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }}
run: |
set -euo pipefail
CERT_PATH="${RUNNER_TEMP}/developer_id_application.p12"
KEYCHAIN_PATH="${RUNNER_TEMP}/build-signing.keychain-db"
KEYCHAIN_PASSWORD="$(openssl rand -hex 16)"
if ! echo -n "${APPLE_CERT_P12_BASE64}" | base64 --decode > "${CERT_PATH}" 2>/dev/null; then
echo -n "${APPLE_CERT_P12_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 "${APPLE_CERT_PASSWORD}" -T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_PATH}"
security default-keychain -d user -s "${KEYCHAIN_PATH}"
SIGN_IDENTITY="$(security find-identity -v -p codesigning "${KEYCHAIN_PATH}" | awk -F '\"' '/Developer ID Application/ {print $2; exit}')"
if [[ -z "${SIGN_IDENTITY}" || "${SIGN_IDENTITY}" == "\\1" ]]; then
echo "::error::Developer ID Application identity not found in imported certificate"
exit 1
fi
echo "MACOS_SIGN_IDENTITY=${SIGN_IDENTITY}" >> "${GITHUB_ENV}"
- name: Sign app bundle (Developer ID)
run: |
codesign --force --deep --options runtime --timestamp --sign "${MACOS_SIGN_IDENTITY}" dist/IOGraph.app
codesign --verify --deep --strict --verbose=2 dist/IOGraph.app
- name: Prepare artifact
run: |
mkdir -p release
rm -rf build/dmg-root
mkdir -p build/dmg-root
cp -R "dist/IOGraph.app" "build/dmg-root/IOGraph.app"
ditto -c -k --sequesterRsrc --keepParent dist/IOGraph.app "release/IOGraph-macos-${IOGRAPH_VERSION}.zip"
"${CREATE_DMG_BIN}" \
--volname "IOGraph" \
--volicon "packaging/assets/dmg/IOGraphVolume.icns" \
--window-pos 120 120 \
--window-size 446 216 \
--icon-size 128 \
--icon "IOGraph.app" 50 24 \
--app-drop-link 260 24 \
--format UDBZ \
"release/IOGraph-macos-${IOGRAPH_VERSION}.dmg" \
"build/dmg-root"
- name: Notarize and staple DMG
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
run: |
set -euo pipefail
DMG_FILE="release/IOGraph-macos-${IOGRAPH_VERSION}.dmg"
API_KEY_PATH="${RUNNER_TEMP}/AuthKey_${APPLE_API_KEY_ID}.p8"
printf '%s' "${APPLE_API_KEY_P8}" > "${API_KEY_PATH}"
chmod 600 "${API_KEY_PATH}"
xcrun notarytool submit "${DMG_FILE}" \
--key "${API_KEY_PATH}" \
--key-id "${APPLE_API_KEY_ID}" \
--issuer "${APPLE_API_ISSUER_ID}" \
--wait
xcrun stapler staple "${DMG_FILE}"
xcrun stapler validate "${DMG_FILE}"
# On CI runners, Gatekeeper context for DMG "open" checks can be unavailable
# even for accepted + stapled artifacts ("source=Insufficient Context").
if ! spctl -a -vvv -t open "${DMG_FILE}"; then
echo "::warning::spctl open check reported insufficient CI context; notarization/staple already succeeded."
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: IOGraph-macos
path: |
release/IOGraph-macos-*.zip
release/IOGraph-macos-*.dmg
- name: Publish GitHub Release asset
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
retry() {
local attempt=1
local max_attempts=4
local delay_seconds=10
until "$@"; do
if (( attempt >= max_attempts )); then
return 1
fi
echo "Command failed. Retrying in ${delay_seconds}s (attempt ${attempt}/${max_attempts})..."
sleep "${delay_seconds}"
attempt=$((attempt + 1))
delay_seconds=$((delay_seconds * 2))
done
}
TAG="${GITHUB_REF_NAME}"
ZIP_FILE="release/IOGraph-macos-${IOGRAPH_VERSION}.zip"
DMG_FILE="release/IOGraph-macos-${IOGRAPH_VERSION}.dmg"
if ! gh release view "${TAG}" >/dev/null 2>&1; then
CREATE_ARGS=(gh release create "${TAG}" --title "${TAG}" --notes "Automated release for ${TAG}")
if [[ "${TAG}" == *-* ]]; then
CREATE_ARGS+=(--prerelease)
fi
retry "${CREATE_ARGS[@]}"
fi
retry gh release upload "${TAG}" "${ZIP_FILE}" "${DMG_FILE}" --clobber