Build #56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| on: | |
| push: | |
| tags: | |
| - 'v[0-9]+.[0-9]+.[0-9]+' | |
| branches: | |
| - staging | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'App version string (e.g. 1.2.3)' | |
| required: true | |
| default: '0.0.1' | |
| build_number: | |
| description: 'Build number (integer)' | |
| required: true | |
| default: '1' | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: read | |
| container: | |
| image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:latest | |
| credentials: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p linux -a stack_wallet -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Create git_versions.dart stubs | |
| run: | | |
| mkdir -p crypto_plugins/flutter_libepiccash/lib | |
| mkdir -p crypto_plugins/flutter_libmwc/lib | |
| EPIC_TAG=$(git -C crypto_plugins/flutter_libepiccash describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| MWC_TAG=$(git -C crypto_plugins/flutter_libmwc describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| printf 'String getPluginVersion() => "%s";\n' "$EPIC_TAG" \ | |
| > crypto_plugins/flutter_libepiccash/lib/git_versions.dart | |
| printf 'String getPluginVersion() => "%s";\n' "$MWC_TAG" \ | |
| > crypto_plugins/flutter_libmwc/lib/git_versions.dart | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| env: | |
| USE_SYSTEM_SECURE_STORAGE_DEPS: "1" | |
| run: flutter build linux --release --verbose | |
| - name: Package | |
| run: | | |
| tar -czf "stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz" \ | |
| -C build/linux/x64/release bundle | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| path: stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| build-android: | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: read | |
| container: | |
| image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:android | |
| credentials: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p android -a stack_wallet -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Create git_versions.dart stubs | |
| run: | | |
| mkdir -p crypto_plugins/flutter_libepiccash/lib | |
| mkdir -p crypto_plugins/flutter_libmwc/lib | |
| EPIC_TAG=$(git -C crypto_plugins/flutter_libepiccash describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| MWC_TAG=$(git -C crypto_plugins/flutter_libmwc describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| printf 'String getPluginVersion() => "%s";\n' "$EPIC_TAG" \ | |
| > crypto_plugins/flutter_libepiccash/lib/git_versions.dart | |
| printf 'String getPluginVersion() => "%s";\n' "$MWC_TAG" \ | |
| > crypto_plugins/flutter_libmwc/lib/git_versions.dart | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Set up Android local.properties | |
| run: | | |
| cat > android/local.properties <<EOF | |
| sdk.dir=${ANDROID_SDK_ROOT} | |
| flutter.sdk=${FLUTTER_HOME} | |
| EOF | |
| - name: Set up signing | |
| env: | |
| KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| run: | | |
| printf '%s' "$KEYSTORE_BASE64" | base64 --decode > android/keystore-orig.jks | |
| [ -s android/keystore-orig.jks ] || { echo "ERROR: ANDROID_KEYSTORE_BASE64 secret is empty or not set"; exit 1; } | |
| keytool -importkeystore \ | |
| -srckeystore android/keystore-orig.jks \ | |
| -destkeystore android/keystore.jks \ | |
| -deststoretype pkcs12 \ | |
| -srcstorepass "${{ secrets.ANDROID_STORE_PASSWORD }}" \ | |
| -deststorepass "${{ secrets.ANDROID_STORE_PASSWORD }}" \ | |
| -noprompt \ | |
| -J-Dkeystore.pkcs12.legacy | |
| rm android/keystore-orig.jks | |
| cat > android/key.properties <<EOF | |
| storeFile=../keystore.jks | |
| storePassword=${{ secrets.ANDROID_STORE_PASSWORD }} | |
| keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }} | |
| keyAlias=${{ secrets.ANDROID_KEY_ALIAS }} | |
| EOF | |
| - name: Build APKs | |
| run: flutter build apk --split-per-abi --release | |
| - name: Build AAB | |
| run: flutter build appbundle --release | |
| - name: Collect artifacts | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| mkdir -p android-artifacts | |
| cp build/app/outputs/flutter-apk/app-arm64-v8a-release.apk \ | |
| android-artifacts/stack_wallet-android-arm64-v8a-${VERSION}.apk | |
| cp build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk \ | |
| android-artifacts/stack_wallet-android-armeabi-v7a-${VERSION}.apk | |
| cp build/app/outputs/flutter-apk/app-x86_64-release.apk \ | |
| android-artifacts/stack_wallet-android-x86_64-${VERSION}.apk | |
| cp build/app/outputs/bundle/release/app-release.aab \ | |
| android-artifacts/stack_wallet-android-${VERSION}.aab | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-android-${{ steps.ver.outputs.version }} | |
| path: android-artifacts/ | |
| build-windows: | |
| runs-on: windows-2022 | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Flutter doctor | |
| run: flutter doctor -v | |
| - name: Configure app | |
| env: | |
| MWEBD_FETCH: '1' | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p windows -a stack_wallet -d -s | |
| # The Actions windows-2022 runner user lacks SeCreateSymbolicLinkPrivilege, | |
| # so link_assets.sh's mklink /D calls either fail or produce broken reparse | |
| # points that Flutter's asset resolver cannot traverse. Replace each of | |
| # the five gitignored asset directories with real copies instead. | |
| - name: Replace asset symlinks with copies (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| for dirname in default_themes icon lottie in_app_logo_icons svg; do | |
| target="assets/${dirname}" | |
| source="asset_sources/${dirname}/stack_wallet" | |
| # Remove whatever link_assets.sh left (reparse point, symlink, or nothing). | |
| # cmd.exe rmdir on a junction/symlink removes the link, not the target. | |
| if [ -e "$target" ] || [ -L "$target" ]; then | |
| cmd.exe /c rmdir "$(cygpath -w "$target")" 2>/dev/null || rm -rf "$target" | |
| fi | |
| mkdir -p "$target" | |
| cp -r "${source}/." "$target/" | |
| done | |
| - name: Get dependencies | |
| run: flutter pub get | |
| # Stack Wallet uses mwebd.exe as a subprocess on Windows, not the FFI | |
| # DLL, so we don't need libmwebd.dll. The upstream plugin's Windows | |
| # build path requires WSL, which the GitHub runner lacks. | |
| - name: Patch flutter_mwebd to skip Windows FFI build (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| cache_root="$(cygpath -u "$LOCALAPPDATA")/Pub/Cache/hosted/pub.dev" | |
| plugin_dir=$(find "$cache_root" -maxdepth 1 -type d -name 'flutter_mwebd-*' -print -quit) | |
| if [ -z "$plugin_dir" ] || [ ! -f "$plugin_dir/pubspec.yaml" ]; then | |
| echo "::error::Could not locate flutter_mwebd in $cache_root" | |
| exit 1 | |
| fi | |
| pubspec="$plugin_dir/pubspec.yaml" | |
| echo "Patching $pubspec" | |
| sed -i '/^ windows:$/,/^ ffiPlugin: true$/d' "$pubspec" | |
| flutter pub get | |
| - name: Create git_versions.dart stubs | |
| run: | | |
| mkdir -p crypto_plugins/flutter_libepiccash/lib | |
| mkdir -p crypto_plugins/flutter_libmwc/lib | |
| EPIC_TAG=$(git -C crypto_plugins/flutter_libepiccash describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| MWC_TAG=$(git -C crypto_plugins/flutter_libmwc describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| printf 'String getPluginVersion() => "%s";\n' "$EPIC_TAG" \ | |
| > crypto_plugins/flutter_libepiccash/lib/git_versions.dart | |
| printf 'String getPluginVersion() => "%s";\n' "$MWC_TAG" \ | |
| > crypto_plugins/flutter_libmwc/lib/git_versions.dart | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build secp256k1.dll for Windows | |
| run: dart run coinlib:build_windows | |
| - name: Build | |
| run: flutter build windows --release | |
| - name: Package | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path "build/windows/x64/runner/Release/*" ` | |
| -DestinationPath "stack_wallet-windows-x86_64-${{ steps.ver.outputs.version }}.zip" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-windows-x86_64-${{ steps.ver.outputs.version }}.zip | |
| path: stack_wallet-windows-x86_64-${{ steps.ver.outputs.version }}.zip | |
| build-macos: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p macos -a stack_wallet -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Create git_versions.dart stubs | |
| run: | | |
| mkdir -p crypto_plugins/flutter_libepiccash/lib | |
| mkdir -p crypto_plugins/flutter_libmwc/lib | |
| EPIC_TAG=$(git -C crypto_plugins/flutter_libepiccash describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| MWC_TAG=$(git -C crypto_plugins/flutter_libmwc describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| printf 'String getPluginVersion() => "%s";\n' "$EPIC_TAG" \ | |
| > crypto_plugins/flutter_libepiccash/lib/git_versions.dart | |
| printf 'String getPluginVersion() => "%s";\n' "$MWC_TAG" \ | |
| > crypto_plugins/flutter_libmwc/lib/git_versions.dart | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| run: flutter build macos --release | |
| - name: Package | |
| run: | | |
| cd "build/macos/Build/Products/Release" | |
| zip -r "$GITHUB_WORKSPACE/stack_wallet-macos-aarch64-${{ steps.ver.outputs.version }}.zip" \ | |
| "Stack Wallet.app" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-macos-aarch64-${{ steps.ver.outputs.version }}.zip | |
| path: stack_wallet-macos-aarch64-${{ steps.ver.outputs.version }}.zip | |
| build-ios: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| targets: aarch64-apple-ios | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p ios -a stack_wallet -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Create git_versions.dart stubs | |
| run: | | |
| mkdir -p crypto_plugins/flutter_libepiccash/lib | |
| mkdir -p crypto_plugins/flutter_libmwc/lib | |
| EPIC_TAG=$(git -C crypto_plugins/flutter_libepiccash describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| MWC_TAG=$(git -C crypto_plugins/flutter_libmwc describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| printf 'String getPluginVersion() => "%s";\n' "$EPIC_TAG" \ | |
| > crypto_plugins/flutter_libepiccash/lib/git_versions.dart | |
| printf 'String getPluginVersion() => "%s";\n' "$MWC_TAG" \ | |
| > crypto_plugins/flutter_libmwc/lib/git_versions.dart | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| run: flutter build ios --release --no-codesign | |
| - name: Package IPA | |
| run: | | |
| mkdir Payload | |
| cp -r build/ios/iphoneos/Runner.app Payload/ | |
| zip -r "stack_wallet-ios-aarch64-${{ steps.ver.outputs.version }}.ipa" Payload/ | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-ios-aarch64-${{ steps.ver.outputs.version }}.ipa | |
| path: stack_wallet-ios-aarch64-${{ steps.ver.outputs.version }}.ipa | |
| build-campfire-linux: | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: read | |
| container: | |
| image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:latest | |
| credentials: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p linux -a campfire -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| env: | |
| USE_SYSTEM_SECURE_STORAGE_DEPS: "1" | |
| run: flutter build linux --release --verbose | |
| - name: Package | |
| run: | | |
| tar -czf "campfire-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz" \ | |
| -C build/linux/x64/release bundle | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| path: campfire-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| build-stack-duo-linux: | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: read | |
| container: | |
| image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:latest | |
| credentials: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p linux -a stack_duo -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| env: | |
| USE_SYSTEM_SECURE_STORAGE_DEPS: "1" | |
| run: flutter build linux --release --verbose | |
| - name: Package | |
| run: | | |
| tar -czf "stack_duo-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz" \ | |
| -C build/linux/x64/release bundle | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| path: stack_duo-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| build-flatpak: | |
| runs-on: ubuntu-24.04 | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download Linux bundle | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| - name: Stage bundle and icon | |
| run: | | |
| tar -xzf "stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz" -C flatpak/ | |
| cp asset_sources/icon/stack_wallet/icon.png flatpak/com.cypherstack.stackwallet.png | |
| - name: Install Flatpak tools | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y flatpak flatpak-builder | |
| - name: Set up Flathub remote | |
| run: flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| - name: Cache Flatpak SDK | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.local/share/flatpak | |
| key: flatpak-freedesktop-24.08-v1 | |
| - name: Install Flatpak SDK | |
| run: | | |
| flatpak install --user --noninteractive flathub \ | |
| org.freedesktop.Platform//24.08 \ | |
| org.freedesktop.Sdk//24.08 | |
| - name: Build Flatpak | |
| run: | | |
| flatpak-builder --user --force-clean \ | |
| --repo=flatpak-repo \ | |
| build-flatpak flatpak/com.cypherstack.stackwallet.yaml | |
| - name: Bundle Flatpak | |
| run: | | |
| flatpak build-bundle flatpak-repo \ | |
| --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \ | |
| "stack_wallet-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak" \ | |
| com.cypherstack.stackwallet | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak | |
| path: stack_wallet-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak | |
| build-appimage: | |
| runs-on: ubuntu-24.04 | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download Linux bundle | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| - name: Install AppImage tools | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y squashfs-tools | |
| - name: Build AppImage | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| tar -xzf "stack_wallet-linux-x86_64-${VERSION}.tar.gz" | |
| mkdir -p AppDir | |
| cp -r bundle/* AppDir/ | |
| cp appimage/stack_wallet/AppRun AppDir/AppRun | |
| chmod +x AppDir/AppRun | |
| cp appimage/stack_wallet/stack_wallet.desktop AppDir/ | |
| cp asset_sources/icon/stack_wallet/icon.png AppDir/stack_wallet.png | |
| curl -fsSL -o appimagetool \ | |
| https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage | |
| chmod +x appimagetool | |
| ARCH=x86_64 ./appimagetool --appimage-extract-and-run AppDir \ | |
| "stack_wallet-appimage-x86_64-${VERSION}.AppImage" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-appimage-x86_64-${{ steps.ver.outputs.version }}.AppImage | |
| path: stack_wallet-appimage-x86_64-${{ steps.ver.outputs.version }}.AppImage | |
| build-campfire-android: | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: read | |
| container: | |
| image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:android | |
| credentials: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p android -a campfire -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Set up Android local.properties | |
| run: | | |
| cat > android/local.properties <<EOF | |
| sdk.dir=${ANDROID_SDK_ROOT} | |
| flutter.sdk=${FLUTTER_HOME} | |
| EOF | |
| - name: Set up signing | |
| env: | |
| KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| run: | | |
| printf '%s' "$KEYSTORE_BASE64" | base64 --decode > android/keystore-orig.jks | |
| [ -s android/keystore-orig.jks ] || { echo "ERROR: ANDROID_KEYSTORE_BASE64 secret is empty or not set"; exit 1; } | |
| keytool -importkeystore \ | |
| -srckeystore android/keystore-orig.jks \ | |
| -destkeystore android/keystore.jks \ | |
| -deststoretype pkcs12 \ | |
| -srcstorepass "${{ secrets.ANDROID_STORE_PASSWORD }}" \ | |
| -deststorepass "${{ secrets.ANDROID_STORE_PASSWORD }}" \ | |
| -noprompt \ | |
| -J-Dkeystore.pkcs12.legacy | |
| rm android/keystore-orig.jks | |
| cat > android/key.properties <<EOF | |
| storeFile=../keystore.jks | |
| storePassword=${{ secrets.ANDROID_STORE_PASSWORD }} | |
| keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }} | |
| keyAlias=${{ secrets.ANDROID_KEY_ALIAS }} | |
| EOF | |
| - name: Build APKs | |
| run: flutter build apk --split-per-abi --release | |
| - name: Build AAB | |
| run: flutter build appbundle --release | |
| - name: Collect artifacts | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| mkdir -p android-artifacts | |
| cp build/app/outputs/flutter-apk/app-arm64-v8a-release.apk \ | |
| android-artifacts/campfire-android-arm64-v8a-${VERSION}.apk | |
| cp build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk \ | |
| android-artifacts/campfire-android-armeabi-v7a-${VERSION}.apk | |
| cp build/app/outputs/flutter-apk/app-x86_64-release.apk \ | |
| android-artifacts/campfire-android-x86_64-${VERSION}.apk | |
| cp build/app/outputs/bundle/release/app-release.aab \ | |
| android-artifacts/campfire-android-${VERSION}.aab | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-android-${{ steps.ver.outputs.version }} | |
| path: android-artifacts/ | |
| build-campfire-windows: | |
| runs-on: windows-2022 | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Flutter doctor | |
| run: flutter doctor -v | |
| - name: Install Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p windows -a campfire -d -s | |
| - name: Replace asset symlinks with copies (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| for dirname in default_themes icon lottie in_app_logo_icons svg; do | |
| target="assets/${dirname}" | |
| source="asset_sources/${dirname}/campfire" | |
| if [ -e "$target" ] || [ -L "$target" ]; then | |
| cmd.exe /c rmdir "$(cygpath -w "$target")" 2>/dev/null || rm -rf "$target" | |
| fi | |
| mkdir -p "$target" | |
| cp -r "${source}/." "$target/" | |
| done | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build secp256k1.dll for Windows | |
| run: dart run coinlib:build_windows | |
| - name: Build | |
| run: flutter build windows --release | |
| - name: Package | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path "build/windows/x64/runner/Release/*" ` | |
| -DestinationPath "campfire-windows-x86_64-${{ steps.ver.outputs.version }}.zip" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-windows-x86_64-${{ steps.ver.outputs.version }}.zip | |
| path: campfire-windows-x86_64-${{ steps.ver.outputs.version }}.zip | |
| build-campfire-macos: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Install Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p macos -a campfire -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| run: flutter build macos --release | |
| - name: Package | |
| run: | | |
| cd "build/macos/Build/Products/Release" | |
| zip -r "$GITHUB_WORKSPACE/campfire-macos-aarch64-${{ steps.ver.outputs.version }}.zip" \ | |
| "Campfire.app" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-macos-aarch64-${{ steps.ver.outputs.version }}.zip | |
| path: campfire-macos-aarch64-${{ steps.ver.outputs.version }}.zip | |
| build-campfire-ios: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| targets: aarch64-apple-ios | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Install additional Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| rustup target add aarch64-apple-ios --toolchain 1.89.0 | |
| rustup target add x86_64-apple-ios --toolchain 1.89.0 | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p ios -a campfire -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| run: flutter build ios --release --no-codesign | |
| - name: Package IPA | |
| run: | | |
| mkdir Payload | |
| cp -r build/ios/iphoneos/Runner.app Payload/ | |
| zip -r "campfire-ios-aarch64-${{ steps.ver.outputs.version }}.ipa" Payload/ | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-ios-aarch64-${{ steps.ver.outputs.version }}.ipa | |
| path: campfire-ios-aarch64-${{ steps.ver.outputs.version }}.ipa | |
| build-campfire-flatpak: | |
| runs-on: ubuntu-24.04 | |
| needs: build-campfire-linux | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download Linux bundle | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: campfire-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| - name: Stage bundle and icon | |
| run: | | |
| tar -xzf "campfire-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz" -C flatpak/ | |
| cp asset_sources/icon/campfire/icon.png flatpak/com.cypherstack.campfire.png | |
| - name: Install Flatpak tools | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y flatpak flatpak-builder | |
| - name: Set up Flathub remote | |
| run: flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| - name: Cache Flatpak SDK | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.local/share/flatpak | |
| key: flatpak-freedesktop-24.08-v1 | |
| - name: Install Flatpak SDK | |
| run: | | |
| flatpak install --user --noninteractive flathub \ | |
| org.freedesktop.Platform//24.08 \ | |
| org.freedesktop.Sdk//24.08 | |
| - name: Build Flatpak | |
| run: | | |
| flatpak-builder --user --force-clean \ | |
| --repo=flatpak-repo \ | |
| build-flatpak flatpak/com.cypherstack.campfire.yaml | |
| - name: Bundle Flatpak | |
| run: | | |
| flatpak build-bundle flatpak-repo \ | |
| --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \ | |
| "campfire-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak" \ | |
| com.cypherstack.campfire | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak | |
| path: campfire-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak | |
| build-campfire-appimage: | |
| runs-on: ubuntu-24.04 | |
| needs: build-campfire-linux | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download Linux bundle | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: campfire-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| - name: Install AppImage tools | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y squashfs-tools | |
| - name: Build AppImage | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| tar -xzf "campfire-linux-x86_64-${VERSION}.tar.gz" | |
| mkdir -p AppDir | |
| cp -r bundle/* AppDir/ | |
| cp appimage/campfire/AppRun AppDir/AppRun | |
| chmod +x AppDir/AppRun | |
| cp appimage/campfire/campfire.desktop AppDir/ | |
| cp asset_sources/icon/campfire/icon.png AppDir/campfire.png | |
| curl -fsSL -o appimagetool \ | |
| https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage | |
| chmod +x appimagetool | |
| ARCH=x86_64 ./appimagetool --appimage-extract-and-run AppDir \ | |
| "campfire-appimage-x86_64-${VERSION}.AppImage" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-appimage-x86_64-${{ steps.ver.outputs.version }}.AppImage | |
| path: campfire-appimage-x86_64-${{ steps.ver.outputs.version }}.AppImage | |
| build-stack-duo-android: | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: read | |
| container: | |
| image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:android | |
| credentials: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p android -a stack_duo -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Set up Android local.properties | |
| run: | | |
| cat > android/local.properties <<EOF | |
| sdk.dir=${ANDROID_SDK_ROOT} | |
| flutter.sdk=${FLUTTER_HOME} | |
| EOF | |
| - name: Set up signing | |
| env: | |
| KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| run: | | |
| printf '%s' "$KEYSTORE_BASE64" | base64 --decode > android/keystore-orig.jks | |
| [ -s android/keystore-orig.jks ] || { echo "ERROR: ANDROID_KEYSTORE_BASE64 secret is empty or not set"; exit 1; } | |
| keytool -importkeystore \ | |
| -srckeystore android/keystore-orig.jks \ | |
| -destkeystore android/keystore.jks \ | |
| -deststoretype pkcs12 \ | |
| -srcstorepass "${{ secrets.ANDROID_STORE_PASSWORD }}" \ | |
| -deststorepass "${{ secrets.ANDROID_STORE_PASSWORD }}" \ | |
| -noprompt \ | |
| -J-Dkeystore.pkcs12.legacy | |
| rm android/keystore-orig.jks | |
| cat > android/key.properties <<EOF | |
| storeFile=../keystore.jks | |
| storePassword=${{ secrets.ANDROID_STORE_PASSWORD }} | |
| keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }} | |
| keyAlias=${{ secrets.ANDROID_KEY_ALIAS }} | |
| EOF | |
| - name: Build APKs | |
| run: flutter build apk --split-per-abi --release | |
| - name: Build AAB | |
| run: flutter build appbundle --release | |
| - name: Collect artifacts | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| mkdir -p android-artifacts | |
| cp build/app/outputs/flutter-apk/app-arm64-v8a-release.apk \ | |
| android-artifacts/stack_duo-android-arm64-v8a-${VERSION}.apk | |
| cp build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk \ | |
| android-artifacts/stack_duo-android-armeabi-v7a-${VERSION}.apk | |
| cp build/app/outputs/flutter-apk/app-x86_64-release.apk \ | |
| android-artifacts/stack_duo-android-x86_64-${VERSION}.apk | |
| cp build/app/outputs/bundle/release/app-release.aab \ | |
| android-artifacts/stack_duo-android-${VERSION}.aab | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-android-${{ steps.ver.outputs.version }} | |
| path: android-artifacts/ | |
| build-stack-duo-windows: | |
| runs-on: windows-2022 | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Flutter doctor | |
| run: flutter doctor -v | |
| - name: Install Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p windows -a stack_duo -d -s | |
| - name: Replace asset symlinks with copies (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| for dirname in default_themes icon lottie in_app_logo_icons svg; do | |
| target="assets/${dirname}" | |
| source="asset_sources/${dirname}/stack_duo" | |
| if [ -e "$target" ] || [ -L "$target" ]; then | |
| cmd.exe /c rmdir "$(cygpath -w "$target")" 2>/dev/null || rm -rf "$target" | |
| fi | |
| mkdir -p "$target" | |
| cp -r "${source}/." "$target/" | |
| done | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build secp256k1.dll for Windows | |
| run: dart run coinlib:build_windows | |
| - name: Build | |
| run: flutter build windows --release | |
| - name: Package | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path "build/windows/x64/runner/Release/*" ` | |
| -DestinationPath "stack_duo-windows-x86_64-${{ steps.ver.outputs.version }}.zip" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-windows-x86_64-${{ steps.ver.outputs.version }}.zip | |
| path: stack_duo-windows-x86_64-${{ steps.ver.outputs.version }}.zip | |
| build-windows-arm: | |
| runs-on: windows-11-arm | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| # Flutter only publishes x64 Windows SDK binaries; architecture: x64 forces | |
| # the action to fetch the x64 SDK which runs via emulation on the ARM64 host. | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| architecture: x64 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Install Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| rustup target add --toolchain 1.89.0 aarch64-pc-windows-msvc | |
| rustup target add --toolchain 1.85.1 aarch64-pc-windows-msvc | |
| - name: Flutter doctor | |
| run: flutter doctor -v | |
| - name: Configure app | |
| env: | |
| # configure_stack_wallet.sh calls build_standalone_mwebd_windows.dart | |
| # without --fetch by default, which tries to build mwebd.exe from source | |
| # via WSL + CGO. On ARM64 the WSL host is ARM64 but the x64 MinGW | |
| # assembler can't compile Go's gcc_arm64.S. Fetch the pre-built x64 | |
| # binary instead — it runs fine as a subprocess under x64 emulation. | |
| MWEBD_FETCH: '1' | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p windows -a stack_wallet -i -s | |
| - name: Replace asset symlinks with copies (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| for dirname in default_themes icon lottie in_app_logo_icons svg; do | |
| target="assets/${dirname}" | |
| source="asset_sources/${dirname}/stack_wallet" | |
| if [ -e "$target" ] || [ -L "$target" ]; then | |
| cmd.exe /c rmdir "$(cygpath -w "$target")" 2>/dev/null || rm -rf "$target" | |
| fi | |
| mkdir -p "$target" | |
| cp -r "${source}/." "$target/" | |
| done | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Patch flutter_mwebd to skip Windows FFI build (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| cache_root="$(cygpath -u "$LOCALAPPDATA")/Pub/Cache/hosted/pub.dev" | |
| plugin_dir=$(find "$cache_root" -maxdepth 1 -type d -name 'flutter_mwebd-*' -print -quit) | |
| if [ -z "$plugin_dir" ] || [ ! -f "$plugin_dir/pubspec.yaml" ]; then | |
| echo "::error::Could not locate flutter_mwebd in $cache_root" | |
| exit 1 | |
| fi | |
| pubspec="$plugin_dir/pubspec.yaml" | |
| echo "Patching $pubspec" | |
| sed -i '/^ windows:$/,/^ ffiPlugin: true$/d' "$pubspec" | |
| flutter pub get | |
| - name: Build flutter_libepiccash for Windows ARM64 | |
| run: | | |
| set -euo pipefail | |
| cd crypto_plugins/flutter_libepiccash/rust | |
| cargo +1.89.0 build --target aarch64-pc-windows-msvc --release --lib | |
| mkdir -p ../scripts/windows/build | |
| # Cargo may output to target/release/ instead of target/<triple>/release/ | |
| # when --target matches the native host. Search both locations. | |
| DLL="$(find target -name 'epic_cash_wallet.dll' -path '*/release/*' | head -1)" | |
| [ -n "$DLL" ] || { echo "epic_cash_wallet.dll not found"; exit 1; } | |
| cp "$DLL" ../scripts/windows/build/libepic_cash_wallet.dll | |
| - name: Build flutter_libmwc for Windows ARM64 | |
| run: | | |
| set -euo pipefail | |
| cd crypto_plugins/flutter_libmwc/rust | |
| cargo +1.85.1 build --target aarch64-pc-windows-msvc --release --lib | |
| mkdir -p ../scripts/windows/build | |
| DLL="$(find target -name 'mwc_wallet.dll' -path '*/release/*' | head -1)" | |
| [ -n "$DLL" ] || { echo "mwc_wallet.dll not found"; exit 1; } | |
| cp "$DLL" ../scripts/windows/build/libmwc_wallet.dll | |
| - name: Build frostdart for Windows ARM64 | |
| run: | | |
| set -euo pipefail | |
| cd crypto_plugins/frostdart/src/serai/hrf | |
| cargo +1.89.0 build --target aarch64-pc-windows-msvc --release --lib | |
| mkdir -p ../../../scripts/windows/build | |
| DLL="$(find target -name 'hrf_api.dll' -path '*/release/*' | head -1)" | |
| [ -n "$DLL" ] || { echo "hrf_api.dll not found"; exit 1; } | |
| cp "$DLL" ../../../scripts/windows/build/frostdart.dll | |
| - name: Create git_versions.dart stubs | |
| run: | | |
| mkdir -p crypto_plugins/flutter_libepiccash/lib | |
| mkdir -p crypto_plugins/flutter_libmwc/lib | |
| EPIC_TAG=$(git -C crypto_plugins/flutter_libepiccash describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| MWC_TAG=$(git -C crypto_plugins/flutter_libmwc describe --tags --exact-match HEAD 2>/dev/null || echo "dev") | |
| printf 'String getPluginVersion() => "%s";\n' "$EPIC_TAG" \ | |
| > crypto_plugins/flutter_libepiccash/lib/git_versions.dart | |
| printf 'String getPluginVersion() => "%s";\n' "$MWC_TAG" \ | |
| > crypto_plugins/flutter_libmwc/lib/git_versions.dart | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| # coinlib's windows/CMakeLists.txt builds secp256k1 via cmake ExternalProject | |
| # during flutter build windows. dart run coinlib:build_windows is skipped | |
| # because it hardcodes -A x64. | |
| - name: Build | |
| run: flutter build windows --release | |
| - name: Package | |
| shell: pwsh | |
| run: | | |
| # Flutter outputs to arm64/ when it detects native ARM64, x64/ otherwise | |
| # (x64 SDK via emulation on ARM64 runner may report either arch). | |
| $releaseDir = if (Test-Path "build/windows/arm64/runner/Release") { | |
| "build/windows/arm64/runner/Release" | |
| } else { | |
| "build/windows/x64/runner/Release" | |
| } | |
| Compress-Archive -Path "$releaseDir/*" ` | |
| -DestinationPath "stack_wallet-windows-arm64-${{ steps.ver.outputs.version }}.zip" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_wallet-windows-arm64-${{ steps.ver.outputs.version }}.zip | |
| path: stack_wallet-windows-arm64-${{ steps.ver.outputs.version }}.zip | |
| build-campfire-windows-arm: | |
| runs-on: windows-11-arm | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| # Flutter only publishes x64 Windows SDK binaries; architecture: x64 forces | |
| # the action to fetch the x64 SDK which runs via emulation on the ARM64 host. | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| architecture: x64 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Flutter doctor | |
| run: flutter doctor -v | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p windows -a campfire -d -s | |
| - name: Replace asset symlinks with copies (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| for dirname in default_themes icon lottie in_app_logo_icons svg; do | |
| target="assets/${dirname}" | |
| source="asset_sources/${dirname}/campfire" | |
| if [ -e "$target" ] || [ -L "$target" ]; then | |
| cmd.exe /c rmdir "$(cygpath -w "$target")" 2>/dev/null || rm -rf "$target" | |
| fi | |
| mkdir -p "$target" | |
| cp -r "${source}/." "$target/" | |
| done | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| # coinlib's windows/CMakeLists.txt builds secp256k1 via cmake ExternalProject | |
| # during flutter build windows. dart run coinlib:build_windows is skipped | |
| # because it hardcodes -A x64. | |
| - name: Build | |
| run: flutter build windows --release | |
| - name: Package | |
| shell: pwsh | |
| run: | | |
| $releaseDir = if (Test-Path "build/windows/arm64/runner/Release") { | |
| "build/windows/arm64/runner/Release" | |
| } else { | |
| "build/windows/x64/runner/Release" | |
| } | |
| Compress-Archive -Path "$releaseDir/*" ` | |
| -DestinationPath "campfire-windows-arm64-${{ steps.ver.outputs.version }}.zip" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: campfire-windows-arm64-${{ steps.ver.outputs.version }}.zip | |
| path: campfire-windows-arm64-${{ steps.ver.outputs.version }}.zip | |
| build-stack-duo-windows-arm: | |
| runs-on: windows-11-arm | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| # Flutter only publishes x64 Windows SDK binaries; architecture: x64 forces | |
| # the action to fetch the x64 SDK which runs via emulation on the ARM64 host. | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| architecture: x64 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Install Rust toolchains | |
| run: | | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| rustup target add --toolchain 1.89.0 aarch64-pc-windows-msvc | |
| - name: Flutter doctor | |
| run: flutter doctor -v | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p windows -a stack_duo -i -s | |
| - name: Replace asset symlinks with copies (CI workaround) | |
| run: | | |
| set -euo pipefail | |
| for dirname in default_themes icon lottie in_app_logo_icons svg; do | |
| target="assets/${dirname}" | |
| source="asset_sources/${dirname}/stack_duo" | |
| if [ -e "$target" ] || [ -L "$target" ]; then | |
| cmd.exe /c rmdir "$(cygpath -w "$target")" 2>/dev/null || rm -rf "$target" | |
| fi | |
| mkdir -p "$target" | |
| cp -r "${source}/." "$target/" | |
| done | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Build frostdart for Windows ARM64 | |
| run: | | |
| set -euo pipefail | |
| cd crypto_plugins/frostdart/src/serai/hrf | |
| cargo +1.89.0 build --target aarch64-pc-windows-msvc --release --lib | |
| mkdir -p ../../../scripts/windows/build | |
| DLL="$(find target -name 'hrf_api.dll' -path '*/release/*' | head -1)" | |
| [ -n "$DLL" ] || { echo "hrf_api.dll not found"; exit 1; } | |
| cp "$DLL" ../../../scripts/windows/build/frostdart.dll | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| # coinlib's windows/CMakeLists.txt builds secp256k1 via cmake ExternalProject | |
| # during flutter build windows. dart run coinlib:build_windows is skipped | |
| # because it hardcodes -A x64. | |
| - name: Build | |
| run: flutter build windows --release | |
| - name: Package | |
| shell: pwsh | |
| run: | | |
| $releaseDir = if (Test-Path "build/windows/arm64/runner/Release") { | |
| "build/windows/arm64/runner/Release" | |
| } else { | |
| "build/windows/x64/runner/Release" | |
| } | |
| Compress-Archive -Path "$releaseDir/*" ` | |
| -DestinationPath "stack_duo-windows-arm64-${{ steps.ver.outputs.version }}.zip" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-windows-arm64-${{ steps.ver.outputs.version }}.zip | |
| path: stack_duo-windows-arm64-${{ steps.ver.outputs.version }}.zip | |
| build-stack-duo-macos: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Install Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| rustup target add aarch64-apple-darwin --toolchain 1.89.0 | |
| cargo install cargo-lipo | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p macos -a stack_duo -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| run: flutter build macos --release | |
| - name: Package | |
| run: | | |
| cd "build/macos/Build/Products/Release" | |
| zip -r "$GITHUB_WORKSPACE/stack_duo-macos-aarch64-${{ steps.ver.outputs.version }}.zip" \ | |
| "Stack Duo.app" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-macos-aarch64-${{ steps.ver.outputs.version }}.zip | |
| path: stack_duo-macos-aarch64-${{ steps.ver.outputs.version }}.zip | |
| build-stack-duo-ios: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| BUILD_NUMBER="${{ inputs.build_number }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| BUILD_NUMBER="${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| targets: aarch64-apple-ios | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.1' | |
| channel: 'stable' | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.24.13' | |
| - name: Install additional Rust toolchains | |
| run: | | |
| rustup toolchain install 1.85.1 | |
| rustup toolchain install 1.89.0 | |
| rustup default 1.89.0 | |
| rustup target add aarch64-apple-ios --toolchain 1.89.0 | |
| rustup target add x86_64-apple-ios --toolchain 1.89.0 | |
| - name: Configure app | |
| run: | | |
| cd scripts | |
| echo "yes" | ./build_app.sh \ | |
| -v "${{ steps.ver.outputs.version }}" \ | |
| -b "${{ steps.ver.outputs.build_number }}" \ | |
| -p ios -a stack_duo -d -s | |
| - name: Get dependencies | |
| run: flutter pub get | |
| - name: Decode secrets | |
| env: | |
| CHANGE_NOW: ${{ secrets.CHANGE_NOW }} | |
| run: echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart | |
| - name: Build | |
| run: flutter build ios --release --no-codesign | |
| - name: Package IPA | |
| run: | | |
| mkdir Payload | |
| cp -r build/ios/iphoneos/Runner.app Payload/ | |
| zip -r "stack_duo-ios-aarch64-${{ steps.ver.outputs.version }}.ipa" Payload/ | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-ios-aarch64-${{ steps.ver.outputs.version }}.ipa | |
| path: stack_duo-ios-aarch64-${{ steps.ver.outputs.version }}.ipa | |
| build-stack-duo-flatpak: | |
| runs-on: ubuntu-24.04 | |
| needs: build-stack-duo-linux | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download Linux bundle | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: stack_duo-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| - name: Stage bundle and icon | |
| run: | | |
| tar -xzf "stack_duo-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz" -C flatpak/ | |
| cp asset_sources/icon/stack_duo/icon.png flatpak/com.cypherstack.stackduo.png | |
| - name: Install Flatpak tools | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y flatpak flatpak-builder | |
| - name: Set up Flathub remote | |
| run: flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| - name: Cache Flatpak SDK | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.local/share/flatpak | |
| key: flatpak-freedesktop-24.08-v1 | |
| - name: Install Flatpak SDK | |
| run: | | |
| flatpak install --user --noninteractive flathub \ | |
| org.freedesktop.Platform//24.08 \ | |
| org.freedesktop.Sdk//24.08 | |
| - name: Build Flatpak | |
| run: | | |
| flatpak-builder --user --force-clean \ | |
| --repo=flatpak-repo \ | |
| build-flatpak flatpak/com.cypherstack.stackduo.yaml | |
| - name: Bundle Flatpak | |
| run: | | |
| flatpak build-bundle flatpak-repo \ | |
| --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \ | |
| "stack_duo-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak" \ | |
| com.cypherstack.stackduo | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak | |
| path: stack_duo-flatpak-x86_64-${{ steps.ver.outputs.version }}.flatpak | |
| build-stack-duo-appimage: | |
| runs-on: ubuntu-24.04 | |
| needs: build-stack-duo-linux | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set version | |
| id: ver | |
| run: | | |
| if [ "${{ github.ref_type }}" = "tag" ]; then | |
| VERSION="${{ github.ref_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ -n "${{ inputs.version }}" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="0.0.0-staging.${{ github.run_number }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download Linux bundle | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: stack_duo-linux-x86_64-${{ steps.ver.outputs.version }}.tar.gz | |
| - name: Install AppImage tools | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y squashfs-tools | |
| - name: Build AppImage | |
| run: | | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| tar -xzf "stack_duo-linux-x86_64-${VERSION}.tar.gz" | |
| mkdir -p AppDir | |
| cp -r bundle/* AppDir/ | |
| cp appimage/stack_duo/AppRun AppDir/AppRun | |
| chmod +x AppDir/AppRun | |
| cp appimage/stack_duo/stack_duo.desktop AppDir/ | |
| cp asset_sources/icon/stack_duo/icon.png AppDir/stack_duo.png | |
| curl -fsSL -o appimagetool \ | |
| https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage | |
| chmod +x appimagetool | |
| ARCH=x86_64 ./appimagetool --appimage-extract-and-run AppDir \ | |
| "stack_duo-appimage-x86_64-${VERSION}.AppImage" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: stack_duo-appimage-x86_64-${{ steps.ver.outputs.version }}.AppImage | |
| path: stack_duo-appimage-x86_64-${{ steps.ver.outputs.version }}.AppImage | |