Make 1 shared card for linked accounts #64
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 | |
| 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' | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.41.9' | |
| channel: stable | |
| - name: Install dependencies | |
| run: flutter pub get | |
| - 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.41.9' | |
| channel: stable | |
| - name: Setup CMake 3.x | |
| uses: jwlawson/actions-setup-cmake@v2 | |
| with: | |
| cmake-version: '3.31.6' | |
| - name: Install dependencies | |
| run: flutter pub get | |
| - name: Build Windows | |
| run: flutter build windows --release | |
| env: | |
| CMAKE_POLICY_VERSION_MINIMUM: "3.5" | |
| - name: Zip Windows build | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath NetherLink-windows.zip | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: windows-zip | |
| path: NetherLink-windows.zip | |
| build-macos: | |
| name: Build macOS DMG | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.41.9' | |
| channel: stable | |
| - name: Install dependencies | |
| 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/NetherLink.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/NetherLink.app" | |
| rm -rf "$STAGING_DIR" | |
| mkdir -p "$STAGING_DIR" | |
| cp -R "$APP_PATH" "$STAGING_DIR/" | |
| ln -s /Applications "$STAGING_DIR/Applications" | |
| hdiutil create \ | |
| -volname "NetherLink" \ | |
| -srcfolder "$STAGING_DIR" \ | |
| -ov \ | |
| -format UDZO \ | |
| "$GITHUB_WORKSPACE/NetherLink-macos.dmg" | |
| codesign --force --sign - "$GITHUB_WORKSPACE/NetherLink-macos.dmg" | |
| codesign --verify --strict "$GITHUB_WORKSPACE/NetherLink-macos.dmg" | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: macos-dmg | |
| path: NetherLink-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/checkout@v5 | |
| - 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: macos-dmg | |
| path: artifacts/ | |
| - name: Rename Android APK | |
| run: mv artifacts/app-release.apk artifacts/NetherLink-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/NetherLink-android.apk | |
| artifacts/NetherLink-windows.zip | |
| artifacts/NetherLink-macos.dmg | |
| 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/checkout@v5 | |
| - 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: macos-dmg | |
| path: artifacts/ | |
| - name: Rename Android APK | |
| run: mv artifacts/app-release.apk artifacts/NetherLink-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/NetherLink-android.apk | |
| artifacts/NetherLink-windows.zip | |
| artifacts/NetherLink-macos.dmg | |
| 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: "NetherLink 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: "NetherLink 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" |