Build and Release App #5
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 and Release App | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_type: | |
| description: "Release type" | |
| required: true | |
| default: "release" | |
| type: choice | |
| options: | |
| - release | |
| - prerelease | |
| workflow_run: | |
| workflows: ["Bump Version & Release"] | |
| types: | |
| - completed | |
| jobs: | |
| get-version: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.get_version.outputs.version }} | |
| prerelease: ${{ steps.get_version.outputs.prerelease }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: get_version | |
| run: | | |
| VERSION=$(cat pubspec.yaml | grep version: | awk '{print $2}') | |
| VERSION="v$VERSION" | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.release_type }}" == "prerelease" ]]; then | |
| PRERELEASE=true | |
| else | |
| PRERELEASE=false | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "prerelease=$PRERELEASE" >> $GITHUB_OUTPUT | |
| build: | |
| needs: get-version | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| # One platform failing should not hide whether the others work. | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: android | |
| os: ubuntu-latest | |
| artifact: android | |
| - platform: windows | |
| os: windows-latest | |
| artifact: windows | |
| - platform: macos | |
| os: macos-latest | |
| artifact: macos-arm64 | |
| - platform: macos | |
| os: macos-26-intel | |
| artifact: macos-x64 | |
| - platform: linux | |
| os: ubuntu-latest | |
| artifact: linux-amd64 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: 3.47.0 | |
| # Flutter's Linux build needs the GTK toolchain, which the runner image | |
| # does not carry by default. | |
| - name: Install Linux build dependencies | |
| if: matrix.platform == 'linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev | |
| - name: Install dependencies | |
| run: flutter pub get | |
| - name: Build Android | |
| if: matrix.platform == 'android' | |
| run: >- | |
| flutter build apk --release | |
| --dart-define=ADMINCRAFT_GOOGLE_WEB_CLIENT_ID=${{ vars.ADMINCRAFT_GOOGLE_WEB_CLIENT_ID }} | |
| - name: Build Windows | |
| if: matrix.platform == 'windows' | |
| run: >- | |
| flutter build windows --release | |
| --dart-define=ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_ID=${{ vars.ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_ID }} | |
| --dart-define=ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_SECRET=${{ secrets.ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_SECRET }} | |
| - name: Build macOS | |
| if: matrix.platform == 'macos' | |
| run: >- | |
| flutter build macos --release | |
| --dart-define=ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_ID=${{ vars.ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_ID }} | |
| --dart-define=ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_SECRET=${{ secrets.ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_SECRET }} | |
| - name: Build Linux | |
| if: matrix.platform == 'linux' | |
| run: >- | |
| flutter build linux --release | |
| --dart-define=ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_ID=${{ vars.ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_ID }} | |
| --dart-define=ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_SECRET=${{ secrets.ADMINCRAFT_GOOGLE_DESKTOP_CLIENT_SECRET }} | |
| - name: Package Android | |
| if: matrix.platform == 'android' | |
| shell: bash | |
| run: | | |
| mkdir -p dist | |
| mv build/app/outputs/flutter-apk/app-release.apk "dist/admincraft-${VERSION}-android.apk" | |
| env: | |
| VERSION: ${{ needs.get-version.outputs.version }} | |
| # Portable zip plus an Inno Setup installer, so the download page offers | |
| # the same pair as every other desktop platform. | |
| - name: Package Windows | |
| if: matrix.platform == 'windows' | |
| shell: bash | |
| run: | | |
| mkdir -p dist | |
| DIST="$PWD/dist" | |
| RELEASE_DIR="$PWD/build/windows/x64/runner/Release" | |
| ( cd "$RELEASE_DIR" && 7z a -tzip "$DIST/admincraft-${VERSION}-windows-portable.zip" ./* ) | |
| # Inno Setup ships on the runner image, but the path has moved between | |
| # image versions, so look for it before falling back to installing it. | |
| ISCC="" | |
| for candidate in "/c/Program Files (x86)/Inno Setup 6/ISCC.exe" "/c/Program Files/Inno Setup 6/ISCC.exe"; do | |
| [ -x "$candidate" ] && ISCC="$candidate" && break | |
| done | |
| if [ -z "$ISCC" ]; then | |
| choco install innosetup -y --no-progress | |
| ISCC="/c/Program Files (x86)/Inno Setup 6/ISCC.exe" | |
| fi | |
| echo "Using $ISCC" | |
| "$ISCC" "//DAppVersion=${VERSION#v}" "//DSourceDir=${RELEASE_DIR}" "//DOutputDir=${DIST}" windows/packaging/admincraft.iss | |
| mv dist/admincraft-setup.exe "dist/admincraft-${VERSION}-windows-installer.exe" | |
| env: | |
| VERSION: ${{ needs.get-version.outputs.version }} | |
| # Unsigned: without an Apple Developer certificate Gatekeeper asks the user | |
| # to allow the app on first launch. Signing would need a MAC_CSC_LINK | |
| # secret and an Apple Developer account. | |
| - name: Package macOS | |
| if: matrix.platform == 'macos' | |
| shell: bash | |
| run: | | |
| mkdir -p dist | |
| APP=build/macos/Build/Products/Release/admincraft.app | |
| BASE="dist/admincraft-${VERSION}-${{ matrix.artifact }}" | |
| ditto -c -k --keepParent "$APP" "${BASE}-portable.zip" | |
| hdiutil create -volname Admincraft -srcfolder "$APP" -ov -format UDZO "${BASE}-installer.dmg" | |
| env: | |
| VERSION: ${{ needs.get-version.outputs.version }} | |
| - name: Package Linux | |
| if: matrix.platform == 'linux' | |
| shell: bash | |
| run: | | |
| linux/packaging/build-packages.sh "$VERSION" build/linux/x64/release/bundle dist | |
| env: | |
| VERSION: ${{ needs.get-version.outputs.version }} | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: admincraft-${{ needs.get-version.outputs.version }}-${{ matrix.artifact }} | |
| path: dist/* | |
| if-no-files-found: error | |
| release: | |
| needs: [get-version, build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| # Collected by pattern rather than one step per platform, so adding a | |
| # platform to the matrix above needs no change here. | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: admincraft-${{ needs.get-version.outputs.version }}-* | |
| path: dist | |
| merge-multiple: true | |
| - name: List collected files | |
| run: ls -lh dist | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ needs.get-version.outputs.version }} | |
| name: Release ${{ needs.get-version.outputs.version }} | |
| prerelease: ${{ needs.get-version.outputs.prerelease }} | |
| generate_release_notes: true | |
| files: dist/* | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Delete build artifacts from GitHub | |
| uses: geekyeggo/delete-artifact@v5 | |
| with: | |
| name: admincraft-${{ needs.get-version.outputs.version }}-* |