name: Build Fladder on: push: tags: - "v*" branches: - master pull_request: paths: - pubspec.yaml - .github/workflows/build.yml - .fvmrc types: - opened - reopened schedule: # Run nightly at midnight UTC, but only if there were changes to develop - cron: "0 0 * * *" workflow_dispatch: inputs: build_type: description: "Build type (release, nightly)" required: false default: "nightly" type: choice options: - release - nightly concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: NIGHTLY_TAG: nightly jobs: # Check if workflow should run based on trigger conditions check-trigger: runs-on: ubuntu-latest outputs: should_run: ${{ steps.check.outputs.should_run }} build_type: ${{ steps.check.outputs.build_type }} steps: - name: Checkout repository uses: actions/checkout@v4.1.1 with: fetch-depth: 0 - name: Check if should run and determine build type id: check run: | # Determine build type based on trigger and input if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then BUILD_TYPE="${{ github.event.inputs.build_type }}" elif [[ "${{ startsWith(github.ref, 'refs/tags/v') }}" == "true" ]]; then BUILD_TYPE="release" elif [[ "${{ github.event_name }}" == "schedule" ]]; then # Check if there were commits to develop in the last 24 hours git checkout develop COMMITS_LAST_24H=$(git log --since="24 hours ago" --oneline | wc -l) if [[ $COMMITS_LAST_24H -gt 0 ]]; then BUILD_TYPE="nightly" else echo "No commits to develop in the last 24 hours, skipping nightly build" echo "should_run=false" >> $GITHUB_OUTPUT exit 0 fi elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then BUILD_TYPE="nightly" else # For PRs and other events, build but don't release BUILD_TYPE="development" fi echo "build_type=${BUILD_TYPE}" >> $GITHUB_OUTPUT echo "should_run=true" >> $GITHUB_OUTPUT echo "Build type determined: ${BUILD_TYPE}" fetch-info: needs: [check-trigger] if: needs.check-trigger.outputs.should_run == 'true' runs-on: ubuntu-latest outputs: version_name: ${{ steps.fetch.outputs.version_name }} flutter_version: ${{ steps.fetch.outputs.flutter_version }} nightly_version: ${{ steps.fetch.outputs.nightly_version }} build_type: ${{ needs.check-trigger.outputs.build_type }} steps: - name: Checkout repository uses: actions/checkout@v4.1.1 with: fetch-depth: 0 - name: Fetch version name and create nightly version id: fetch run: | # Extract version_name from pubspec.yaml VERSION_NAME=$(grep '^version:' pubspec.yaml | cut -d ':' -f2 | cut -d '+' -f1 | tr -d ' ') echo "version_name=${VERSION_NAME}" >> "$GITHUB_OUTPUT" # Extract flutter_version from .fvmrc FLUTTER_VERSION=$(jq -r '.flutter' .fvmrc) echo "flutter_version=${FLUTTER_VERSION}" >> "$GITHUB_OUTPUT" # Create nightly version if needed if [[ "${{ needs.check-trigger.outputs.build_type }}" == "nightly" ]]; then NIGHTLY_VERSION="${VERSION_NAME}-nightly" echo "nightly_version=${NIGHTLY_VERSION}" >> "$GITHUB_OUTPUT" echo "Nightly version: $NIGHTLY_VERSION" fi # Print versions for logging echo "Base version: $VERSION_NAME" echo "Flutter version: $FLUTTER_VERSION" shell: bash build-android: needs: [fetch-info] runs-on: ubuntu-latest outputs: artifact_suffix: ${{ env.ARTIFACT_SUFFIX }} steps: - name: Checkout repository uses: actions/checkout@v4.1.1 - name: Determine Build Type run: | echo "ARTIFACT_SUFFIX=${{ needs.fetch-info.outputs.build_type }}" >> $GITHUB_ENV echo "ARTIFACT_SUFFIX=${{ needs.fetch-info.outputs.build_type }}" >> $GITHUB_OUTPUT - name: Decode Keystore for release env: ENCODED_STRING: ${{ secrets.KEYSTORE_BASE_64 }} RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }} RELEASE_KEYSTORE_ALIAS: ${{ secrets.RELEASE_KEYSTORE_ALIAS }} RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} GITHUB_RUN_NUMBER: ${{ github.run_number }} run: | echo "$ENCODED_STRING" | base64 -d > android/app/keystore.jks # Create the key.properties file cat > android/app/key.properties <> $GITHUB_OUTPUT else echo "version=${{ needs.fetch-info.outputs.version_name }}" >> $GITHUB_OUTPUT fi - name: Delete existing nightly release if: needs.fetch-info.outputs.build_type == 'nightly' run: | # Delete existing nightly release and tag with better error handling echo "Checking for existing nightly release..." if gh release view ${{ env.NIGHTLY_TAG }} >/dev/null 2>&1; then echo "Deleting existing nightly release..." gh release delete ${{ env.NIGHTLY_TAG }} --yes --cleanup-tag else echo "No existing nightly release found." fi # Clean up any orphaned tags if git tag -l | grep -q "^${{ env.NIGHTLY_TAG }}$"; then echo "Deleting orphaned nightly tag..." git push origin --delete ${{ env.NIGHTLY_TAG }} || true fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Generate changelog if: needs.fetch-info.outputs.build_type == 'nightly' id: changelog run: | # Get the latest stable release tag for comparison LATEST_STABLE_RELEASE=$(gh release list --limit 50 --exclude-drafts --json tagName,isPrerelease --jq '.[] | select(.isPrerelease == false) | .tagName' | head -1 || echo "") # Create new changelog with comparison link cat > changelog.md <<-EOF # $(date -u "+%Y-%m-%d %H:%M:%S UTC") This is an automated nightly build containing the latest changes from the develop branch. **⚠️ Warning:** This is a development build and may contain bugs or incomplete features. EOF # Add comparison link if we have a latest stable release if [ -n "$LATEST_STABLE_RELEASE" ]; then cat >> changelog.md <<-EOF ## 📋 What's Changed See all changes since the latest release: [Compare $LATEST_STABLE_RELEASE...HEAD](https://github.com/${{ github.repository }}/compare/$LATEST_STABLE_RELEASE...HEAD) EOF else cat >> changelog.md <<-EOF ## 📋 What's Changed See all changes: [View commits](https://github.com/${{ github.repository }}/commits/develop) EOF fi # Add build metadata cat >> changelog.md <<-EOF --- 📅 **Build Date:** $(date -u "+%Y-%m-%d %H:%M:%S UTC") 🔧 **Build Number:** ${{ github.run_number }} 📝 **Commit:** ${{ github.sha }} 🌿 **Branch:** develop EOF echo "changelog_file=changelog.md" >> $GITHUB_OUTPUT env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Download Artifacts Android uses: actions/download-artifact@v4 with: name: fladder-android path: fladder-android - name: Move Android run: | mv fladder-android/${{ needs.build-android.outputs.artifact_suffix }}.apk Fladder-Android-${{ steps.version.outputs.version }}.apk mv fladder-android/${{ needs.build-android.outputs.artifact_suffix }}.aab Fladder-Android-${{ steps.version.outputs.version }}.aab - name: Download Windows portable artifact uses: actions/download-artifact@v4 with: name: fladder-windows-portable path: fladder-windows-portable - name: Compress Windows run: | cd fladder-windows-portable zip -r ../Fladder-Windows-${{ steps.version.outputs.version }}.zip . - name: Download Windows installer artifact uses: actions/download-artifact@v4 with: name: fladder-windows-installer path: fladder-windows-installer - name: Rename Windows installer run: mv fladder-windows-installer/fladder_setup.exe Fladder-Windows-${{ steps.version.outputs.version }}-Setup.exe - name: Download Artifacts iOS uses: actions/download-artifact@v4 with: name: fladder-iOS path: fladder-iOS - name: Move iOS run: mv fladder-iOS/iOS.ipa Fladder-iOS-${{ steps.version.outputs.version }}.ipa - name: Download Artifacts macOS uses: actions/download-artifact@v4 with: name: fladder-macOS path: fladder-macOS - name: Move macOS run: mv fladder-macOS/macOS.dmg Fladder-macOS-${{ steps.version.outputs.version }}.dmg - name: Download Artifacts Linux uses: actions/download-artifact@v4 with: name: fladder-linux path: fladder-linux - name: Compress Linux run: | cd fladder-linux zip -r ../Fladder-Linux-${{ steps.version.outputs.version }}.zip . - name: Download Artifacts Linux Flatpak if: needs.fetch-info.outputs.build_type == 'release' uses: actions/download-artifact@v4 with: name: fladder-linux-flatpak path: fladder-linux-flatpak - name: Move Linux Flatpak if: needs.fetch-info.outputs.build_type == 'release' run: mv fladder-linux-flatpak/Fladder-Linux.flatpak Fladder-Linux-${{ steps.version.outputs.version }}.flatpak - name: Download Artifacts Linux AppImage uses: actions/download-artifact@v4 with: name: fladder-linux-appimage path: fladder-linux-appimage - name: Move Linux AppImages run: | mv fladder-linux-appimage/Fladder_x86_64.AppImage Fladder-Linux-${{ steps.version.outputs.version }}.AppImage mv fladder-linux-appimage/Fladder_x86_64.AppImage.zsync Fladder-Linux-${{ steps.version.outputs.version }}.AppImage.zsync - name: Download Artifacts Web uses: actions/download-artifact@v4 with: name: fladder-web path: fladder-web - name: Compress Web run: | cd fladder-web zip -r ../Fladder-Web-${{ steps.version.outputs.version }}.zip . - name: Create Release uses: softprops/action-gh-release@v2.2.2 with: tag_name: ${{ needs.fetch-info.outputs.build_type == 'nightly' && env.NIGHTLY_TAG || github.ref_name }} name: ${{ needs.fetch-info.outputs.build_type == 'nightly' && format('🌙 Nightly Build - {0}', steps.version.outputs.version) || '' }} body_path: ${{ needs.fetch-info.outputs.build_type == 'nightly' && 'changelog.md' || '' }} draft: ${{ needs.fetch-info.outputs.build_type == 'release' }} prerelease: ${{ needs.fetch-info.outputs.build_type == 'nightly' }} make_latest: ${{ needs.fetch-info.outputs.build_type == 'release' }} generate_release_notes: ${{ needs.fetch-info.outputs.build_type == 'release' }} fail_on_unmatched_files: true files: | Fladder-Android-${{ steps.version.outputs.version }}.apk Fladder-Android-${{ steps.version.outputs.version }}.aab Fladder-Windows-${{ steps.version.outputs.version }}-Setup.exe Fladder-Windows-${{ steps.version.outputs.version }}.zip Fladder-iOS-${{ steps.version.outputs.version }}.ipa Fladder-macOS-${{ steps.version.outputs.version }}.dmg Fladder-Web-${{ steps.version.outputs.version }}.zip Fladder-Linux-${{ steps.version.outputs.version }}.zip Fladder-Linux-${{ steps.version.outputs.version }}.AppImage Fladder-Linux-${{ steps.version.outputs.version }}.AppImage.zsync env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Add Flatpak to release if: needs.fetch-info.outputs.build_type == 'release' uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} files: | Fladder-Linux-${{ steps.version.outputs.version }}.flatpak env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} release_play_console: name: Upload AAB to Google Play Console needs: - fetch-info - create_release - build-android runs-on: ubuntu-latest steps: - name: Download Artifacts Android uses: actions/download-artifact@v4 with: name: fladder-android path: fladder-android - name: Upload AAB to Google Play Console uses: r0adkll/upload-google-play@v1.1.3 with: serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }} packageName: "nl.jknaapen.fladder" releaseFiles: "fladder-android/${{ needs.build-android.outputs.artifact_suffix }}.aab" track: ${{ needs.fetch-info.outputs.build_type == 'nightly' && 'internal' || 'production' }} status: ${{ needs.fetch-info.outputs.build_type == 'nightly' && 'completed' || 'draft' }} releaseName: "${{ github.run_number }} (${{ needs.fetch-info.outputs.version_name }})" release_web: name: Release Web needs: - fetch-info - create_release runs-on: ubuntu-latest if: needs.fetch-info.outputs.build_type == 'release' steps: - name: Checkout repository uses: actions/checkout@v4.1.1 - name: Download Artifacts Web uses: actions/download-artifact@v4 with: name: fladder-web path: build/web - name: Deploy to ghcr.io uses: mr-smithers-excellent/docker-build-push@v6 with: image: fladder addLatest: true multiPlatform: true platform: linux/amd64,linux/arm64,linux/arm/v7 registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Deploy rootless-image to ghcr.io uses: mr-smithers-excellent/docker-build-push@v6 with: dockerfile: Dockerfile-rootless image: fladder-rootless addLatest: true multiPlatform: true platform: linux/amd64,linux/arm64,linux/arm/v7 registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Clean builds folder run: rm -rf build/web - name: Download Artifacts Web uses: actions/download-artifact@v4 with: name: fladder-web-pages path: build/web - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./build/web # Winget package submission winget-package-submit: runs-on: ubuntu-latest needs: [check-trigger, create_release] strategy: matrix: include: - build_type: release identifier: DonutWare.Fladder max_versions: "" - build_type: nightly identifier: DonutWare.Fladder.Nightly max_versions: "1" steps: - name: Submit to Winget (${{ matrix.build_type }}) if: needs.check-trigger.outputs.build_type == matrix.build_type uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f with: identifier: ${{ matrix.identifier }} installers-regex: 'Fladder-Windows-.*-Setup\.exe$' token: ${{ secrets.WINGET_TOKEN }} max-versions-to-keep: ${{ matrix.max_versions || '' }} release-tag: ${{ matrix.build_type == 'nightly' && env.NIGHTLY_TAG || github.ref_name }}