Skip to content

Build

Build #21

Workflow file for this run

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@v4
with:
name: stack_wallet-linux-x86_64-${{ steps.ver.outputs.version }}
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: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 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: |
echo "$KEYSTORE_BASE64" | base64 --decode > android/keystore.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
- uses: actions/upload-artifact@v4
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@v5
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 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@v4
with:
name: stack_wallet-windows-x86_64-${{ steps.ver.outputs.version }}
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@v5
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@v4
with:
name: stack_wallet-macos-aarch64-${{ steps.ver.outputs.version }}
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@v5
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@v4
with:
name: stack_wallet-ios-aarch64-${{ steps.ver.outputs.version }}
path: stack_wallet-ios-aarch64-${{ steps.ver.outputs.version }}.ipa
release:
if: github.ref_type == 'tag'
needs: [build-linux, build-android, build-windows, build-macos, build-ios]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: artifacts/*