Toss Multi-Platform Build and Release Workflow #4
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: Toss Multi-Platform Build and Release Workflow | |
on: | |
workflow_dispatch: | |
jobs: | |
get-latest-tag: | |
name: Get Latest and Previous Git Tags | |
runs-on: ubuntu-latest | |
outputs: | |
latest_tag: ${{ steps.tags.outputs.latest_tag }} | |
previous_tag: ${{ steps.tags.outputs.previous_tag }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Determine tags | |
id: tags | |
run: | | |
git fetch --tags | |
latest_tag=$(git tag --sort=-version:refname | head -n1) | |
previous_tag=$(git tag --sort=-version:refname | sed -n '2p') | |
echo "latest_tag=$latest_tag" >> "$GITHUB_OUTPUT" | |
echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT" | |
windows-build: | |
name: Build for Windows (Inno Setup) | |
runs-on: windows-latest | |
needs: get-latest-tag | |
outputs: | |
windows_artifact: ${{ steps.upload_windows.outputs.artifact_path }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Fix flutter SDK folder permission | |
run: git config --global --add safe.directory %TEMP%/flutter/-- | |
- name: Set up Flutter | |
uses: subosito/flutter-action@v2 | |
with: | |
flutter-version: '3.29.2' | |
- name: Install dependencies | |
run: flutter pub get | |
- name: Build Windows app | |
run: flutter build windows --release | |
- name: Install Inno Setup | |
run: choco install innosetup -y | |
- name: Create Inno Setup script | |
run: | | |
echo '; Inno Setup script to package the Flutter app' > package.iss | |
echo '[Setup]' >> package.iss | |
echo 'Compression=zip' >> package.iss | |
echo 'AppName=Toss' >> package.iss | |
echo "AppVersion=${{ needs.get-latest-tag.outputs.latest_tag }}" >> package.iss | |
echo 'DefaultDirName={pf}\Toss' >> package.iss | |
echo 'DefaultGroupName=Toss' >> package.iss | |
echo 'OutputBaseFilename=TossInstaller' >> package.iss | |
echo '[Files]' >> package.iss | |
echo 'Source: "build\windows\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs' >> package.iss | |
echo '[Icons]' >> package.iss | |
echo 'Name: "{group}\Toss"; Filename: "{app}\toss.exe"' >> package.iss | |
- name: Create Installer | |
run: iscc package.iss | |
- name: Upload Installer | |
id: upload_windows | |
uses: actions/upload-artifact@v4 | |
with: | |
name: Toss-Windows-Installer | |
path: Output/TossInstaller.exe | |
linux-build: | |
name: Build for Linux (AppImage) | |
runs-on: ubuntu-latest | |
needs: get-latest-tag | |
outputs: | |
linux_artifact: ${{ steps.upload_linux.outputs.artifact_path }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Install apt dependencies | |
run: | | |
sudo apt-get update | |
sudo apt install -y clang cmake curl git ninja-build pkg-config unzip xz-utils zip libgtk-3-dev liblzma-dev libsecret-1-dev | |
- name: Fix flutter SDK folder permission | |
run: git config --global --add safe.directory /tmp/flutter/-- | |
- name: Set up Flutter | |
uses: subosito/flutter-action@v2 | |
with: | |
flutter-version: '3.29.2' | |
- name: Install dependencies | |
run: flutter pub get | |
- name: Build Linux app | |
run: flutter build linux --release | |
- name: Install AppImageTool | |
run: | | |
wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage | |
chmod +x appimagetool-x86_64.AppImage | |
- name: Package as AppImage | |
run: | | |
mkdir -p AppDir/usr/bin | |
cp -r build/linux/x64/release/bundle/* AppDir/usr/bin | |
chmod +x AppDir/usr/bin/toss | |
# Create .desktop file using printf to avoid indentation problems | |
mkdir -p AppDir | |
printf '%s\n' \ | |
'[Desktop Entry]' \ | |
'Type=Application' \ | |
'Name=Toss' \ | |
'Exec=toss' \ | |
'Icon=toss' \ | |
'Categories=Utility;' > AppDir/toss.desktop | |
# Copy icon (must match Icon=toss and be .png) | |
cp assets/icons/icon.png AppDir/toss.png | |
./appimagetool-x86_64.AppImage AppDir Toss.AppImage | |
- name: Upload AppImage | |
id: upload_linux | |
uses: actions/upload-artifact@v4 | |
with: | |
name: Toss-Linux-AppImage | |
path: Toss.AppImage | |
android-build: | |
name: Build for Android (APK) | |
runs-on: ubuntu-latest | |
needs: get-latest-tag | |
outputs: | |
android_artifact: ${{ steps.upload_android.outputs.artifact_path }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Fix flutter SDK folder permission | |
run: git config --global --add safe.directory /tmp/flutter/-- | |
- name: Set up Flutter | |
uses: subosito/flutter-action@v2 | |
with: | |
flutter-version: '3.29.2' | |
- name: Install dependencies | |
run: flutter pub get | |
- name: Build Android APK | |
run: flutter build apk --release | |
- name: Upload APK | |
id: upload_android | |
uses: actions/upload-artifact@v4 | |
with: | |
name: Toss-Android-APK | |
path: build/app/outputs/flutter-apk/app-release.apk | |
ios-build: | |
name: Trigger iOS Build on Codemagic | |
runs-on: ubuntu-latest | |
needs: get-latest-tag | |
outputs: | |
build_id: ${{ steps.trigger_build.outputs.build_id }} | |
steps: | |
- name: Trigger Codemagic iOS Build | |
id: trigger_build | |
run: | | |
RESPONSE=$(curl -s -X POST \ | |
-H "Content-Type: application/json" \ | |
-H "x-auth-token: ${{ secrets.CODEMAGIC_TOKEN }}" \ | |
-d '{ | |
"appId": "68048cb2df9d43bf817c1eaa", | |
"workflowId": "68048cb2df9d43bf817c1ea9", | |
"branch": "master", | |
"environment": { | |
"TAG_NAME": "${{ needs.get-latest-tag.outputs.latest_tag }}" | |
} | |
}' \ | |
https://api.codemagic.io/builds) | |
echo "$RESPONSE" | |
BUILD_ID=$(echo "$RESPONSE" | jq -r '.buildId') | |
if [ -z "$BUILD_ID" ] || [ "$BUILD_ID" == "null" ]; then | |
echo "Failed to trigger build" | |
exit 1 | |
fi | |
echo "build_id=${BUILD_ID}" >> "$GITHUB_OUTPUT" | |
wait-for-codemagic: | |
name: Wait for Codemagic Build to Complete | |
runs-on: ubuntu-latest | |
needs: ios-build | |
outputs: | |
build_status: ${{ steps.check_status.outputs.status }} | |
steps: | |
- name: Poll Codemagic Build Status | |
id: check_status | |
run: | | |
BUILD_ID=${{ needs.ios-build.outputs.build_id }} | |
echo "Polling status for build ID: $BUILD_ID" | |
for i in {1..100}; do | |
STATUS=$(curl -s -H "x-auth-token: ${{ secrets.CODEMAGIC_TOKEN }}" \ | |
"https://api.codemagic.io/builds/$BUILD_ID" | jq -r '.build.status') | |
echo "Status: $STATUS" | |
if [[ "$STATUS" == "finished" ]]; then | |
echo "Build completed." | |
echo "status=success" >> "$GITHUB_OUTPUT" | |
exit 0 | |
elif [[ "$STATUS" == "failed" || "$STATUS" == "canceled" ]]; then | |
echo "Build failed or canceled." | |
echo "status=failed" >> "$GITHUB_OUTPUT" | |
exit 1 | |
fi | |
sleep 10 | |
done | |
echo "Timed out waiting for build to finish" | |
exit 1 | |
fetch-codemagic-artifacts: | |
name: Fetch IPA from Codemagic | |
runs-on: ubuntu-latest | |
needs: [ios-build, wait-for-codemagic] | |
outputs: | |
codemagic_artifact: ${{ steps.upload_codemagic.outputs.artifact_path }} | |
steps: | |
- name: Get .ipa Artifact URL | |
id: get_artifact_url | |
run: | | |
BUILD_ID=${{ needs.ios-build.outputs.build_id }} | |
BUILD_JSON=$(curl -s -H "x-auth-token: ${{ secrets.CODEMAGIC_TOKEN }}" \ | |
"https://api.codemagic.io/builds/$BUILD_ID") | |
echo "$BUILD_JSON" > build_info.json | |
IPA_URL=$(echo "$BUILD_JSON" | jq -r '.build.artefacts[] | select(.name | endswith(".ipa")) | .url') | |
if [ -z "$IPA_URL" ] || [ "$IPA_URL" == "null" ]; then | |
echo "No IPA artifact found." | |
exit 1 | |
fi | |
echo "IPA_URL=$IPA_URL" >> $GITHUB_ENV | |
- name: Download .ipa | |
run: | | |
curl -L -o Toss.ipa "$IPA_URL" | |
- name: Upload IPA | |
id: upload_codemagic | |
uses: actions/upload-artifact@v4 | |
with: | |
name: Toss-iOS-IPA | |
path: Toss.ipa | |
create-release: | |
needs: | |
- windows-build | |
- linux-build | |
- android-build | |
- fetch-codemagic-artifacts | |
- get-latest-tag | |
runs-on: ubuntu-latest | |
steps: | |
- name: Download Windows Installer | |
uses: actions/download-artifact@v4 | |
with: | |
name: Toss-Windows-Installer | |
- name: Download Linux AppImage | |
uses: actions/download-artifact@v4 | |
with: | |
name: Toss-Linux-AppImage | |
- name: Download Android APK | |
uses: actions/download-artifact@v4 | |
with: | |
name: Toss-Android-APK | |
- name: Rename APK | |
run: mv app-release.apk Toss.apk | |
- name: Download iOS IPA | |
uses: actions/download-artifact@v4 | |
with: | |
name: Toss-iOS-IPA | |
- name: Generate release body | |
id: release_body | |
run: | | |
# Start with the changelog link | |
echo "**Full Changelog**: https://github.com/Slipstreamm/Toss/compare/${{ needs.get-latest-tag.outputs.previous_tag }}...${{ needs.get-latest-tag.outputs.latest_tag }}" > release_body.md | |
echo "" >> release_body.md | |
echo "## SHA256 Hashes" >> release_body.md | |
# Compute and append the SHA256 for each artifact | |
for file in TossInstaller.exe Toss.AppImage Toss.apk Toss.ipa; do | |
HASH=$(sha256sum "$file" | awk '{print $1}') | |
echo "- $file: \`$HASH\`" >> release_body.md | |
done | |
- name: Create/Update GitHub Release and Upload Assets | |
uses: ncipollo/release-action@v1 | |
with: | |
tag: ${{ needs.get-latest-tag.outputs.latest_tag }} | |
artifacts: | | |
TossInstaller.exe | |
Toss.AppImage | |
Toss.apk | |
Toss.ipa | |
bodyFile: release_body.md | |
allowUpdates: true # update if the tag already exists | |
makeLatest: true # force this release to be marked “latest” | |
prerelease: false | |
token: ${{ secrets.GITHUB_TOKEN }} |