-
-
Notifications
You must be signed in to change notification settings - Fork 87
prep for F-Droid: isolate firebase and mobile_scanner behind seams #321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -243,6 +243,89 @@ jobs: | |
| files: ${{ steps.rename.outputs.apk }} | ||
| generate_release_notes: true | ||
|
|
||
| # Keeps the F-Droid build recipe (docs/fdroid/*.yml) in sync with each | ||
| # release and, once a fdroiddata fork is configured, pushes the updated | ||
| # recipe there as a merge request. F-Droid builds from source itself (see | ||
| # docs/fdroid/wtf.openstrap.openstrap_edge.yml's header for the full | ||
| # rationale/verification) — this job never ships a binary to F-Droid, it | ||
| # only keeps the recipe's versionName/versionCode/commit current so the | ||
| # inclusion (or an update) has something correct to build. After the FIRST | ||
| # inclusion is merged, F-Droid's own AutoUpdateMode:Version + | ||
| # UpdateCheckMode:Tags bot picks up ordinary tags on its own — this job's | ||
| # ongoing job is mainly a safety net for now, and the sole mechanism before | ||
| # that first inclusion exists. | ||
| # | ||
| # Deliberately does NOT fail the release if fdroiddata isn't configured yet | ||
| # (no FDROID_GITLAB_TOKEN secret) — F-Droid isn't wired up until the first | ||
| # inclusion MR is manually opened and merged; this job just keeps the draft | ||
| # recipe current in the meantime and does the rest once it is wired up. | ||
| fdroid: | ||
| needs: preflight | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false # nothing here writes to THIS repo | ||
|
|
||
| # Stamp the release's real versionName/versionCode/commit into the | ||
| # checked-in draft recipe. Plain sed rather than a YAML library: the | ||
| # three fields each appear in exactly one recognizable spot in the file | ||
| # (see docs/fdroid/wtf.openstrap.openstrap_edge.yml), and keeping this | ||
| # a shell one-liner means no extra Python deps for a 3-line edit. | ||
| - name: Stamp release version into the fdroid recipe | ||
| run: | | ||
| set -euo pipefail | ||
| ver=$(grep -E '^version:' pubspec.yaml | head -1 | awk '{print $2}') | ||
| name=${ver%%+*} | ||
| build=${ver#*+} | ||
| tag="$GITHUB_REF_NAME" | ||
| f=docs/fdroid/wtf.openstrap.openstrap_edge.yml | ||
| sed -i \ | ||
| -e "s/^\([[:space:]-]*versionName:[[:space:]]*\).*/\1$name/" \ | ||
| -e "s/^\([[:space:]]*versionCode:[[:space:]]*\).*/\1$build/" \ | ||
| -e "s/^\([[:space:]]*commit:[[:space:]]*\)[^ ]*/\1$tag/" \ | ||
| -e "s/^CurrentVersion:.*/CurrentVersion: $name/" \ | ||
| -e "s/^CurrentVersionCode:.*/CurrentVersionCode: $build/" \ | ||
| "$f" | ||
| echo "Stamped $f -> versionName=$name versionCode=$build commit=$tag" | ||
|
|
||
| # Push the stamped recipe to a fdroiddata fork and open/update a merge | ||
| # request, ONLY once that fork + token are configured. Until then this | ||
| # step just explains what's missing and exits clean — the release | ||
| # itself must never fail on account of F-Droid plumbing. | ||
| - name: Sync recipe to fdroiddata fork | ||
| env: | ||
| FDROID_GITLAB_TOKEN: ${{ secrets.FDROID_GITLAB_TOKEN }} | ||
| FDROID_FORK_REPO: ${{ vars.FDROID_FORK_REPO }} # e.g. https://gitlab.com/yourname/fdroiddata.git | ||
| run: | | ||
| set -euo pipefail | ||
| if [ -z "${FDROID_GITLAB_TOKEN:-}" ] || [ -z "${FDROID_FORK_REPO:-}" ]; then | ||
| echo "::notice::FDROID_GITLAB_TOKEN / FDROID_FORK_REPO not set — skipping fdroiddata sync." | ||
| echo "::notice::One-time setup: fork https://gitlab.com/fdroid/fdroiddata, add a GitLab" | ||
| echo "::notice::personal access token as the FDROID_GITLAB_TOKEN secret and the fork's" | ||
| echo "::notice::clone URL as the FDROID_FORK_REPO repo variable. Until the first" | ||
| echo "::notice::inclusion MR is opened and merged by hand, this step has nothing to do." | ||
| exit 0 | ||
| fi | ||
|
|
||
| branch="update-openstrap-edge-${GITHUB_REF_NAME}" | ||
| workdir="$RUNNER_TEMP/fdroiddata" | ||
| repo_url="${FDROID_FORK_REPO/https:\/\//https:\/\/oauth2:${FDROID_GITLAB_TOKEN}@}" | ||
|
|
||
| git clone --depth 1 "$repo_url" "$workdir" | ||
| cp docs/fdroid/wtf.openstrap.openstrap_edge.yml \ | ||
| "$workdir/metadata/wtf.openstrap.openstrap_edge.yml" | ||
|
|
||
| cd "$workdir" | ||
| git checkout -b "$branch" | ||
| git -c user.name="openstrap-release-bot" -c user.email="noreply@openstrap.wtf" \ | ||
| commit -am "wtf.openstrap.openstrap_edge: update to ${GITHUB_REF_NAME}" \ | ||
| --allow-empty -- metadata/wtf.openstrap.openstrap_edge.yml | ||
| git push -u origin "$branch" \ | ||
| -o merge_request.create \ | ||
| -o merge_request.title="wtf.openstrap.openstrap_edge: update to ${GITHUB_REF_NAME}" \ | ||
| -o merge_request.target=fdroid/fdroiddata | ||
|
Comment on lines
+321
to
+327
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): The GitLab push option sets Triggers: When Suggested fix: Use the upstream project's supported GitLab push option/API for the target project and set |
||
|
|
||
| # Unsigned iOS .ipa for sideloading (AltStore / Sideloadly / TrollStore). It is | ||
| # NOT App Store signed — users re-sign it with their own Apple ID on install. | ||
| # Note: free-account sideloads re-sign with a different team id, so App Group | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| // barcode_reader.dart (F-Droid / FLOSS variant) — flutter_zxing-backed | ||
| // stand-in with the exact API of lib/scan/barcode_reader.dart, zero Google | ||
| // dependencies (mobile_scanner's ML Kit pulls play-services-basement/base/ | ||
| // tasks on Android either way — checked its build.gradle directly). | ||
| // | ||
| // Not compiled by default. The F-Droid build recipe (see | ||
| // docs/fdroid/wtf.openstrap.openstrap_edge.yml) copies this over | ||
| // lib/scan/barcode_reader.dart and adds flutter_zxing + camera to | ||
| // pubspec.yaml before building. scan_barcode.dart (the only caller) is | ||
| // unaffected — it only ever sees this API. | ||
| // | ||
| // flutter_zxing (pub.dev, 2.3.0, Apache-2.0, pure Dart FFI over the ZXing | ||
| // C++ library via the `camera` plugin — no Google Play Services / ML Kit) | ||
| // verified to cover every format this app scans: Format.ean13/ean8/upca/ | ||
| // upce/dataBar/dataBarExpanded all exist (lib/src/models/format.dart). | ||
| // ReaderWidget's error surface is onControllerCreated(controller, error) — | ||
| // a non-null error there is how the underlying `camera` plugin reports | ||
| // camera failures, including permission denial via a CameraException whose | ||
| // `code` is 'CameraAccessDenied' (or 'CameraAccessDeniedWithoutPrompt' on | ||
| // iOS, kept here for API parity though this file only ever ships on | ||
| // Android). | ||
|
|
||
| import 'package:camera/camera.dart'; | ||
| import 'package:flutter/widgets.dart'; | ||
| import 'package:flutter_zxing/flutter_zxing.dart' as zx; | ||
|
Comment on lines
+23
to
+25
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- scoped repository knowledge files ---'
find /tmp/coderabbit-repo-knowledge/openstrap-edge-7422777d -maxdepth 2 -type f -name '*.md' -print | sort
printf '%s\n' '--- reviewed file ---'
cat -n docs/fdroid/barcode_reader.floss.dart
printf '%s\n' '--- analyzer/dependency/workflow candidates ---'
git ls-files | grep -E '(^|/)(analysis_options[^/]*|pubspec\.yaml|pubspec\.lock|.*fdroid.*|.*workflow.*|.*action.*|.*build.*|.*script.*)$' | head -200
printf '%s\n' '--- references to reviewed template and packages ---'
rg -n --glob '!pubspec.lock' 'barcode_reader\.floss|flutter_zxing|package:camera|docs/fdroid|fdroid' .Repository: OpenStrap/edge Length of output: 8215 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- analysis_options.yaml ---'
cat -n analysis_options.yaml
printf '%s\n' '--- pubspec.yaml package declarations ---'
rg -n -A4 -B4 '^(dependencies|dev_dependencies):|camera|flutter_zxing|mobile_scanner' pubspec.yaml
printf '%s\n' '--- F-Droid recipe relevant range ---'
sed -n '1,120p' docs/fdroid/wtf.openstrap.openstrap_edge.yml
printf '%s\n' '--- workflow analysis commands ---'
rg -n -A5 -B5 'flutter analyze|dart analyze|analyze' .github/workflows
printf '%s\n' '--- applicable repository conventions ---'
cat /tmp/coderabbit-repo-knowledge/openstrap-edge-7422777d/conventions/pubspec-yaml.md
printf '%s\n' '--- scoped learnings ---'
cat /tmp/coderabbit-repo-knowledge/openstrap-edge-7422777d/learnings/lib-import.mdRepository: OpenStrap/edge Length of output: 11621 🌐 Web query:
💡 Result: When you run the flutter analyze command, it recursively analyzes Dart files within your project directory [1][2][3]. To exclude specific directories (such as a docs directory) or files from this analysis, you must configure the analysis_options.yaml file located at the root of your project [4][5][6]. There is no native --exclude flag for the flutter analyze command-line tool [7]. Consequently, the recommended and standard method for excluding files or directories from static analysis is to use the analyzer: entry in your analysis_options.yaml file [4][6]. To exclude a directory like docs, add it to the exclude section of your analysis_options.yaml file using glob pattern syntax [4][6]: analyzer: exclude: - 'docs/' In this configuration, the glob pattern ensures that all files and subdirectories within the docs directory are ignored by the analyzer [4][8][6]. All paths defined in the exclude list must be relative to the directory containing the analysis_options.yaml file [4][6]. Citations:
Keep the F-Droid source template out of the default analyzer. Root-level 🧰 Tools🪛 GitHub Actions: test / 0_test.txt[warning] 23-23: The imported package 'camera' is not declared as a dependency of the importing package (depend_on_referenced_packages). [error] 23-23: Flutter analyze failed: Target of URI does not exist: 'package:camera/camera.dart' (uri_does_not_exist). [warning] 25-25: The imported package 'flutter_zxing' is not declared as a dependency of the importing package (depend_on_referenced_packages). [error] 25-25: Flutter analyze failed: Target of URI does not exist: 'package:flutter_zxing/flutter_zxing.dart' (uri_does_not_exist). 🪛 GitHub Actions: test / test[warning] 23-23: flutter analyze: Imported package 'camera' is not declared as a dependency (depend_on_referenced_packages). [error] 23-23: flutter analyze: Target URI does not exist: 'package:camera/camera.dart' (uri_does_not_exist). [warning] 25-25: flutter analyze: Imported package 'flutter_zxing' is not declared as a dependency (depend_on_referenced_packages). [error] 25-25: flutter analyze: Target URI does not exist: 'package:flutter_zxing/flutter_zxing.dart' (uri_does_not_exist). 🤖 Prompt for AI AgentsSource: Pipeline failures |
||
|
|
||
| enum BarcodeFormat { ean13, ean8, upcA, upcE, dataBar, dataBarExpanded } | ||
|
|
||
| class BarcodeReaderError { | ||
| const BarcodeReaderError({required this.permissionDenied}); | ||
| final bool permissionDenied; | ||
| } | ||
|
|
||
| typedef BarcodeReaderErrorBuilder = Widget Function(BuildContext, BarcodeReaderError); | ||
|
|
||
| class BarcodeReaderWidget extends StatefulWidget { | ||
| const BarcodeReaderWidget({ | ||
| super.key, | ||
| required this.formats, | ||
| required this.onDetect, | ||
| required this.errorBuilder, | ||
| }); | ||
|
|
||
| final List<BarcodeFormat> formats; | ||
| final ValueChanged<String> onDetect; | ||
| final BarcodeReaderErrorBuilder errorBuilder; | ||
|
|
||
| @override | ||
| State<BarcodeReaderWidget> createState() => _BarcodeReaderWidgetState(); | ||
| } | ||
|
|
||
| class _BarcodeReaderWidgetState extends State<BarcodeReaderWidget> { | ||
| bool _done = false; | ||
| BarcodeReaderError? _error; | ||
|
|
||
| static const Map<BarcodeFormat, int> _formatBits = { | ||
| BarcodeFormat.ean13: zx.Format.ean13, | ||
| BarcodeFormat.ean8: zx.Format.ean8, | ||
| BarcodeFormat.upcA: zx.Format.upca, | ||
| BarcodeFormat.upcE: zx.Format.upce, | ||
| BarcodeFormat.dataBar: zx.Format.dataBar, | ||
| BarcodeFormat.dataBarExpanded: zx.Format.dataBarExpanded, | ||
| }; | ||
|
|
||
| int get _codeFormat => | ||
| widget.formats.fold(0, (acc, f) => acc | (_formatBits[f] ?? 0)); | ||
|
|
||
| void _onScan(zx.Code code) { | ||
| if (_done || !code.isValid) return; | ||
| final text = code.text; | ||
| if (text == null || text.trim().isEmpty) return; | ||
| _done = true; | ||
| widget.onDetect(text.trim()); | ||
| } | ||
|
|
||
| void _onControllerCreated(CameraController? controller, Exception? error) { | ||
| if (error == null) return; | ||
| final denied = error is CameraException && | ||
| (error.code == 'CameraAccessDenied' || | ||
| error.code == 'CameraAccessDeniedWithoutPrompt'); | ||
| if (mounted) setState(() => _error = BarcodeReaderError(permissionDenied: denied)); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| final err = _error; | ||
| if (err != null) return widget.errorBuilder(context, err); | ||
| return zx.ReaderWidget( | ||
| codeFormat: _codeFormat, | ||
| onScan: _onScan, | ||
| onControllerCreated: _onControllerCreated, | ||
| showFlashlight: false, | ||
| showToggleCamera: false, | ||
| showGallery: false, | ||
| allowPinchZoom: false, | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // firebase_bridge.dart (F-Droid / FLOSS variant) — no-op stand-in with the | ||
| // exact API of lib/telemetry/firebase_bridge.dart, zero firebase_* imports. | ||
| // | ||
| // Not compiled by default. The F-Droid build recipe (see | ||
| // docs/fdroid/wtf.openstrap.openstrap_edge.yml) copies this over | ||
| // lib/telemetry/firebase_bridge.dart and drops the four firebase_* lines | ||
| // from pubspec.yaml before building, so the FLOSS build contains zero | ||
| // Google Play Services / Firebase code. Every caller (telemetry_service.dart, | ||
| // main.dart) is unaffected — they only ever see this API. | ||
|
|
||
| import 'package:flutter/foundation.dart'; | ||
|
|
||
| class FirebaseTraceHandle { | ||
| const FirebaseTraceHandle._(); | ||
| Future<void> stop() async {} | ||
| void putAttribute(String name, String value) {} | ||
| } | ||
|
|
||
| class FirebaseBridge { | ||
| static Future<void> initialize({Duration? timeout}) async {} | ||
|
|
||
| static bool get isInitialized => false; | ||
|
|
||
| static void setCollectionEnabled(bool value) {} | ||
|
|
||
| static void recordFlutterError(FlutterErrorDetails details, {required bool fatal}) {} | ||
|
|
||
| static void recordError(Object error, StackTrace stack, {required bool fatal, String? reason}) {} | ||
|
|
||
| static void log(String message) {} | ||
|
|
||
| static void setCustomKey(String key, Object value) {} | ||
|
|
||
| static Future<FirebaseTraceHandle> startTrace(String name) async => | ||
| const FirebaseTraceHandle._(); | ||
|
|
||
| static void logEvent(String name, Map<String, Object> parameters) {} | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,117 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| # F-Droid build recipe for OpenStrap edge — VERIFIED locally, full combined | ||||||||||||||||||||||||||||||||||||||||||||||
| # build (all three patches below applied together): `flutter build apk | ||||||||||||||||||||||||||||||||||||||||||||||
| # --release` succeeds, and the resulting APK's classes.dex has zero | ||||||||||||||||||||||||||||||||||||||||||||||
| # com/google/firebase and zero com/google/mlkit references. The only | ||||||||||||||||||||||||||||||||||||||||||||||
| # remaining com/google/android/gms/* strings are microG's own FOSS | ||||||||||||||||||||||||||||||||||||||||||||||
| # reimplementation classes (Apache-2.0, published under that namespace by | ||||||||||||||||||||||||||||||||||||||||||||||
| # design so Google-API-compiled code links against them unmodified). | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
| # This is NOT read by F-Droid from this repo — it's the file to copy into | ||||||||||||||||||||||||||||||||||||||||||||||
| # fdroiddata (https://gitlab.com/fdroid/fdroiddata) as | ||||||||||||||||||||||||||||||||||||||||||||||
| # metadata/wtf.openstrap.openstrap_edge.yml when opening the inclusion MR. | ||||||||||||||||||||||||||||||||||||||||||||||
| # Keeping it here, versioned next to the app it describes. | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
| # ── FIRST blocker: Firebase ───────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||||||||||
| # pubspec.yaml depends on firebase_core/firebase_crashlytics/ | ||||||||||||||||||||||||||||||||||||||||||||||
| # firebase_performance/firebase_analytics. Firebase is already fully | ||||||||||||||||||||||||||||||||||||||||||||||
| # optional at RUNTIME (see lib/telemetry/telemetry_service.dart and | ||||||||||||||||||||||||||||||||||||||||||||||
| # android/app/build.gradle.kts — the app builds and runs with zero Firebase | ||||||||||||||||||||||||||||||||||||||||||||||
| # credentials), but F-Droid rejects apps that bundle the Play Services / | ||||||||||||||||||||||||||||||||||||||||||||||
| # Firebase Android libraries at all, used or not. | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
| # Fix landed in this repo: every firebase_* import is confined to ONE file, | ||||||||||||||||||||||||||||||||||||||||||||||
| # lib/telemetry/firebase_bridge.dart (see its header comment). A FLOSS-build | ||||||||||||||||||||||||||||||||||||||||||||||
| # stand-in with the identical API and zero firebase_* imports lives at | ||||||||||||||||||||||||||||||||||||||||||||||
| # docs/fdroid/firebase_bridge.floss.dart. The recipe just swaps that one file | ||||||||||||||||||||||||||||||||||||||||||||||
| # and drops the four firebase_* pubspec lines — no other source edits | ||||||||||||||||||||||||||||||||||||||||||||||
| # needed, so it survives future changes to telemetry_service.dart without | ||||||||||||||||||||||||||||||||||||||||||||||
| # hand-patching call sites. | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
| # ── SECOND blocker: geolocator's GMS location backend ─────────────────────── | ||||||||||||||||||||||||||||||||||||||||||||||
| # geolocator_android pulls com.google.android.gms:play-services-location | ||||||||||||||||||||||||||||||||||||||||||||||
| # (used for GPS workout routes). Verified in its actual source | ||||||||||||||||||||||||||||||||||||||||||||||
| # (GeolocationManager.java:72-88, geolocator_android 4.6.2): it already falls | ||||||||||||||||||||||||||||||||||||||||||||||
| # back to plain android.location.LocationManager whenever Google Play | ||||||||||||||||||||||||||||||||||||||||||||||
| # Services isn't available, via the SAME com.google.android.gms.location.* | ||||||||||||||||||||||||||||||||||||||||||||||
| # package/class names either way. That's exactly what microG's FOSS | ||||||||||||||||||||||||||||||||||||||||||||||
| # reimplementation (org.microg.gms:play-services-location, Apache-2.0) | ||||||||||||||||||||||||||||||||||||||||||||||
| # ships, so a Gradle dependency substitution swaps it in with ZERO Dart/ | ||||||||||||||||||||||||||||||||||||||||||||||
| # Kotlin source changes — same technique used by organicmaps' F-Droid flavor | ||||||||||||||||||||||||||||||||||||||||||||||
| # (github.com/organicmaps/organicmaps PR #9575). Appended to | ||||||||||||||||||||||||||||||||||||||||||||||
| # android/app/build.gradle.kts by the recipe, not a permanent change to this | ||||||||||||||||||||||||||||||||||||||||||||||
| # repo's checked-in file — the Play Store / GitHub-release build keeps | ||||||||||||||||||||||||||||||||||||||||||||||
| # Google's real fused location provider. Must substitute the whole | ||||||||||||||||||||||||||||||||||||||||||||||
| # basement/base/tasks family, not just play-services-location, or anything | ||||||||||||||||||||||||||||||||||||||||||||||
| # else in the graph still pulling the real ones causes a duplicate-class | ||||||||||||||||||||||||||||||||||||||||||||||
| # build failure (hit this locally before adding mobile_scanner's fix below — | ||||||||||||||||||||||||||||||||||||||||||||||
| # see THIRD item). | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
| # ── THIRD blocker: mobile_scanner's ML Kit ─────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||||||||||
| # mobile_scanner (food barcode scan) bundles Google ML Kit on Android either | ||||||||||||||||||||||||||||||||||||||||||||||
| # way — checked its build.gradle directly: both the bundled | ||||||||||||||||||||||||||||||||||||||||||||||
| # com.google.mlkit:barcode-scanning and the useUnbundled | ||||||||||||||||||||||||||||||||||||||||||||||
| # play-services-mlkit-barcode-scanning paths pull the REAL | ||||||||||||||||||||||||||||||||||||||||||||||
| # com.google.android.gms:play-services-basement/base/tasks, which is also | ||||||||||||||||||||||||||||||||||||||||||||||
| # what caused the SECOND item's duplicate-class conflict until this was | ||||||||||||||||||||||||||||||||||||||||||||||
| # fixed. No Gradle-only escape hatch exists for ML Kit itself (unlike | ||||||||||||||||||||||||||||||||||||||||||||||
| # geolocator, whose own code already had a non-GMS fallback path). | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
| # Fix landed in this repo: every mobile_scanner import is confined to ONE | ||||||||||||||||||||||||||||||||||||||||||||||
| # file, lib/scan/barcode_reader.dart (see its header comment) — same seam | ||||||||||||||||||||||||||||||||||||||||||||||
| # pattern as firebase_bridge.dart. A FLOSS-build stand-in backed by | ||||||||||||||||||||||||||||||||||||||||||||||
| # flutter_zxing (pub.dev, Apache-2.0, pure Dart FFI over the ZXing C++ | ||||||||||||||||||||||||||||||||||||||||||||||
| # library, zero Google dependencies) with the identical API lives at | ||||||||||||||||||||||||||||||||||||||||||||||
| # docs/fdroid/barcode_reader.floss.dart. Verified to cover every barcode | ||||||||||||||||||||||||||||||||||||||||||||||
| # format this app scans (EAN13/EAN8/UPC-A/UPC-E/DataBar/DataBarExpanded — | ||||||||||||||||||||||||||||||||||||||||||||||
| # checked flutter_zxing's Format enum directly) and to build clean alongside | ||||||||||||||||||||||||||||||||||||||||||||||
| # both fixes above. iOS and the Play Store / GitHub-release Android build | ||||||||||||||||||||||||||||||||||||||||||||||
| # keep mobile_scanner unchanged; F-Droid never builds iOS at all. | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Categories: | ||||||||||||||||||||||||||||||||||||||||||||||
| - Health | ||||||||||||||||||||||||||||||||||||||||||||||
| License: MIT | ||||||||||||||||||||||||||||||||||||||||||||||
| SourceCode: https://github.com/OpenStrap/edge | ||||||||||||||||||||||||||||||||||||||||||||||
| IssueTracker: https://github.com/OpenStrap/edge/issues | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| AutoName: OpenStrap | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| RepoType: git | ||||||||||||||||||||||||||||||||||||||||||||||
| Repo: https://github.com/OpenStrap/edge.git | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Builds: | ||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- repository conventions ---'
find /tmp/coderabbit-repo-knowledge/openstrap-edge-7422777d -maxdepth 2 -type f -name '*.md' -print
printf '%s\n' '--- recipe ---'
cat -n docs/fdroid/wtf.openstrap.openstrap_edge.yml
printf '%s\n' '--- relevant workflow references ---'
rg -n -C 5 'Builds\.commit|openstrap_edge|fdroid|v0\.9\.29' .github/workflows docs/fdroidRepository: OpenStrap/edge Length of output: 24378 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- pubspec Flutter project metadata ---'
cat -n pubspec.yaml | sed -n '1,180p'
printf '%s\n' '--- Android build files and Flutter integration ---'
find android -maxdepth 3 -type f \( -name 'build.gradle' -o -name 'build.gradle.kts' -o -name 'settings.gradle' -o -name 'settings.gradle.kts' -o -name 'gradle.properties' \) -print
for f in $(find android -maxdepth 3 -type f \( -name 'build.gradle' -o -name 'build.gradle.kts' -o -name 'settings.gradle' -o -name 'settings.gradle.kts' \) -print); do
printf '%s\n' "--- $f ---"
cat -n "$f"
doneRepository: OpenStrap/edge Length of output: 22942 🌐 Web query:
💡 Result: To build a Flutter application within the F-Droid ecosystem, you must configure the application's metadata file (located in the fdroiddata repository) to handle the Flutter SDK and build process [1][2]. F-Droid recommends using a git submodule for the Flutter SDK, although using it as an srclib remains an option [3][4][2]. Key configurations in the build metadata YAML include: 1. Flutter SDK setup: If using a submodule, set submodules: true in the build configuration [3][4]. If using an srclib, include flutter as a source library (e.g., srclibs: - flutter@stable) and use the Citations:
Provision the Flutter build path in this recipe.
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| - versionName: 0.9.29 | ||||||||||||||||||||||||||||||||||||||||||||||
| versionCode: 62 | ||||||||||||||||||||||||||||||||||||||||||||||
| commit: v0.9.29 # TODO: tag this release before submitting | ||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: printf '%s\n' '--- repository convention files ---'
find /tmp/coderabbit-repo-knowledge/openstrap-edge-7422777d -type f -name '*.md' -print
printf '%s\n' '--- target files and relevant lines ---'
sed -n '70,92p' docs/fdroid/wtf.openstrap.openstrap_edge.yml
sed -n '265,295p' .github/workflows/build.yml
printf '%s\n' '--- F-Droid-related repository conventions ---'
find /tmp/coderabbit-repo-knowledge/openstrap-edge-7422777d -type f -name '*.md' -print0 |
xargs -0 grep -ilE 'fdroid|F-Droid|Builds.commit|build metadata|workflow' 2>/dev/null |Repository: OpenStrap/edge Length of output: 3652 🏁 Script executed: printf '%s\n' '--- workflow trigger and checkout context ---'
sed -n '1,45p' .github/workflows/build.yml
sed -n '245,290p' .github/workflows/build.yml
printf '%s\n' '--- local repository refs for the recipe release ---'
git status --short
git rev-parse --is-inside-work-tree
git rev-parse HEAD
git show-ref --tags | tail -20Repository: OpenStrap/edge Length of output: 4962 🌐 Web query:
💡 Result: In the F-Droid build metadata, the commit field is used to specify the exact point in the source code repository from which to build an application [1]. While the documentation notes that the parameter can accept a "tag, commit or revision number," it explicitly provides the following recommendation: "Note: Don’t use branch name or tag name. The full commit hash should be used" [1][2][3]. Using the full commit hash is the preferred practice for reproducibility, as it ensures the build remains pinned to a specific, immutable state of the repository, whereas tags or branch names can be moved or deleted [1][4]. It is worth noting that some examples in F-Droid documentation and community wiki pages may show tags being used (e.g., v1.2, v1.0, v2.0.2) [1][5]. However, the official Build Metadata Reference standard advises against this in favor of the full commit hash [1][4]. Additionally, when using automated update modes like Citations:
🏁 Script executed: printf '%s\n' '--- recipe policy and update mode ---'
sed -n '1,72p' docs/fdroid/wtf.openstrap.openstrap_edge.yml
printf '%s\n' '--- release tag resolution ---'
git ls-remote https://github.com/OpenStrap/edge.git \
'refs/tags/v0.9.29' 'refs/tags/v0.9.29^{}'
printf '%s\n' '--- workflow checkout contract references ---'
rg -n 'GITHUB_REF_NAME|git rev-parse HEAD|actions/checkout|commit:' .github docs/fdroidRepository: OpenStrap/edge Length of output: 6468 Pin Use 📍 Affects 2 files
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| subdir: android | ||||||||||||||||||||||||||||||||||||||||||||||
| sudo: | ||||||||||||||||||||||||||||||||||||||||||||||
| # Firebase → no-op stub (see FIRST blocker above). | ||||||||||||||||||||||||||||||||||||||||||||||
| - cp docs/fdroid/firebase_bridge.floss.dart lib/telemetry/firebase_bridge.dart | ||||||||||||||||||||||||||||||||||||||||||||||
| - sed -i '/^[[:space:]]*firebase_core:/d;/^[[:space:]]*firebase_crashlytics:/d;/^[[:space:]]*firebase_performance:/d;/^[[:space:]]*firebase_analytics:/d' pubspec.yaml | ||||||||||||||||||||||||||||||||||||||||||||||
| - rm -f app/google-services.json | ||||||||||||||||||||||||||||||||||||||||||||||
| # Barcode scanner → flutter_zxing (see THIRD blocker above). Must run | ||||||||||||||||||||||||||||||||||||||||||||||
| # BEFORE the geolocator substitution below, or the real | ||||||||||||||||||||||||||||||||||||||||||||||
| # play-services-basement/base/tasks mobile_scanner still pulls in | ||||||||||||||||||||||||||||||||||||||||||||||
| # duplicates microG's substituted classes. | ||||||||||||||||||||||||||||||||||||||||||||||
| - cp docs/fdroid/barcode_reader.floss.dart lib/scan/barcode_reader.dart | ||||||||||||||||||||||||||||||||||||||||||||||
| - | | ||||||||||||||||||||||||||||||||||||||||||||||
| sed -i "s/^\([[:space:]]*mobile_scanner:.*\)/\1\n flutter_zxing: ^2.3.0\n camera: ^0.11.0/" pubspec.yaml | ||||||||||||||||||||||||||||||||||||||||||||||
| - sed -i '/^[[:space:]]*mobile_scanner:/d' pubspec.yaml | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+88
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): The F-Droid recipe changes the working subdirectory to Triggers: When fdroiddata executes this recipe with Suggested fix: Run the root-level patch commands from the repository root, or prefix their paths with
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
| # geolocator's GMS location backend → microG (see SECOND blocker above). | ||||||||||||||||||||||||||||||||||||||||||||||
| - | | ||||||||||||||||||||||||||||||||||||||||||||||
| cat >> app/build.gradle.kts <<'EOF' | ||||||||||||||||||||||||||||||||||||||||||||||
| configurations.all { | ||||||||||||||||||||||||||||||||||||||||||||||
| resolutionStrategy.dependencySubstitution { | ||||||||||||||||||||||||||||||||||||||||||||||
| val microg = "0.3.14.250932" | ||||||||||||||||||||||||||||||||||||||||||||||
| substitute(module("com.google.android.gms:play-services-location")).using(module("org.microg.gms:play-services-location:$microg")) | ||||||||||||||||||||||||||||||||||||||||||||||
| substitute(module("com.google.android.gms:play-services-base")).using(module("org.microg.gms:play-services-base:$microg")) | ||||||||||||||||||||||||||||||||||||||||||||||
| substitute(module("com.google.android.gms:play-services-basement")).using(module("org.microg.gms:play-services-basement:$microg")) | ||||||||||||||||||||||||||||||||||||||||||||||
| substitute(module("com.google.android.gms:play-services-tasks")).using(module("org.microg.gms:play-services-tasks:$microg")) | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||||||||||
| output: app/build/outputs/apk/release/app-release-unsigned.apk | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| AutoUpdateMode: Version | ||||||||||||||||||||||||||||||||||||||||||||||
| UpdateCheckMode: Tags | ||||||||||||||||||||||||||||||||||||||||||||||
| CurrentVersion: 0.9.29 | ||||||||||||||||||||||||||||||||||||||||||||||
| CurrentVersionCode: 62 | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: OpenStrap/edge
Length of output: 5459
Security Misconfiguration (CWE-829): Inclusion of Functionality from Untrusted Control Sphere
Reachability: Internal · Exploitability: Difficult
Pin
actions/checkoutto a full commit SHA.@v4is mutable. A compromised or retargeted action can run code in this release job before the later step usesFDROID_GITLAB_TOKEN.🧰 Tools
🪛 zizmor (1.29.0)
[error] 266-266: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Source: Linters/SAST tools