Hardware decoding stopped working for Linux users on 2.13.0 (Fedora 44 report): every source decodes in software, and AV1 plays black video with audio. Two defects in the pinned libmpv build. First, mpv's meson 'drm' feature silently disabled itself because the CI builder lacks libdisplay-info, and every VAAPI path that does not depend on a display server is derived from it: vaapi-copy's standalone render-node device (the path 2.12.1 worked on) and the GL dmabuf interop for direct vaapi. With only the Wayland VA provider compiled in, a machine whose Wayland VA display fails to initialize has no fallback, and vaapi-copy has an empty provider list - every source lands on software decoding. Pin -Ddrm=enabled, -Dvaapi-drm=enabled, -Degl=enabled and -Dvaapi-wayland=enabled, and add libdisplay-info-dev to the CI package lists, so a missing piece fails the build instead of shipping silent software decode. Second, the bundled static FFmpeg has no AV1 software decoder: its native av1 codec is hardware-accelerated only, so once hwdec fails there is no AV1 path at all - every packet errors, video hits EOF, the plane goes black while audio keeps playing. Pin dav1d 1.5.4 (both VideoLAN remotes agree on the tag object and root commit), build it static before ffmpeg, and pass --enable-libdav1d. The build-plan stub test now asserts the hwdec feature flags, the dav1d static build, and ffmpeg's libdav1d. Verified in an ubuntu:24.04 container with the production flag sets: meson reports drm, vaapi-drm, vaapi-wayland, egl and dmabuf-interop-gl enabled, and ffmpeg configures CONFIG_LIBDAV1D=yes with the AV1 VAAPI hwaccel. close #1874
1048 lines
42 KiB
YAML
1048 lines
42 KiB
YAML
name: Build
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
build_android:
|
|
description: Build Android
|
|
default: true
|
|
type: boolean
|
|
build_ios:
|
|
description: Build iOS
|
|
default: true
|
|
type: boolean
|
|
build_macos:
|
|
description: Build macOS
|
|
default: true
|
|
type: boolean
|
|
build_windows:
|
|
description: Build Windows
|
|
default: true
|
|
type: boolean
|
|
build_linux:
|
|
description: Build Linux
|
|
default: true
|
|
type: boolean
|
|
|
|
env:
|
|
# Only place this workflow names the SDK; .github/actions/setup-flutter-git pins the same release.
|
|
FLUTTER_VERSION: "3.44.0"
|
|
# Shared by every release build command; SENTRY_DIST stays per-platform.
|
|
RELEASE_DART_DEFINES: --dart-define=ENABLE_UPDATE_CHECK=true ${{ github.repository == 'edde746/plezy' && '--dart-define=ENABLE_SENTRY=true' || '' }} --dart-define=GIT_COMMIT=${{ github.sha }} --dart-define=SENTRY_ENVIRONMENT=github --dart-define=ENABLE_DONATIONS=true
|
|
TRUSTED_BUILD_CACHE_VERSION: trusted-build-v1
|
|
LINUX_APT_PACKAGES: >
|
|
clang cmake meson ninja-build pkg-config nasm libgtk-3-dev libevdev-dev liblzma-dev
|
|
libstdc++-12-dev libasound2-dev libass-dev libfreetype-dev libfontconfig-dev libfribidi-dev
|
|
libharfbuzz-dev libepoxy-dev libegl-dev libgl-dev libgnutls28-dev libpipewire-0.3-dev
|
|
libva-dev libvdpau-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev
|
|
libxss-dev libxpresent-dev libxkbcommon-dev libpulse-dev libdbus-1-dev libdrm-dev
|
|
libdisplay-info-dev libgbm-dev libwayland-dev wayland-protocols liblcms2-dev libmujs-dev liblua5.2-dev
|
|
ruby ruby-dev rubygems build-essential rpm libarchive-tools imagemagick libcurl4-openssl-dev
|
|
|
|
jobs:
|
|
validate-trusted-ref:
|
|
name: Validate trusted build ref
|
|
runs-on: ubuntu-latest
|
|
permissions: {}
|
|
steps:
|
|
- name: Require the protected main branch
|
|
shell: bash
|
|
run: |
|
|
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
|
|
echo "Release builds may only run from refs/heads/main." >&2
|
|
exit 1
|
|
fi
|
|
|
|
build-android:
|
|
needs: validate-trusted-ref
|
|
if: ${{ inputs.build_android }}
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
id-token: write
|
|
attestations: write
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Java
|
|
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
|
|
with:
|
|
distribution: "temurin"
|
|
java-version: "21"
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
|
with:
|
|
channel: "stable"
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
cache: true
|
|
cache-key: "${{ env.TRUSTED_BUILD_CACHE_VERSION }}-flutter-:os:-:channel:-:version:-:arch:-:hash:"
|
|
pub-cache: false
|
|
|
|
- name: Cache Pub dependencies
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ runner.arch }}-pub-${{ hashFiles('pubspec.yaml', 'pubspec.lock') }}
|
|
|
|
- name: Cache Gradle
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
~/.gradle/caches
|
|
~/.gradle/wrapper
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get --enforce-lockfile --no-example
|
|
|
|
- name: Configure Android signing
|
|
run: |
|
|
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/app/upload-keystore.jks
|
|
cat > android/key.properties << EOF
|
|
storePassword=${{ secrets.ANDROID_STORE_PASSWORD }}
|
|
keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }}
|
|
keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}
|
|
storeFile=upload-keystore.jks
|
|
EOF
|
|
|
|
- name: Build APKs
|
|
run: flutter build apk --release --split-per-abi ${{ env.RELEASE_DART_DEFINES }} --dart-define=SENTRY_DIST=github-android-apk --obfuscate --split-debug-info=debug-info/android-apk --extra-gen-snapshot-options=--save-obfuscation-map=debug-info/android-apk/obfuscation.map.json
|
|
|
|
- name: Upload symbols to bugs.plezy.app
|
|
if: github.repository == 'edde746/plezy'
|
|
env:
|
|
BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }}
|
|
SENTRY_DIST: github-android-apk
|
|
run: ./scripts/upload-symbols.sh android-apk
|
|
|
|
- name: Clean up keystore
|
|
if: always()
|
|
run: rm -f android/app/upload-keystore.jks android/key.properties
|
|
|
|
- name: Package APKs
|
|
run: |
|
|
tar -czf plezy-android-arm64-v8a.tar.gz -C build/app/outputs/flutter-apk app-arm64-v8a-release.apk --transform 's/app-arm64-v8a-release.apk/plezy.apk/'
|
|
tar -czf plezy-android-armeabi-v7a.tar.gz -C build/app/outputs/flutter-apk app-armeabi-v7a-release.apk --transform 's/app-armeabi-v7a-release.apk/plezy.apk/'
|
|
tar -czf plezy-android-x86_64.tar.gz -C build/app/outputs/flutter-apk app-x86_64-release.apk --transform 's/app-x86_64-release.apk/plezy.apk/'
|
|
|
|
- name: Attest APKs
|
|
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4
|
|
with:
|
|
subject-path: |
|
|
plezy-android-arm64-v8a.tar.gz
|
|
plezy-android-armeabi-v7a.tar.gz
|
|
plezy-android-x86_64.tar.gz
|
|
|
|
- name: Upload APKs
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: android-apk
|
|
path: |
|
|
plezy-android-arm64-v8a.tar.gz
|
|
plezy-android-armeabi-v7a.tar.gz
|
|
plezy-android-x86_64.tar.gz
|
|
|
|
build-ios:
|
|
needs: validate-trusted-ref
|
|
if: ${{ inputs.build_ios }}
|
|
runs-on: macos-26
|
|
permissions:
|
|
id-token: write
|
|
attestations: write
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
|
with:
|
|
channel: "stable"
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
cache: true
|
|
cache-key: "${{ env.TRUSTED_BUILD_CACHE_VERSION }}-flutter-:os:-:channel:-:version:-:arch:-:hash:"
|
|
pub-cache: false
|
|
|
|
- name: Cache Pub dependencies
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ runner.arch }}-pub-${{ hashFiles('pubspec.yaml', 'pubspec.lock') }}
|
|
|
|
- name: Cache CocoaPods
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
ios/Pods
|
|
~/Library/Caches/CocoaPods
|
|
~/.cocoapods
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-ios-pods-${{ hashFiles('**/Podfile.lock') }}
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get --enforce-lockfile --no-example
|
|
|
|
- name: Build iOS (no codesign)
|
|
run: flutter build ios --release --no-codesign ${{ env.RELEASE_DART_DEFINES }} --dart-define=SENTRY_DIST=github-ios --split-debug-info=debug-info/ios
|
|
|
|
- name: Upload symbols to bugs.plezy.app
|
|
if: github.repository == 'edde746/plezy'
|
|
env:
|
|
BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }}
|
|
SENTRY_DIST: github-ios
|
|
run: ./scripts/upload-symbols.sh ios
|
|
|
|
- name: Create IPA
|
|
run: |
|
|
mkdir -p Payload
|
|
cp -r build/ios/iphoneos/Runner.app Payload/
|
|
zip -r plezy-ios.ipa Payload
|
|
|
|
- name: Attest IPA
|
|
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4
|
|
with:
|
|
subject-path: plezy-ios.ipa
|
|
|
|
- name: Upload IPA
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: ios-ipa
|
|
path: plezy-ios.ipa
|
|
|
|
build-macos:
|
|
needs: validate-trusted-ref
|
|
if: ${{ inputs.build_macos }}
|
|
runs-on: macos-26
|
|
permissions:
|
|
id-token: write
|
|
attestations: write
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
|
with:
|
|
channel: "stable"
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
cache: true
|
|
cache-key: "${{ env.TRUSTED_BUILD_CACHE_VERSION }}-flutter-:os:-:channel:-:version:-:arch:-:hash:"
|
|
pub-cache: false
|
|
|
|
- name: Cache Pub dependencies
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ runner.arch }}-pub-${{ hashFiles('pubspec.yaml', 'pubspec.lock') }}
|
|
|
|
- name: Cache CocoaPods
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
macos/Pods
|
|
~/Library/Caches/CocoaPods
|
|
~/.cocoapods
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-macos-pods-${{ hashFiles('**/Podfile.lock') }}
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get --enforce-lockfile --no-example
|
|
|
|
- name: Build macOS
|
|
run: flutter build macos --release ${{ env.RELEASE_DART_DEFINES }} --dart-define=SENTRY_DIST=github-macos --split-debug-info=debug-info/macos
|
|
|
|
- name: Upload symbols to bugs.plezy.app
|
|
if: github.repository == 'edde746/plezy'
|
|
env:
|
|
BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }}
|
|
SENTRY_DIST: github-macos
|
|
run: ./scripts/upload-symbols.sh macos
|
|
|
|
- name: Import Code Signing Certificate
|
|
env:
|
|
MACOS_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_BASE64 }}
|
|
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
|
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
|
run: |
|
|
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain
|
|
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
|
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
|
|
|
CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12
|
|
echo "$MACOS_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
|
|
security import $CERTIFICATE_PATH -k $KEYCHAIN_PATH -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
|
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
|
|
|
# Add keychain to search list
|
|
security list-keychains -d user -s $KEYCHAIN_PATH login.keychain
|
|
|
|
- name: Sign Application
|
|
env:
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
run: |
|
|
# Find the identity
|
|
IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | grep -o '".*"' | tr -d '"')
|
|
echo "Signing with identity: $IDENTITY"
|
|
|
|
APP_PATH="build/macos/Build/Products/Release/Plezy.app"
|
|
|
|
# Deep sign everything inside-out: executables, dylibs, XPC services, app bundles, frameworks
|
|
find "$APP_PATH/Contents/Frameworks" \( -name "*.xpc" -o -name "*.app" -o -name "*.framework" -o -name "*.dylib" \) -print0 \
|
|
| sort -zr \
|
|
| while IFS= read -r -d '' item; do
|
|
echo "Signing: $item"
|
|
codesign --force --sign "$IDENTITY" --timestamp --options runtime "$item"
|
|
done
|
|
|
|
# Sign any remaining bare executables (e.g. Sparkle's Autoupdate)
|
|
find "$APP_PATH/Contents/Frameworks" -type f -perm +111 ! -name "*.dylib" ! -path "*/Headers/*" ! -path "*/Modules/*" -print0 \
|
|
| while IFS= read -r -d '' exe; do
|
|
codesign --force --sign "$IDENTITY" --timestamp --options runtime "$exe" 2>/dev/null || true
|
|
done
|
|
|
|
# Sign the app bundle itself
|
|
echo "Signing app bundle: $APP_PATH"
|
|
codesign --force --sign "$IDENTITY" --timestamp --options runtime --entitlements macos/Runner/Release.entitlements "$APP_PATH"
|
|
|
|
- name: Verify Signature
|
|
run: |
|
|
APP_PATH="build/macos/Build/Products/Release/Plezy.app"
|
|
echo "Verifying signature..."
|
|
codesign -dvvv "$APP_PATH"
|
|
echo "Verifying signed entitlements..."
|
|
codesign -d --entitlements :- "$APP_PATH" > "$RUNNER_TEMP/macos-entitlements.plist"
|
|
/usr/libexec/PlistBuddy -c "Print" "$RUNNER_TEMP/macos-entitlements.plist"
|
|
/usr/libexec/PlistBuddy -c "Print :com.apple.security.cs.allow-jit" "$RUNNER_TEMP/macos-entitlements.plist"
|
|
/usr/libexec/PlistBuddy -c "Print :com.apple.security.cs.allow-unsigned-executable-memory" "$RUNNER_TEMP/macos-entitlements.plist"
|
|
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
|
|
|
|
- name: Notarize Application
|
|
env:
|
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
run: |
|
|
APP_PATH="build/macos/Build/Products/Release/Plezy.app"
|
|
|
|
# Create a temporary ZIP for notarization submission
|
|
echo "Creating ZIP for notarization..."
|
|
ditto -c -k --keepParent "$APP_PATH" notarization.zip
|
|
|
|
# Submit for notarization
|
|
echo "Submitting to Apple's notary service..."
|
|
xcrun notarytool submit notarization.zip \
|
|
--apple-id "$APPLE_ID" \
|
|
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
|
|
--team-id "$APPLE_TEAM_ID" \
|
|
--wait
|
|
|
|
# Staple the notarization ticket to the app
|
|
echo "Stapling notarization ticket..."
|
|
xcrun stapler staple "$APP_PATH"
|
|
|
|
# Verify stapling
|
|
echo "Verifying notarization..."
|
|
xcrun stapler validate "$APP_PATH"
|
|
|
|
- name: Create DMG
|
|
run: |
|
|
mkdir -p dmg-staging
|
|
cp -R build/macos/Build/Products/Release/Plezy.app dmg-staging/
|
|
ln -s /Applications dmg-staging/Applications
|
|
hdiutil create -format ULMO -srcfolder dmg-staging -volname "Plezy" plezy-macos.dmg
|
|
|
|
- name: Sign DMG for Sparkle (EdDSA)
|
|
if: env.SPARKLE_PRIVATE_KEY != ''
|
|
env:
|
|
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
|
|
run: |
|
|
printf -- "-----BEGIN ED25519 PRIVATE KEY-----\n%s\n-----END ED25519 PRIVATE KEY-----\n" "$SPARKLE_PRIVATE_KEY" > ed25519_key.pem
|
|
OUTPUT=$(dart run auto_updater:sign_update plezy-macos.dmg ed25519_key.pem)
|
|
rm ed25519_key.pem
|
|
# Extract edSignature value from output like: sparkle:edSignature="..." length="..."
|
|
SIGNATURE=$(echo "$OUTPUT" | grep -o 'edSignature="[^"]*"' | sed 's/edSignature="//;s/"//')
|
|
echo "MACOS_ED_SIGNATURE=$SIGNATURE" >> $GITHUB_ENV
|
|
echo "MACOS_DMG_SIZE=$(stat -f%z plezy-macos.dmg)" >> $GITHUB_ENV
|
|
|
|
- name: Attest macOS DMG
|
|
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4
|
|
with:
|
|
subject-path: plezy-macos.dmg
|
|
|
|
- name: Write macOS signature metadata
|
|
run: |
|
|
echo "${{ env.MACOS_ED_SIGNATURE }}" > macos-ed-signature.txt
|
|
echo "${{ env.MACOS_DMG_SIZE }}" > macos-dmg-size.txt
|
|
|
|
- name: Upload macOS DMG
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: macos-dmg
|
|
path: |
|
|
plezy-macos.dmg
|
|
macos-ed-signature.txt
|
|
macos-dmg-size.txt
|
|
|
|
build-windows:
|
|
needs: validate-trusted-ref
|
|
name: Build Windows (${{ matrix.arch }})
|
|
if: ${{ inputs.build_windows }}
|
|
runs-on: ${{ matrix.runner }}
|
|
permissions:
|
|
contents: read
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- arch: x64
|
|
runner: windows-latest
|
|
flutter_setup: action
|
|
native_cache_path: build/windows/x64/_deps
|
|
- arch: arm64
|
|
runner: windows-11-arm
|
|
flutter_setup: git
|
|
native_cache_path: |
|
|
build/windows/arm64/_deps
|
|
build/windows/arm64/mpv-dev-arm64
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Cache Windows native dependencies
|
|
id: windows-native-cache
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: ${{ matrix.native_cache_path }}
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-windows-native-${{ matrix.arch }}-${{ hashFiles('windows/CMakeLists.txt') }}
|
|
|
|
- name: Install 7-Zip
|
|
if: matrix.arch == 'arm64' && steps.windows-native-cache.outputs.cache-hit != 'true'
|
|
shell: pwsh
|
|
run: choco install 7zip -y
|
|
|
|
- name: Setup Flutter
|
|
if: matrix.flutter_setup == 'action'
|
|
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
|
with:
|
|
channel: "stable"
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
cache: true
|
|
cache-key: "${{ env.TRUSTED_BUILD_CACHE_VERSION }}-flutter-:os:-:channel:-:version:-:arch:-:hash:"
|
|
pub-cache: false
|
|
|
|
- name: Set up Flutter from its pinned commit
|
|
if: matrix.flutter_setup == 'git'
|
|
uses: ./.github/actions/setup-flutter-git
|
|
|
|
- name: Cache Pub dependencies
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
~\AppData\Local\Pub\Cache
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ runner.arch }}-pub-${{ hashFiles('pubspec.yaml', 'pubspec.lock') }}
|
|
|
|
- name: Install dependencies
|
|
shell: pwsh
|
|
run: flutter pub get --enforce-lockfile --no-example
|
|
|
|
- name: Install patched Flutter engine (DComp)
|
|
shell: pwsh
|
|
run: |
|
|
flutter precache --windows
|
|
.\windows\tool\install-patched-engine.ps1
|
|
|
|
- name: Build Windows ${{ matrix.arch }}
|
|
shell: pwsh
|
|
run: flutter build windows --release ${{ env.RELEASE_DART_DEFINES }} --dart-define=SENTRY_DIST=github-windows-${{ matrix.arch }} --split-debug-info=debug-info/windows-${{ matrix.arch }}
|
|
|
|
- name: Verify Windows bundle contents
|
|
shell: pwsh
|
|
run: |
|
|
$bundleDir = "build/windows/${{ matrix.arch }}/runner/Release"
|
|
if (-not (Test-Path -LiteralPath $bundleDir -PathType Container)) {
|
|
throw "Windows bundle directory does not exist: $bundleDir"
|
|
}
|
|
|
|
$bundlePath = (Resolve-Path -LiteralPath $bundleDir).Path
|
|
$foundFiles = @(
|
|
Get-ChildItem -LiteralPath $bundlePath -File -Recurse |
|
|
ForEach-Object {
|
|
$_.FullName.Substring($bundlePath.Length + 1).Replace('\', '/')
|
|
} |
|
|
Sort-Object
|
|
)
|
|
|
|
Write-Host "Files found in ${bundleDir}:"
|
|
$foundFiles | ForEach-Object { Write-Host " $_" }
|
|
|
|
$requiredFiles = @(
|
|
"plezy.exe"
|
|
"flutter_windows.dll"
|
|
"sqlite3.dll"
|
|
"libmpv-2.dll"
|
|
"data/app.so"
|
|
"data/icudtl.dat"
|
|
"data/flutter_assets/NativeAssetsManifest.json"
|
|
# MSVC runtime bundled by InstallRequiredSystemLibraries in
|
|
# windows/CMakeLists.txt; without it the app crashes at startup on
|
|
# machines whose system-wide redist is older than the CI toolset.
|
|
"msvcp140.dll"
|
|
"vcruntime140.dll"
|
|
)
|
|
$forbiddenFiles = @(
|
|
"plezy.lib"
|
|
"plezy.exp"
|
|
"simdutf.lib"
|
|
)
|
|
|
|
$bundleErrors = @()
|
|
foreach ($file in $requiredFiles) {
|
|
if ($foundFiles -notcontains $file) {
|
|
Write-Output "::error::Required Windows bundle file is missing: $file"
|
|
$bundleErrors += "missing $file"
|
|
}
|
|
}
|
|
foreach ($file in $forbiddenFiles) {
|
|
if ($foundFiles -contains $file) {
|
|
Write-Output "::error::Forbidden link by-product is present in the Windows bundle: $file"
|
|
$bundleErrors += "present $file"
|
|
}
|
|
}
|
|
|
|
# sentry.dll is the inproc-backend native SDK; crashpad_handler.exe is
|
|
# intentionally absent (windows/CMakeLists.txt sets
|
|
# SENTRY_NATIVE_BACKEND=inproc), so do not assert on it here.
|
|
|
|
if ($bundleErrors.Count -gt 0) {
|
|
throw "Windows bundle verification failed: $($bundleErrors -join '; ')"
|
|
}
|
|
|
|
- name: Upload symbols to bugs.plezy.app
|
|
if: github.repository == 'edde746/plezy'
|
|
shell: pwsh
|
|
env:
|
|
BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }}
|
|
SENTRY_DIST: github-windows-${{ matrix.arch }}
|
|
run: .\scripts\upload-symbols.ps1 windows-${{ matrix.arch }}
|
|
|
|
- name: Upload ${{ matrix.arch }} build
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: windows-${{ matrix.arch }}-build
|
|
path: build/windows/${{ matrix.arch }}/runner/Release/
|
|
|
|
package-windows:
|
|
needs: build-windows
|
|
if: ${{ inputs.build_windows }}
|
|
runs-on: windows-latest
|
|
permissions:
|
|
id-token: write
|
|
attestations: write
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
|
with:
|
|
channel: "stable"
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
cache: true
|
|
cache-key: "${{ env.TRUSTED_BUILD_CACHE_VERSION }}-flutter-:os:-:channel:-:version:-:arch:-:hash:"
|
|
pub-cache: false
|
|
|
|
- name: Install dependencies
|
|
shell: pwsh
|
|
run: flutter pub get --enforce-lockfile --no-example
|
|
|
|
- name: Download x64 build
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: windows-x64-build
|
|
path: build-x64
|
|
|
|
- name: Download arm64 build
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: windows-arm64-build
|
|
path: build-arm64
|
|
|
|
- name: Read version from pubspec
|
|
id: version
|
|
shell: pwsh
|
|
run: |
|
|
$v = (Select-String -Path pubspec.yaml -Pattern '^version:\s*(\S+)').Matches[0].Groups[1].Value -replace '\+.*'
|
|
echo "version=$v" >> $env:GITHUB_OUTPUT
|
|
|
|
- name: Build installer and portables
|
|
run: .\windows\build-installer.ps1 -X64BuildDir "build-x64" -Arm64BuildDir "build-arm64" -Version "${{ steps.version.outputs.version }}"
|
|
|
|
# Unsigned on purpose: the Store re-signs the bundle during
|
|
# certification. See windows/build-msix.ps1.
|
|
- name: Build Store package (MSIX)
|
|
run: .\windows\build-msix.ps1 -X64BuildDir "build-x64" -Arm64BuildDir "build-arm64" -Version "${{ steps.version.outputs.version }}"
|
|
|
|
- name: Sign installer for WinSparkle (EdDSA)
|
|
if: env.SPARKLE_PRIVATE_KEY != ''
|
|
env:
|
|
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
|
|
shell: pwsh
|
|
run: |
|
|
$keyPath = Join-Path $env:RUNNER_TEMP "plezy-winsparkle-ed25519.pem"
|
|
try {
|
|
Set-Content -Path $keyPath -Value $env:SPARKLE_PRIVATE_KEY -Encoding ascii -NoNewline
|
|
$output = & dart run auto_updater:sign_update plezy-windows-installer.exe $keyPath
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "WinSparkle signer failed with exit code $LASTEXITCODE"
|
|
}
|
|
$match = [regex]::Match($output, 'edSignature="([^"]*)"')
|
|
if (-not $match.Success) {
|
|
throw "WinSparkle signer returned no EdDSA signature"
|
|
}
|
|
Set-Content -Path win-ed-signature.txt -Value $match.Groups[1].Value -Encoding ascii -NoNewline
|
|
Set-Content -Path win-installer-size.txt -Value (Get-Item plezy-windows-installer.exe).Length.ToString() -Encoding ascii -NoNewline
|
|
} finally {
|
|
Remove-Item -Path $keyPath -Force -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
- name: Attest Windows artifacts
|
|
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4
|
|
with:
|
|
subject-path: |
|
|
plezy-windows-x64-portable.7z
|
|
plezy-windows-arm64-portable.7z
|
|
plezy-windows-installer.exe
|
|
plezy-windows.msixbundle
|
|
|
|
- name: Upload x64 portable
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: windows-x64-portable
|
|
path: plezy-windows-x64-portable.7z
|
|
|
|
- name: Upload arm64 portable
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: windows-arm64-portable
|
|
path: plezy-windows-arm64-portable.7z
|
|
|
|
- name: Upload installer
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: windows-installer
|
|
path: |
|
|
plezy-windows-installer.exe
|
|
win-ed-signature.txt
|
|
win-installer-size.txt
|
|
|
|
# Deliberately not attached to the GitHub release in create-release: a
|
|
# Store-identity package cannot be installed without the Store's
|
|
# certificate, so it is only useful as a Partner Center upload.
|
|
- name: Upload Store package
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: windows-msix
|
|
path: plezy-windows.msixbundle
|
|
|
|
build-linux:
|
|
needs: validate-trusted-ref
|
|
name: Build Linux (${{ matrix.arch }})
|
|
if: ${{ inputs.build_linux }}
|
|
runs-on: ${{ matrix.runner }}
|
|
permissions:
|
|
id-token: write
|
|
attestations: write
|
|
contents: read
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- arch: x64
|
|
runner: ubuntu-latest
|
|
flutter_channel: stable
|
|
pkg_config_arch: x86_64-linux-gnu
|
|
- arch: arm64
|
|
runner: ubuntu-24.04-arm
|
|
flutter_channel: master
|
|
pkg_config_arch: aarch64-linux-gnu
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
|
with:
|
|
channel: ${{ matrix.flutter_channel }}
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
cache: true
|
|
cache-key: "${{ env.TRUSTED_BUILD_CACHE_VERSION }}-flutter-:os:-:channel:-:version:-:arch:-:hash:"
|
|
pub-cache: false
|
|
|
|
- name: Cache Pub dependencies
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ runner.arch }}-pub-${{ hashFiles('pubspec.yaml', 'pubspec.lock') }}
|
|
|
|
- name: Cache APT packages
|
|
uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
|
|
with:
|
|
packages: ${{ env.LINUX_APT_PACKAGES }}
|
|
version: trusted-build-v1.1
|
|
|
|
- name: Install Linux dependencies
|
|
shell: bash
|
|
run: |
|
|
read -r -a packages <<< "$LINUX_APT_PACKAGES"
|
|
|
|
for attempt in 1 2 3; do
|
|
if sudo apt-get update -o Acquire::Retries=3 && sudo apt-get install -y -o Acquire::Retries=3 "${packages[@]}"; then
|
|
exit 0
|
|
fi
|
|
|
|
sudo apt-get clean
|
|
sudo rm -rf /var/lib/apt/lists/*
|
|
sleep $((attempt * 15))
|
|
done
|
|
|
|
exit 1
|
|
|
|
- name: Cache libmpv build
|
|
id: libmpv-cache
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: libmpv-prefix
|
|
key: ${{ env.TRUSTED_BUILD_CACHE_VERSION }}-libmpv-${{ runner.arch }}-${{ hashFiles('linux/packaging/build-libmpv.sh', 'linux/packaging/native-inputs.json') }}
|
|
|
|
- name: Build libmpv
|
|
if: steps.libmpv-cache.outputs.cache-hit != 'true'
|
|
shell: bash
|
|
run: bash linux/packaging/build-libmpv.sh
|
|
|
|
- name: Install fpm
|
|
shell: bash
|
|
run: sudo gem install fpm --version 1.17.0 --no-document
|
|
|
|
- name: Install dependencies
|
|
shell: bash
|
|
run: flutter pub get --enforce-lockfile --no-example
|
|
|
|
- name: Build Linux ${{ matrix.arch }}
|
|
shell: bash
|
|
run: flutter build linux --release ${{ env.RELEASE_DART_DEFINES }} --dart-define=SENTRY_DIST=github-linux-${{ matrix.arch }} --split-debug-info=debug-info/linux-${{ matrix.arch }}
|
|
env:
|
|
PKG_CONFIG_PATH: ${{ github.workspace }}/libmpv-prefix/lib/pkgconfig:${{ github.workspace }}/libmpv-prefix/lib/${{ matrix.pkg_config_arch }}/pkgconfig
|
|
|
|
- name: Upload symbols to bugs.plezy.app
|
|
if: github.repository == 'edde746/plezy'
|
|
shell: bash
|
|
env:
|
|
BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }}
|
|
SENTRY_DIST: github-linux-${{ matrix.arch }}
|
|
run: ./scripts/upload-symbols.sh linux-${{ matrix.arch }}
|
|
|
|
- name: Resolve bundle directory
|
|
shell: bash
|
|
run: |
|
|
if [[ "${{ matrix.arch }}" == "x64" ]]; then
|
|
bundle_dir=build/linux/x64/release/bundle
|
|
else
|
|
bundle_dir=$(find build/linux -path "*/release/bundle" -type d | head -1)
|
|
fi
|
|
if [[ -z "$bundle_dir" || ! -d "$bundle_dir" ]]; then
|
|
echo "ERROR: Linux bundle directory not found" >&2
|
|
exit 1
|
|
fi
|
|
echo "BUNDLE_DIR=$bundle_dir" >> "$GITHUB_ENV"
|
|
|
|
# Everything below resolves the bundle *before* packaging, so the packages
|
|
# and the tarball are cut from one identical tree.
|
|
#
|
|
# The plane needs the pinned Wayland-enabled libmpv: a distro libmpv still
|
|
# plays and still does HDR, but silently drops hwdec to vaapi-copy - which
|
|
# was measured, not assumed. So libmpv travels with us and no artifact
|
|
# depends on a host one. That removed the host `mpv` dependency, and with it
|
|
# the transitive pull of everything libmpv itself needs - libass, pulse,
|
|
# pipewire, fontconfig and the rest. bundle-libs.sh is what supplies those,
|
|
# so it has to run before packaging too, or the packages would carry libmpv
|
|
# and nothing it links.
|
|
- name: Copy libmpv into bundle
|
|
shell: bash
|
|
run: |
|
|
BUNDLE_LIB="$BUNDLE_DIR/lib"
|
|
LIBMPV_DIR=$(dirname "$(find libmpv-prefix -name 'libmpv.so' | head -1)")
|
|
cp -a "$LIBMPV_DIR"/libmpv.so* "$BUNDLE_LIB/"
|
|
cp -a libmpv-prefix/lib/libshaderc_shared.so* "$BUNDLE_LIB/"
|
|
|
|
- name: Bundle shared libraries
|
|
shell: bash
|
|
run: bash linux/packaging/bundle-libs.sh "$BUNDLE_DIR"
|
|
|
|
- name: Copy wrapper script into bundle
|
|
shell: bash
|
|
run: cp linux/packaging/plezy.sh "$BUNDLE_DIR/plezy.sh"
|
|
|
|
# Same check the package smoke build runs, against the artifact that
|
|
# actually ships: a library nobody declares is a broken install, and it is
|
|
# invisible until a user on a clean machine tries to launch.
|
|
#
|
|
# This also stands in for the `ldd ./plezy | grep "not found"` step that
|
|
# used to run after packaging. That one folded ldd's stderr into grep's
|
|
# input and dropped its exit status, so ldd failing outright - a missing
|
|
# loader, an exec-format mismatch, no ldd at all - left the match empty and
|
|
# printed "All dependencies resolved." This guard runs ldd over every
|
|
# object under lib/ as well as the executable, fails on an unresolved
|
|
# soname, fails when ldd cannot read an object, and refuses to pass when
|
|
# the walk found no host libraries at all. Packaging below only reads the
|
|
# bundle, so a second shell ldd afterwards could only restate a weaker
|
|
# subset of what this already proved about the very same tree.
|
|
- name: Verify every unbundled library the bundle needs is declared
|
|
shell: bash
|
|
run: python3 linux/packaging/check-bundle-host-deps.py "$BUNDLE_DIR"
|
|
|
|
# Last, from the fully resolved tree above. The host-dependency guard is
|
|
# skipped because the named step above just ran it against this same
|
|
# bundle; the internal run exists for by-hand packaging outside CI.
|
|
- name: Build Linux Packages
|
|
shell: bash
|
|
run: |
|
|
BUILD_DIR="$BUNDLE_DIR" \
|
|
ARCH_SUFFIX=${{ matrix.arch }} \
|
|
OUTPUT_DIR="$GITHUB_WORKSPACE" \
|
|
PLEZY_SKIP_HOST_DEP_CHECK=1 \
|
|
python3 linux/packaging/build-packages.py
|
|
|
|
# The depends lists reached fpm above; only the packages it wrote can show
|
|
# they arrived. Same script the smoke build runs, so the two jobs cannot
|
|
# drift on what counts as declared - and unlike the smoke build, this one
|
|
# covers arm64 and the artifacts users actually install.
|
|
- name: Verify the declared dependencies reached the package metadata
|
|
shell: bash
|
|
run: python3 linux/packaging/check-package-deps.py "$GITHUB_WORKSPACE" --arch ${{ matrix.arch }}
|
|
|
|
- name: Create tarball
|
|
shell: bash
|
|
run: |
|
|
cd "$BUNDLE_DIR"
|
|
tar -czf "$GITHUB_WORKSPACE/plezy-linux-${{ matrix.arch }}.tar.gz" *
|
|
|
|
- name: Attest Linux ${{ matrix.arch }} artifacts
|
|
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4
|
|
with:
|
|
subject-path: |
|
|
plezy-linux-${{ matrix.arch }}.tar.gz
|
|
plezy-linux-${{ matrix.arch }}.deb
|
|
plezy-linux-${{ matrix.arch }}.rpm
|
|
plezy-linux-${{ matrix.arch }}.pkg.tar.zst
|
|
|
|
- name: Upload Linux ${{ matrix.arch }} artifacts
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: linux-${{ matrix.arch }}
|
|
path: |
|
|
plezy-linux-${{ matrix.arch }}.tar.gz
|
|
plezy-linux-${{ matrix.arch }}.deb
|
|
plezy-linux-${{ matrix.arch }}.rpm
|
|
plezy-linux-${{ matrix.arch }}.pkg.tar.zst
|
|
|
|
create-release:
|
|
needs: [validate-trusted-ref, build-android, build-ios, build-macos, build-windows, package-windows, build-linux]
|
|
if: ${{ always() && needs.validate-trusted-ref.result == 'success' && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && inputs.build_android && inputs.build_ios && inputs.build_macos && inputs.build_windows && inputs.build_linux }}
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
sparse-checkout: pubspec.yaml
|
|
sparse-checkout-cone-mode: false
|
|
persist-credentials: false
|
|
|
|
- name: Read version from pubspec.yaml
|
|
id: version
|
|
run: |
|
|
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //' | sed 's/+.*//')
|
|
BUILD_NUMBER=$(grep '^version:' pubspec.yaml | sed 's/.*+//')
|
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
|
|
|
|
- name: Download Android artifacts
|
|
if: ${{ inputs.build_android }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: android-apk
|
|
path: artifacts/android-apk
|
|
|
|
- name: Download iOS artifact
|
|
if: ${{ inputs.build_ios }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: ios-ipa
|
|
path: artifacts/ios-ipa
|
|
|
|
- name: Download macOS artifact
|
|
if: ${{ inputs.build_macos }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: macos-dmg
|
|
path: artifacts/macos-dmg
|
|
|
|
- name: Download Windows x64 artifact
|
|
if: ${{ inputs.build_windows }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: windows-x64-portable
|
|
path: artifacts/windows-x64-portable
|
|
|
|
- name: Download Windows arm64 artifact
|
|
if: ${{ inputs.build_windows }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: windows-arm64-portable
|
|
path: artifacts/windows-arm64-portable
|
|
|
|
- name: Download Windows installer artifact
|
|
if: ${{ inputs.build_windows }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: windows-installer
|
|
path: artifacts/windows-installer
|
|
|
|
- name: Download Linux x64 artifacts
|
|
if: ${{ inputs.build_linux }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: linux-x64
|
|
path: artifacts/linux-x64
|
|
|
|
- name: Download Linux arm64 artifacts
|
|
if: ${{ inputs.build_linux }}
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: linux-arm64
|
|
path: artifacts/linux-arm64
|
|
|
|
- name: Display structure of downloaded files
|
|
run: ls -R artifacts
|
|
|
|
- name: Generate appcast.xml
|
|
run: |
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
BUILD_NUMBER="${{ steps.version.outputs.build_number }}"
|
|
|
|
# Read macOS signature metadata (may be empty if secrets not configured)
|
|
MACOS_ED_SIG=""
|
|
MACOS_DMG_SIZE="0"
|
|
if [ -f artifacts/macos-dmg/macos-ed-signature.txt ]; then
|
|
MACOS_ED_SIG=$(cat artifacts/macos-dmg/macos-ed-signature.txt)
|
|
fi
|
|
if [ -f artifacts/macos-dmg/macos-dmg-size.txt ]; then
|
|
MACOS_DMG_SIZE=$(cat artifacts/macos-dmg/macos-dmg-size.txt)
|
|
fi
|
|
|
|
# Read Windows signature metadata (may be empty if secrets not configured)
|
|
WIN_ED_SIG=""
|
|
WIN_INSTALLER_SIZE="0"
|
|
if [ -f artifacts/windows-installer/win-ed-signature.txt ]; then
|
|
WIN_ED_SIG=$(cat artifacts/windows-installer/win-ed-signature.txt)
|
|
fi
|
|
if [ -f artifacts/windows-installer/win-installer-size.txt ]; then
|
|
WIN_INSTALLER_SIZE=$(cat artifacts/windows-installer/win-installer-size.txt)
|
|
fi
|
|
|
|
cat > appcast.xml << XMLEOF
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
|
|
<channel>
|
|
<title>Plezy Updates</title>
|
|
<item>
|
|
<title>Version ${VERSION}</title>
|
|
<sparkle:version>${BUILD_NUMBER}</sparkle:version>
|
|
<sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
|
|
<sparkle:releaseNotesLink>https://gh-html.edde746.dev/edde746/plezy/${VERSION}</sparkle:releaseNotesLink>
|
|
XMLEOF
|
|
|
|
# macOS enclosure
|
|
if [ -n "$MACOS_ED_SIG" ]; then
|
|
cat >> appcast.xml << XMLEOF
|
|
<enclosure url="https://github.com/edde746/plezy/releases/download/${VERSION}/plezy-macos.dmg"
|
|
length="${MACOS_DMG_SIZE}" type="application/octet-stream"
|
|
sparkle:edSignature="${MACOS_ED_SIG}"
|
|
sparkle:os="macos" />
|
|
XMLEOF
|
|
fi
|
|
|
|
# Windows enclosure
|
|
if [ -n "$WIN_ED_SIG" ]; then
|
|
cat >> appcast.xml << XMLEOF
|
|
<enclosure url="https://github.com/edde746/plezy/releases/download/${VERSION}/plezy-windows-installer.exe"
|
|
length="${WIN_INSTALLER_SIZE}" type="application/octet-stream"
|
|
sparkle:edSignature="${WIN_ED_SIG}"
|
|
sparkle:installerArguments="/SILENT /SP-"
|
|
sparkle:os="windows" />
|
|
XMLEOF
|
|
fi
|
|
|
|
cat >> appcast.xml << 'XMLEOF'
|
|
</item>
|
|
</channel>
|
|
</rss>
|
|
XMLEOF
|
|
|
|
# Clean up leading whitespace from heredoc indentation
|
|
sed -i 's/^ //' appcast.xml
|
|
|
|
echo "Generated appcast.xml:"
|
|
cat appcast.xml
|
|
|
|
- name: Collect release files
|
|
id: release-files
|
|
run: |
|
|
{
|
|
echo 'files<<EOF'
|
|
if [ "${{ inputs.build_android }}" = "true" ]; then
|
|
echo artifacts/android-apk/plezy-android-arm64-v8a.tar.gz
|
|
echo artifacts/android-apk/plezy-android-armeabi-v7a.tar.gz
|
|
echo artifacts/android-apk/plezy-android-x86_64.tar.gz
|
|
fi
|
|
if [ "${{ inputs.build_ios }}" = "true" ]; then
|
|
echo artifacts/ios-ipa/plezy-ios.ipa
|
|
fi
|
|
if [ "${{ inputs.build_macos }}" = "true" ]; then
|
|
echo artifacts/macos-dmg/plezy-macos.dmg
|
|
fi
|
|
if [ "${{ inputs.build_windows }}" = "true" ]; then
|
|
echo artifacts/windows-x64-portable/plezy-windows-x64-portable.7z
|
|
echo artifacts/windows-arm64-portable/plezy-windows-arm64-portable.7z
|
|
echo artifacts/windows-installer/plezy-windows-installer.exe
|
|
fi
|
|
if [ "${{ inputs.build_linux }}" = "true" ]; then
|
|
echo 'artifacts/linux-x64/*'
|
|
echo 'artifacts/linux-arm64/*'
|
|
fi
|
|
echo appcast.xml
|
|
echo EOF
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Create Release
|
|
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3
|
|
with:
|
|
files: ${{ steps.release-files.outputs.files }}
|
|
draft: true
|
|
prerelease: false
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|