Allow friends to see which server you are connected to #192
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 & Release (dev) | |
| on: | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: build-release-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-android: | |
| name: Build Android APK | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| cache: gradle | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.44.0' | |
| channel: stable | |
| cache: true | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.pub-cache | |
| key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pub- | |
| - name: Prepare signing keystore | |
| env: | |
| ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} | |
| KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} | |
| KEY_ALIAS: ${{ secrets.KEY_ALIAS || 'release' }} | |
| run: | | |
| if [ -z "$ANDROID_KEYSTORE_BASE64" ]; then | |
| echo "Missing ANDROID_KEYSTORE_BASE64 in GitHub Secrets." | |
| exit 1 | |
| fi | |
| if [ -z "$KEYSTORE_PASSWORD" ] || [ -z "$KEY_PASSWORD" ]; then | |
| echo "Missing KEYSTORE_PASSWORD or KEY_PASSWORD in GitHub Secrets." | |
| exit 1 | |
| fi | |
| TEMP_KEYSTORE_PATH="$(mktemp)" | |
| trap 'rm -f "$TEMP_KEYSTORE_PATH"' EXIT | |
| if ! echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$TEMP_KEYSTORE_PATH"; then | |
| echo "Failed to decode ANDROID_KEYSTORE_BASE64. Verify it is valid base64 in GitHub Secrets." | |
| exit 1 | |
| fi | |
| if ! mv "$TEMP_KEYSTORE_PATH" android/app-release.jks; then | |
| echo "Failed to write decoded keystore to android/app-release.jks. Verify the android directory is writable." | |
| exit 1 | |
| fi | |
| if ! printf '%s\n' "$KEYSTORE_PASSWORD" | keytool -list -keystore android/app-release.jks >/dev/null 2>&1; then | |
| rm -f android/app-release.jks | |
| echo "Keystore validation failed. Verify android/app-release.jks is a readable keystore file and KEYSTORE_PASSWORD is correct for it." | |
| exit 1 | |
| fi | |
| if ! printf '%s\n' "$KEYSTORE_PASSWORD" | keytool -list -keystore android/app-release.jks -alias "$KEY_ALIAS" >/dev/null 2>&1; then | |
| rm -f android/app-release.jks | |
| echo "Keystore alias validation failed. Verify KEY_ALIAS exists in the configured keystore." | |
| exit 1 | |
| fi | |
| chmod 600 android/app-release.jks | |
| umask 077 | |
| printf 'storePassword=%s\nkeyPassword=%s\nkeyAlias=%s\nstoreFile=app-release.jks\n' \ | |
| "$KEYSTORE_PASSWORD" "$KEY_PASSWORD" "$KEY_ALIAS" > android/key.properties | |
| chmod 600 android/key.properties | |
| - name: Build APK | |
| run: flutter build apk --release | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: android-apk | |
| path: build/app/outputs/flutter-apk/app-release.apk | |
| build-windows: | |
| name: Build Windows EXE | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.44.0' | |
| channel: stable | |
| cache: false | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/AppData/Local/Pub/Cache | |
| key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pub- | |
| - name: Setup CMake 3.x | |
| uses: jwlawson/actions-setup-cmake@v2 | |
| with: | |
| cmake-version: '3.31.6' | |
| - name: Build Windows | |
| run: flutter build windows --release | |
| env: | |
| CMAKE_POLICY_VERSION_MINIMUM: "3.5" | |
| - name: Build MSIX | |
| run: dart run msix:create | |
| - name: Zip Windows build | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath MCCompanion-windows.zip | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: windows-zip | |
| path: MCCompanion-windows.zip | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: windows-msix | |
| path: build/windows/x64/runner/Release/MCCompanion.msix | |
| build-macos: | |
| name: Build macOS DMG | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.44.0' | |
| channel: stable | |
| cache: true | |
| - name: Cache pub dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.pub-cache | |
| key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pub- | |
| - name: Cache CocoaPods | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cocoapods/repos | |
| ~/Library/Caches/CocoaPods | |
| macos/Pods | |
| key: ${{ runner.os }}-cocoapods-${{ hashFiles('macos/Podfile.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cocoapods- | |
| - name: Prepare macOS dependency overrides | |
| run: | | |
| cat > pubspec_overrides.yaml <<'EOF' | |
| dependency_overrides: | |
| connectivity_plus: 6.1.4 | |
| EOF | |
| flutter pub get | |
| - name: Build macOS | |
| run: flutter build macos --release | |
| env: | |
| FLUTTER_XCODE_CODE_SIGNING_ALLOWED: "NO" | |
| FLUTTER_XCODE_CODE_SIGN_IDENTITY: "" | |
| FLUTTER_XCODE_CODE_SIGNING_REQUIRED: "NO" | |
| - name: Ad-hoc sign macOS app | |
| run: | | |
| APP_PATH="build/macos/Build/Products/Release/MCCompanion.app" | |
| codesign --force --deep --sign - "$APP_PATH" | |
| codesign --verify --deep --strict "$APP_PATH" | |
| - name: Create macOS DMG | |
| run: | | |
| STAGING_DIR="$RUNNER_TEMP/dmg-staging" | |
| APP_PATH="build/macos/Build/Products/Release/MCCompanion.app" | |
| rm -rf "$STAGING_DIR" | |
| mkdir -p "$STAGING_DIR" | |
| cp -R "$APP_PATH" "$STAGING_DIR/" | |
| ln -s /Applications "$STAGING_DIR/Applications" | |
| hdiutil create \ | |
| -volname "MCCompanion" \ | |
| -srcfolder "$STAGING_DIR" \ | |
| -ov \ | |
| -format UDZO \ | |
| "$GITHUB_WORKSPACE/MCCompanion-macos.dmg" | |
| codesign --force --sign - "$GITHUB_WORKSPACE/MCCompanion-macos.dmg" | |
| codesign --verify --strict "$GITHUB_WORKSPACE/MCCompanion-macos.dmg" | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: macos-dmg | |
| path: MCCompanion-macos.dmg | |
| release: | |
| name: Create or Update dev Release | |
| needs: [build-android, build-windows, build-macos] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: android-apk | |
| path: artifacts/ | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: windows-zip | |
| path: artifacts/ | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: windows-msix | |
| path: artifacts/ | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: macos-dmg | |
| path: artifacts/ | |
| - name: Rename Android APK | |
| run: mv artifacts/app-release.apk artifacts/MCCompanion-android.apk | |
| - name: Create or update dev release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: dev | |
| name: Development Build | |
| prerelease: true | |
| body: | | |
| Automated development build from commit ${{ github.sha }} on branch `${{ github.ref_name }}`. | |
| This is a development build. If you don't know what you are doing, please don't install it. | |
| Warning: Google/Apple authentication won't work with dev builds. | |
| files: | | |
| artifacts/MCCompanion-android.apk | |
| artifacts/MCCompanion-windows.zip | |
| artifacts/MCCompanion-macos.dmg | |
| artifacts/MCCompanion.msix | |
| notify-discord: | |
| name: Notify Discord | |
| if: ${{ always() }} | |
| needs: [build-android, build-windows, build-macos, release] | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - name: Send build status embed | |
| env: | |
| DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
| ANDROID_RESULT: ${{ needs.build-android.result }} | |
| WINDOWS_RESULT: ${{ needs.build-windows.result }} | |
| MACOS_RESULT: ${{ needs.build-macos.result }} | |
| RELEASE_RESULT: ${{ needs.release.result }} | |
| REPOSITORY: ${{ github.repository }} | |
| BRANCH: ${{ github.ref_name }} | |
| ACTOR: ${{ github.actor }} | |
| SHA: ${{ github.sha }} | |
| COMMIT_MESSAGE: ${{ github.event.head_commit.message }} | |
| RUN_ID: ${{ github.run_id }} | |
| SERVER_URL: ${{ github.server_url }} | |
| RELEASES_URL: ${{ github.server_url }}/${{ github.repository }}/releases/tag/dev | |
| run: | | |
| if [ -z "$DISCORD_WEBHOOK_URL" ]; then | |
| echo "DISCORD_WEBHOOK_URL is not configured. Skipping Discord notification." | |
| exit 0 | |
| fi | |
| OVERALL_STATUS="✅ Build Succeeded" | |
| EMBED_COLOR=5763719 | |
| if [ "$ANDROID_RESULT" != "success" ] || [ "$WINDOWS_RESULT" != "success" ] || [ "$MACOS_RESULT" != "success" ] || [ "$RELEASE_RESULT" != "success" ]; then | |
| OVERALL_STATUS="❌ Build Failed" | |
| EMBED_COLOR=15548997 | |
| fi | |
| RUN_URL="$SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID" | |
| COMMIT_URL="$SERVER_URL/$REPOSITORY/commit/$SHA" | |
| COMMIT_SUBJECT="$(printf '%s' "$COMMIT_MESSAGE" | head -n 1)" | |
| PAYLOAD="$(jq -n \ | |
| --arg overallStatus "$OVERALL_STATUS" \ | |
| --arg repository "$REPOSITORY" \ | |
| --arg branch "$BRANCH" \ | |
| --arg actor "$ACTOR" \ | |
| --arg runUrl "$RUN_URL" \ | |
| --arg commitUrl "$COMMIT_URL" \ | |
| --arg sha "$SHA" \ | |
| --arg commitSubject "$COMMIT_SUBJECT" \ | |
| --arg android "$ANDROID_RESULT" \ | |
| --arg windows "$WINDOWS_RESULT" \ | |
| --arg macos "$MACOS_RESULT" \ | |
| --arg release "$RELEASE_RESULT" \ | |
| --arg releasesUrl "$RELEASES_URL" \ | |
| --argjson color "$EMBED_COLOR" \ | |
| '{ | |
| username: "GitHub Actions", | |
| avatar_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png", | |
| embeds: [ | |
| { | |
| title: $overallStatus, | |
| color: $color, | |
| description: ("**Repository:** `" + $repository + "`\n**Branch:** `" + $branch + "`\n**Triggered by:** `" + $actor + "`"), | |
| author: { | |
| name: "GitHub", | |
| icon_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" | |
| }, | |
| fields: [ | |
| { name: "Android", value: $android, inline: true }, | |
| { name: "Windows", value: $windows, inline: true }, | |
| { name: "macOS", value: $macos, inline: true }, | |
| { name: "Release", value: $release, inline: true }, | |
| { name: "Commit", value: ("[" + ($sha | .[0:7]) + "](" + $commitUrl + ")" + (if $commitSubject != "" then " " + $commitSubject else "" end)), inline: false }, | |
| { name: "Releases Page", value: ("[View Releases](" + $releasesUrl + ")"), inline: false } | |
| ], | |
| url: $runUrl, | |
| timestamp: now | todateiso8601 | |
| } | |
| ] | |
| }')" | |
| RESPONSE_FILE="$(mktemp)" | |
| HTTP_STATUS="$(curl -sS -o "$RESPONSE_FILE" -w "%{http_code}" -H "Content-Type: application/json" -d "$PAYLOAD" "$DISCORD_WEBHOOK_URL" || true)" | |
| if [ "${HTTP_STATUS:-000}" -lt 200 ] || [ "${HTTP_STATUS:-000}" -ge 300 ]; then | |
| echo "Failed to send Discord notification. HTTP status: ${HTTP_STATUS:-000}" | |
| echo "Response body:" | |
| cat "$RESPONSE_FILE" | |
| exit 1 | |
| fi | |
| rm -f "$RESPONSE_FILE" | |
| release-beta: | |
| name: Create or Update beta Release | |
| needs: [build-android, build-windows, build-macos] | |
| if: ${{ needs.build-android.result == 'success' && needs.build-windows.result == 'success' && needs.build-macos.result == 'success' && startsWith(github.event.head_commit.message, '[beta]') }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: android-apk | |
| path: artifacts/ | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: windows-zip | |
| path: artifacts/ | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: windows-msix | |
| path: artifacts/ | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: macos-dmg | |
| path: artifacts/ | |
| - name: Rename Android APK | |
| run: mv artifacts/app-release.apk artifacts/MCCompanion-android.apk | |
| - name: Create or update beta release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: beta | |
| target_commitish: ${{ github.sha }} | |
| name: Beta Build | |
| prerelease: true | |
| body: | | |
| Automated beta build from commit ${{ github.sha }} on branch `${{ github.ref_name }}`. | |
| This is a beta build intended for testing before wider release. | |
| Warning: Google/Apple authentication won't work with beta builds. | |
| files: | | |
| artifacts/MCCompanion-android.apk | |
| artifacts/MCCompanion-windows.zip | |
| artifacts/MCCompanion-macos.dmg | |
| artifacts/MCCompanion.msix | |
| notify-discord-beta: | |
| name: Notify Discord Beta Release | |
| needs: [release-beta] | |
| if: ${{ needs.release-beta.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - name: Send beta release embed | |
| env: | |
| DISCORD_BETA_WEBHOOK_URL: ${{ secrets.DISCORD_BETA_WEBHOOK_URL }} | |
| REPOSITORY: ${{ github.repository }} | |
| ACTOR: ${{ github.actor }} | |
| SHA: ${{ github.sha }} | |
| COMMIT_MESSAGE: ${{ github.event.head_commit.message }} | |
| RUN_ID: ${{ github.run_id }} | |
| SERVER_URL: ${{ github.server_url }} | |
| BETA_RELEASE_URL: ${{ github.server_url }}/${{ github.repository }}/releases/tag/beta | |
| run: | | |
| if [ -z "$DISCORD_BETA_WEBHOOK_URL" ]; then | |
| echo "DISCORD_BETA_WEBHOOK_URL is not configured. Skipping Discord beta notification." | |
| exit 0 | |
| fi | |
| ROLE_ID="1485783465365344316" | |
| RUN_URL="$SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID" | |
| COMMIT_URL="$SERVER_URL/$REPOSITORY/commit/$SHA" | |
| COMMIT_SUBJECT="$(printf '%s' "$COMMIT_MESSAGE" | head -n 1)" | |
| PAYLOAD="$(jq -n \ | |
| --arg roleId "$ROLE_ID" \ | |
| --arg betaReleaseUrl "$BETA_RELEASE_URL" \ | |
| --arg commitUrl "$COMMIT_URL" \ | |
| --arg sha "$SHA" \ | |
| --arg commitSubject "$COMMIT_SUBJECT" \ | |
| --arg runUrl "$RUN_URL" \ | |
| --arg actor "$ACTOR" \ | |
| '{ | |
| content: ("<@&" + $roleId + ">"), | |
| allowed_mentions: { | |
| roles: [$roleId] | |
| }, | |
| username: "GitHub Actions", | |
| avatar_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png", | |
| embeds: [ | |
| { | |
| title: "🚀 New Beta Release Available", | |
| url: $betaReleaseUrl, | |
| color: 5793266, | |
| description: ("Hello, <@&" + $roleId + ">, we have a new beta release ready. Check it out on our [beta release](" + $betaReleaseUrl + ")."), | |
| author: { | |
| name: "MCCompanion Beta Releases", | |
| icon_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" | |
| }, | |
| fields: [ | |
| { name: "Commit", value: ("[" + ($sha | .[0:7]) + "](" + $commitUrl + ")" + (if $commitSubject != "" then " " + $commitSubject else "" end)), inline: false }, | |
| { name: "Platforms", value: "Android • Windows • macOS", inline: true }, | |
| { name: "Download links", value: ("[Beta release](" + $betaReleaseUrl + ")"), inline: true }, | |
| { name: "Triggered by", value: $actor, inline: true }, | |
| { name: "Workflow", value: ("[View run](" + $runUrl + ")"), inline: true } | |
| ], | |
| footer: { | |
| text: "MCCompanion beta release" | |
| }, | |
| timestamp: now | todateiso8601 | |
| } | |
| ] | |
| }')" | |
| RESPONSE_FILE="$(mktemp)" | |
| HTTP_STATUS="$(curl -sS -o "$RESPONSE_FILE" -w "%{http_code}" -H "Content-Type: application/json" -d "$PAYLOAD" "$DISCORD_BETA_WEBHOOK_URL")" | |
| CURL_EXIT_CODE=$? | |
| if [ "$CURL_EXIT_CODE" -ne 0 ]; then | |
| echo "Failed to send Discord beta release notification with curl exit code: $CURL_EXIT_CODE" | |
| exit "$CURL_EXIT_CODE" | |
| fi | |
| if [ "${HTTP_STATUS:-000}" -lt 200 ] || [ "${HTTP_STATUS:-000}" -ge 300 ]; then | |
| echo "Failed to send Discord beta release notification. HTTP status: ${HTTP_STATUS:-000}" | |
| echo "Response body:" | |
| cat "$RESPONSE_FILE" | |
| exit 1 | |
| fi | |
| rm -f "$RESPONSE_FILE" |