diff --git a/.github/workflows/build-ci-image.yaml b/.github/workflows/build-ci-image.yaml index 4c40a0873..066290576 100644 --- a/.github/workflows/build-ci-image.yaml +++ b/.github/workflows/build-ci-image.yaml @@ -9,11 +9,14 @@ on: workflow_dispatch: env: - IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/stackwallet-ci + GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/stackwallet-ci jobs: build: runs-on: ubuntu-24.04 + permissions: + contents: read + packages: write steps: - uses: actions/checkout@v6 @@ -21,16 +24,28 @@ jobs: - uses: docker/login-action@v4 with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push + - name: Build and push full image uses: docker/build-push-action@v7 with: context: . + target: full push: true tags: | - ${{ env.IMAGE }}:latest - ${{ env.IMAGE }}:${{ github.sha }} + ${{ env.GHCR_IMAGE }}:latest + ${{ env.GHCR_IMAGE }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Build and push test image + uses: docker/build-push-action@v7 + with: + context: . + target: test + push: true + tags: ${{ env.GHCR_IMAGE }}:test cache-from: type=gha cache-to: type=gha,mode=max diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2e2ed58c6..b0dd56f2e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -183,17 +183,242 @@ jobs: 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@v4 with: name: stack_wallet-android-${{ steps.ver.outputs.version }} path: android-artifacts/ + build-windows: + runs-on: windows-latest + 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 }}" + else + VERSION="${{ inputs.version }}" + BUILD_NUMBER="${{ inputs.build_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' + + - 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 + + - 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: Generate app config + run: dart run build_runner build --delete-conflicting-outputs + + - 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 }}" + else + VERSION="${{ inputs.version }}" + BUILD_NUMBER="${{ inputs.build_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' + + - 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: Generate app config + run: dart run build_runner build --delete-conflicting-outputs + + - 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 }}" + else + VERSION="${{ inputs.version }}" + BUILD_NUMBER="${{ inputs.build_number }}" + fi + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "build_number=${BUILD_NUMBER}" >> $GITHUB_OUTPUT + + - uses: dtolnay/rust-toolchain@master + with: + toolchain: '1.71.0' + targets: aarch64-apple-ios + + - uses: subosito/flutter-action@v2 + with: + flutter-version: '3.38.1' + channel: 'stable' + + - 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: Generate app config + run: dart run build_runner build --delete-conflicting-outputs + + - 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] + needs: [build-linux, build-android, build-windows, build-macos, build-ios] runs-on: ubuntu-latest permissions: contents: write diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 622387ba1..9093439cf 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -3,11 +3,14 @@ on: [pull_request] jobs: test: runs-on: ubuntu-24.04 + permissions: + contents: read + packages: read container: - image: stackwallet/stackwallet-ci:latest + image: ghcr.io/${{ github.repository_owner }}/stackwallet-ci:test credentials: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + username: ${{ github.actor }} + password: ${{ github.token }} steps: - name: Prepare repository uses: actions/checkout@v6 diff --git a/Dockerfile b/Dockerfile index 0c1a24042..e1c6a237d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1.7 -FROM ubuntu:24.04 +FROM ubuntu:24.04 AS full ENV DEBIAN_FRONTEND=noninteractive \ TZ=Etc/UTC \ @@ -78,3 +78,35 @@ RUN git clone --depth 1 --branch 3.38.1 https://github.com/flutter/flutter.git " RUN git config --system --add safe.directory '*' RUN flutter --version && rustc --version && cargo --version && node --version + + +# Minimal image for flutter test (no Rust, no Android SDK, no cross-compilers) +FROM ubuntu:24.04 AS test + +ENV DEBIAN_FRONTEND=noninteractive \ + TZ=Etc/UTC \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates curl file git unzip xz-utils \ + build-essential cmake ninja-build pkg-config \ + clang libclang-dev \ + libgirepository1.0-dev libglib2.0-dev libgtk-3-dev \ + libjsoncpp-dev liblzma-dev libsecret-1-dev libssl-dev \ + && rm -rf /var/lib/apt/lists/* + +ENV FLUTTER_HOME=/opt/flutter \ + PATH=/opt/flutter/bin:/opt/flutter/bin/cache/dart-sdk/bin:$PATH + +RUN git clone --depth 1 --branch 3.38.1 https://github.com/flutter/flutter.git "$FLUTTER_HOME" \ + && git config --global --add safe.directory '*' \ + && flutter config --no-analytics \ + && flutter precache --linux \ + && chmod -R a+rwX "$FLUTTER_HOME" + +RUN git config --system --add safe.directory '*' + +RUN flutter --version diff --git a/scripts/ios/download_all.sh b/scripts/ios/download_all.sh new file mode 100755 index 000000000..714531e9f --- /dev/null +++ b/scripts/ios/download_all.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -x -e + +mkdir -p build + +PLUGINS_DIR=../../crypto_plugins + +(cd "${PLUGINS_DIR}"/flutter_libepiccash/scripts/ios && ./download.sh) + +(cd "${PLUGINS_DIR}"/flutter_libmwc/scripts/ios && ./download.sh) + +# frostdart iOS is built from source by Cargokit at pod install time + +wait +echo "Done" diff --git a/scripts/macos/download_all.sh b/scripts/macos/download_all.sh new file mode 100755 index 000000000..4bbb400bc --- /dev/null +++ b/scripts/macos/download_all.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -x -e + +mkdir -p build + +PLUGINS_DIR=../../crypto_plugins + +(cd "${PLUGINS_DIR}"/flutter_libepiccash/scripts/macos && ./download.sh) + +(cd "${PLUGINS_DIR}"/flutter_libmwc/scripts/macos && ./download.sh) + +(cd "${PLUGINS_DIR}"/frostdart/scripts/macos && ./download.sh) + +wait +echo "Done" diff --git a/scripts/windows/download_all.sh b/scripts/windows/download_all.sh new file mode 100755 index 000000000..6bd350408 --- /dev/null +++ b/scripts/windows/download_all.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -x -e + +mkdir -p build + +PLUGINS_DIR=../../crypto_plugins + +(cd "${PLUGINS_DIR}"/flutter_libepiccash/scripts/windows && ./download.sh) + +(cd "${PLUGINS_DIR}"/flutter_libmwc/scripts/windows && ./download.sh) + +(cd "${PLUGINS_DIR}"/frostdart/scripts/windows && ./download.sh) + +wait +echo "Done"