mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 07:21:58 +00:00
Merge e0c0667e35 into 70d3eee9d2
This commit is contained in:
commit
3ede90d326
5 changed files with 414 additions and 3 deletions
99
.github/workflows/build-check.yml
vendored
Normal file
99
.github/workflows/build-check.yml
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
name: Build check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, ready_for_review]
|
||||||
|
|
||||||
|
# Cancel superseded runs on the same PR.
|
||||||
|
concurrency:
|
||||||
|
group: build-check-${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
android:
|
||||||
|
name: Android (compile)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Make gradlew executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
|
- name: Compile Android (full + playstore, debug)
|
||||||
|
run: ./gradlew :composeApp:assembleFullDebug :composeApp:assemblePlaystoreDebug --stacktrace
|
||||||
|
|
||||||
|
ios:
|
||||||
|
name: iOS (compile)
|
||||||
|
runs-on: macos-15
|
||||||
|
timeout-minutes: 60
|
||||||
|
env:
|
||||||
|
NUVIO_IOS_DISTRIBUTION: full
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Select latest stable Xcode
|
||||||
|
uses: maxim-lobanov/setup-xcode@v1
|
||||||
|
with:
|
||||||
|
xcode-version: latest-stable
|
||||||
|
|
||||||
|
- name: Make gradlew executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
|
# Both iOS distributions (appstore / full) swap source dirs and deps,
|
||||||
|
# so each must be type-checked independently.
|
||||||
|
- name: Compile shared Kotlin/Native (appstore distribution)
|
||||||
|
run: ./gradlew :composeApp:compileKotlinIosArm64 :composeApp:compileKotlinIosSimulatorArm64 -Pnuvio.ios.distribution=appstore --stacktrace
|
||||||
|
|
||||||
|
- name: Compile shared Kotlin/Native (full distribution)
|
||||||
|
run: ./gradlew :composeApp:compileKotlinIosArm64 :composeApp:compileKotlinIosSimulatorArm64 -Pnuvio.ios.distribution=full --stacktrace
|
||||||
|
|
||||||
|
- name: Build iOS app (Debug, simulator destination, unsigned)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
xcodebuild \
|
||||||
|
-project iosApp/iosApp.xcodeproj \
|
||||||
|
-scheme iosApp \
|
||||||
|
-configuration Debug \
|
||||||
|
-destination 'generic/platform=iOS Simulator' \
|
||||||
|
-derivedDataPath build/ios-derived-pr \
|
||||||
|
-skipPackagePluginValidation \
|
||||||
|
-skipMacroValidation \
|
||||||
|
CODE_SIGNING_ALLOWED=NO \
|
||||||
|
CODE_SIGNING_REQUIRED=NO \
|
||||||
|
CODE_SIGN_IDENTITY="" \
|
||||||
|
DEVELOPMENT_TEAM="" \
|
||||||
|
build
|
||||||
|
|
||||||
|
# Desktop targets (macOS .dmg, Windows .exe, Linux) are not yet wired up in
|
||||||
|
# composeApp/build.gradle.kts. Add a `jvm("desktop")` target with the Compose
|
||||||
|
# Desktop plugin and matching `desktop` matrix jobs here once that lands.
|
||||||
303
.github/workflows/release.yml
vendored
Normal file
303
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,303 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
|
- 'v[0-9]+.[0-9]+.[0-9]+-*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare:
|
||||||
|
name: Prepare release metadata
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.version }}
|
||||||
|
tag: ${{ steps.version.outputs.tag }}
|
||||||
|
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
|
||||||
|
steps:
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
tag="${GITHUB_REF##*/}"
|
||||||
|
version="${tag#v}"
|
||||||
|
if [[ "$version" == *-* ]]; then
|
||||||
|
is_prerelease=true
|
||||||
|
else
|
||||||
|
is_prerelease=false
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo "tag=$tag"
|
||||||
|
echo "version=$version"
|
||||||
|
echo "is_prerelease=$is_prerelease"
|
||||||
|
} >>"$GITHUB_OUTPUT"
|
||||||
|
echo "Tag: $tag (version: $version, prerelease: $is_prerelease)"
|
||||||
|
|
||||||
|
android:
|
||||||
|
name: Android release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: prepare
|
||||||
|
timeout-minutes: 60
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Make gradlew executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
|
- name: Configure Android release signing
|
||||||
|
env:
|
||||||
|
KEYSTORE_BASE64: ${{ secrets.NUVIO_RELEASE_KEYSTORE_BASE64 }}
|
||||||
|
KEYSTORE_PASSWORD: ${{ secrets.NUVIO_RELEASE_STORE_PASSWORD }}
|
||||||
|
KEY_ALIAS: ${{ secrets.NUVIO_RELEASE_KEY_ALIAS }}
|
||||||
|
KEY_PASSWORD: ${{ secrets.NUVIO_RELEASE_KEY_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ -n "${KEYSTORE_BASE64:-}" ]]; then
|
||||||
|
keystore_path="$RUNNER_TEMP/nuvio-release.keystore"
|
||||||
|
printf '%s' "$KEYSTORE_BASE64" | base64 -d > "$keystore_path"
|
||||||
|
store_password="$KEYSTORE_PASSWORD"
|
||||||
|
key_alias="$KEY_ALIAS"
|
||||||
|
key_password="$KEY_PASSWORD"
|
||||||
|
echo "Using release keystore from secrets."
|
||||||
|
else
|
||||||
|
echo "::warning::Release signing secrets not set — generating an ephemeral debug-style keystore so the build can complete. APKs will not be installable over signed production builds."
|
||||||
|
keystore_path="$RUNNER_TEMP/nuvio-fallback.keystore"
|
||||||
|
store_password="android"
|
||||||
|
key_alias="androiddebugkey"
|
||||||
|
key_password="android"
|
||||||
|
keytool -genkeypair -v \
|
||||||
|
-keystore "$keystore_path" \
|
||||||
|
-storepass "$store_password" \
|
||||||
|
-keypass "$key_password" \
|
||||||
|
-alias "$key_alias" \
|
||||||
|
-keyalg RSA -keysize 2048 -validity 10000 \
|
||||||
|
-dname "CN=Android Debug,O=Android,C=US"
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "NUVIO_RELEASE_STORE_FILE=$keystore_path"
|
||||||
|
echo "NUVIO_RELEASE_STORE_PASSWORD=$store_password"
|
||||||
|
echo "NUVIO_RELEASE_KEY_ALIAS=$key_alias"
|
||||||
|
echo "NUVIO_RELEASE_KEY_PASSWORD=$key_password"
|
||||||
|
} >> local.properties
|
||||||
|
|
||||||
|
- name: Build per-ABI release APKs (full + playstore)
|
||||||
|
run: |
|
||||||
|
./gradlew \
|
||||||
|
:composeApp:assembleFullRelease \
|
||||||
|
:composeApp:assemblePlaystoreRelease \
|
||||||
|
-Pnuvio.splitAbi=true \
|
||||||
|
--stacktrace
|
||||||
|
|
||||||
|
- name: Stage and rename APK artifacts
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p artifacts
|
||||||
|
for flavor in full playstore; do
|
||||||
|
for abi in arm64-v8a armeabi-v7a x86_64; do
|
||||||
|
src=$(ls "composeApp/build/outputs/apk/${flavor}/release/composeApp-${flavor}-${abi}-release"*.apk 2>/dev/null | head -n1 || true)
|
||||||
|
if [[ -z "$src" ]]; then
|
||||||
|
echo "::error::Missing APK for ${flavor}/${abi}"
|
||||||
|
ls -la "composeApp/build/outputs/apk/${flavor}/release/" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dest="artifacts/Nuvio-${VERSION}-android-${flavor}-${abi}.apk"
|
||||||
|
cp "$src" "$dest"
|
||||||
|
echo " $src -> $dest"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
ls -la artifacts/
|
||||||
|
|
||||||
|
- name: Upload Android APK artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: android-apks
|
||||||
|
path: artifacts/*.apk
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
ios:
|
||||||
|
name: iOS release
|
||||||
|
runs-on: macos-15
|
||||||
|
needs: prepare
|
||||||
|
timeout-minutes: 90
|
||||||
|
env:
|
||||||
|
NUVIO_IOS_DISTRIBUTION: full
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Select latest stable Xcode
|
||||||
|
uses: maxim-lobanov/setup-xcode@v1
|
||||||
|
with:
|
||||||
|
xcode-version: latest-stable
|
||||||
|
|
||||||
|
- name: Make gradlew executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
|
# The Release Kotlin/Native link of the iOS framework regularly needs
|
||||||
|
# 8–10 GB of heap (Compose + Ktor + Supabase). Override at the user
|
||||||
|
# level so we don't have to raise the project default for local devs.
|
||||||
|
- name: Raise Gradle heap for Kotlin/Native release link
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p "$HOME/.gradle"
|
||||||
|
cat >> "$HOME/.gradle/gradle.properties" <<'EOF'
|
||||||
|
org.gradle.jvmargs=-Xmx10g -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=1g
|
||||||
|
kotlin.daemon.jvmargs=-Xmx4g
|
||||||
|
EOF
|
||||||
|
# Make sure no stale daemon is hanging around with the old args.
|
||||||
|
./gradlew --stop || true
|
||||||
|
|
||||||
|
- name: Archive iOS app (Release, unsigned)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
xcodebuild \
|
||||||
|
-project iosApp/iosApp.xcodeproj \
|
||||||
|
-scheme iosApp \
|
||||||
|
-configuration Release \
|
||||||
|
-destination 'generic/platform=iOS' \
|
||||||
|
-archivePath build/Nuvio.xcarchive \
|
||||||
|
-skipPackagePluginValidation \
|
||||||
|
-skipMacroValidation \
|
||||||
|
CODE_SIGNING_ALLOWED=NO \
|
||||||
|
CODE_SIGNING_REQUIRED=NO \
|
||||||
|
CODE_SIGN_IDENTITY="" \
|
||||||
|
DEVELOPMENT_TEAM="" \
|
||||||
|
archive
|
||||||
|
|
||||||
|
- name: Repackage .app into unsigned .ipa
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p artifacts build/Payload
|
||||||
|
app_path="build/Nuvio.xcarchive/Products/Applications/Nuvio.app"
|
||||||
|
if [[ ! -d "$app_path" ]]; then
|
||||||
|
echo "::error::Built .app not found at $app_path"
|
||||||
|
ls -laR build/Nuvio.xcarchive || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cp -R "$app_path" build/Payload/
|
||||||
|
ipa_name="Nuvio-${VERSION}-ios.ipa"
|
||||||
|
(
|
||||||
|
cd build
|
||||||
|
zip -ry "$ipa_name" Payload >/dev/null
|
||||||
|
)
|
||||||
|
mv "build/$ipa_name" "artifacts/$ipa_name"
|
||||||
|
ls -la artifacts/
|
||||||
|
|
||||||
|
- name: Upload iOS IPA artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ios-ipa
|
||||||
|
path: artifacts/*.ipa
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Publish GitHub release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [prepare, android, ios]
|
||||||
|
timeout-minutes: 15
|
||||||
|
steps:
|
||||||
|
- name: Download Android artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: android-apks
|
||||||
|
path: release-assets/
|
||||||
|
|
||||||
|
- name: Download iOS artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ios-ipa
|
||||||
|
path: release-assets/
|
||||||
|
|
||||||
|
- name: List release assets
|
||||||
|
run: ls -la release-assets/
|
||||||
|
|
||||||
|
- name: Compose release notes
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
|
TAG: ${{ needs.prepare.outputs.tag }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
base="https://github.com/${REPO}/releases/download/${TAG}"
|
||||||
|
link() {
|
||||||
|
local file="$1"
|
||||||
|
local label="$2"
|
||||||
|
if [[ -f "release-assets/$file" ]]; then
|
||||||
|
printf '[%s](%s/%s)' "$label" "$base" "$file"
|
||||||
|
else
|
||||||
|
printf '—'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
{
|
||||||
|
echo "## Nuvio ${VERSION}"
|
||||||
|
echo
|
||||||
|
echo "### Downloads"
|
||||||
|
echo
|
||||||
|
echo "| Architecture | Android (Full) | Android (Play Store) | iOS |"
|
||||||
|
echo "| --- | --- | --- | --- |"
|
||||||
|
printf '| arm64 | %s | %s | %s |\n' \
|
||||||
|
"$(link "Nuvio-${VERSION}-android-full-arm64-v8a.apk" "APK")" \
|
||||||
|
"$(link "Nuvio-${VERSION}-android-playstore-arm64-v8a.apk" "APK")" \
|
||||||
|
"$(link "Nuvio-${VERSION}-ios.ipa" "IPA")"
|
||||||
|
printf '| armeabi-v7a | %s | %s | — |\n' \
|
||||||
|
"$(link "Nuvio-${VERSION}-android-full-armeabi-v7a.apk" "APK")" \
|
||||||
|
"$(link "Nuvio-${VERSION}-android-playstore-armeabi-v7a.apk" "APK")"
|
||||||
|
printf '| x86_64 | %s | %s | — |\n' \
|
||||||
|
"$(link "Nuvio-${VERSION}-android-full-x86_64.apk" "APK")" \
|
||||||
|
"$(link "Nuvio-${VERSION}-android-playstore-x86_64.apk" "APK")"
|
||||||
|
echo
|
||||||
|
echo "### Notes"
|
||||||
|
echo
|
||||||
|
echo "- **Android (Full)** is the sideload-distribution flavor with the full feature set. **Android (Play Store)** matches the Play Store-distribution flavor."
|
||||||
|
echo "- The iOS .ipa is **unsigned** — install with AltStore, Sideloadly, or another sideloading tool."
|
||||||
|
echo "- Desktop builds (Windows / macOS / Linux) are not yet published from this workflow."
|
||||||
|
} > release-notes.md
|
||||||
|
echo "--- release notes ---"
|
||||||
|
cat release-notes.md
|
||||||
|
|
||||||
|
- name: Create GitHub release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
name: "Nuvio ${{ needs.prepare.outputs.version }}"
|
||||||
|
tag_name: ${{ needs.prepare.outputs.tag }}
|
||||||
|
body_path: release-notes.md
|
||||||
|
prerelease: ${{ needs.prepare.outputs.is_prerelease == 'true' }}
|
||||||
|
files: |
|
||||||
|
release-assets/*.apk
|
||||||
|
release-assets/*.ipa
|
||||||
|
fail_on_unmatched_files: true
|
||||||
|
|
@ -191,7 +191,10 @@ val generatedRuntimeConfigDir = layout.buildDirectory.dir("generated/runtime-con
|
||||||
|
|
||||||
val generateRuntimeConfigs = tasks.register<GenerateRuntimeConfigsTask>("generateRuntimeConfigs") {
|
val generateRuntimeConfigs = tasks.register<GenerateRuntimeConfigsTask>("generateRuntimeConfigs") {
|
||||||
outputDir.set(generatedRuntimeConfigDir)
|
outputDir.set(generatedRuntimeConfigDir)
|
||||||
localPropertiesFile.set(rootProject.layout.projectDirectory.file("local.properties"))
|
val localPropsFile = rootProject.file("local.properties")
|
||||||
|
if (localPropsFile.exists()) {
|
||||||
|
localPropertiesFile.set(localPropsFile)
|
||||||
|
}
|
||||||
appVersionName.set(releaseAppVersionName)
|
appVersionName.set(releaseAppVersionName)
|
||||||
appVersionCode.set(releaseAppVersionCode)
|
appVersionCode.set(releaseAppVersionCode)
|
||||||
}
|
}
|
||||||
|
|
@ -378,6 +381,14 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
isEnable = providers.gradleProperty("nuvio.splitAbi").orNull == "true"
|
||||||
|
reset()
|
||||||
|
include("arm64-v8a", "armeabi-v7a", "x86_64")
|
||||||
|
isUniversalApk = false
|
||||||
|
}
|
||||||
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit c10b71ab8b4d90796d4a795f775d337c29198ad0
|
|
||||||
1
vendor/quickjs-kt
vendored
1
vendor/quickjs-kt
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 57ce096200ac36bceb4e1ee5b6ec411b12357eb8
|
|
||||||
Loading…
Reference in a new issue