diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 3acb74d..79714fd 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -24,3 +24,127 @@ jobs: - name: Test run: flutter test + + build-debug-apk: + name: Build Debug APK + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v5 + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + + - uses: subosito/flutter-action@v2 + with: + channel: 'stable' + + - run: flutter pub get + + - name: Generate icons and splash screens + run: | + dart run flutter_launcher_icons + dart run flutter_native_splash:create + + - name: Build debug APK + run: flutter build apk --debug + + - name: Upload debug APK + uses: actions/upload-artifact@v4 + with: + name: debug-apk + path: build/app/outputs/flutter-apk/app-debug.apk + if-no-files-found: error + retention-days: 14 + + build-ios-simulator: + name: Build iOS Simulator + runs-on: macos-26 + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v5 + + - uses: subosito/flutter-action@v2 + with: + channel: 'stable' + + - run: flutter pub get + + - name: Generate icons and splash screens + run: | + dart run flutter_launcher_icons + dart run flutter_native_splash:create + + - name: Build iOS simulator app + run: flutter build ios --debug --simulator + + - name: Zip Runner.app + run: cd build/ios/iphonesimulator && zip -r "$GITHUB_WORKSPACE/Runner.app.zip" Runner.app + + - name: Upload simulator build + uses: actions/upload-artifact@v4 + with: + name: ios-simulator + path: Runner.app.zip + if-no-files-found: error + retention-days: 14 + + comment-artifacts: + name: Post Artifact Links + needs: [build-debug-apk, build-ios-simulator] + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && !cancelled() + permissions: + pull-requests: write + steps: + - uses: actions/github-script@v7 + continue-on-error: true + env: + APK_RESULT: ${{ needs.build-debug-apk.result }} + IOS_RESULT: ${{ needs.build-ios-simulator.result }} + with: + script: | + const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}#artifacts`; + const apkOk = process.env.APK_RESULT === 'success'; + const iosOk = process.env.IOS_RESULT === 'success'; + + const lines = ['## Debug builds', '']; + + if (apkOk || iosOk) { + lines.push(`Download from the [artifacts page](${runUrl}):`); + if (apkOk) lines.push('- **debug-apk** — install on Android device/emulator'); + if (iosOk) lines.push('- **ios-simulator** — unzip and install with `xcrun simctl install booted Runner.app`'); + } + + if (!apkOk || !iosOk) { + const failed = []; + if (!apkOk) failed.push('Android APK'); + if (!iosOk) failed.push('iOS simulator'); + lines.push('', `**Failed:** ${failed.join(', ')} — check the [workflow run](${runUrl}) for details.`); + } + + const body = lines.join('\n'); + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const existing = comments.find(c => c.body.startsWith('## Debug builds')); + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + }