Shorebird Documentation

repository·main·Indexed 25 days ago

https://github.com/shorebirdtech/shorebird

Shorebird provides Flutter 'over-the-air' updates (CodePush), enabling developers to push code changes without app store reviews. The repository includes a CLI, backend infrastructure, and various utility packages such as shorebird_ci for CI/CD workflow generation, a Redis client, a JWT verification library, and tools for parsing and diffing Android Dalvik Executable (DEX) files.

Tokens
19.8K
Snippets
39
Records
155
Agent score
84%

What's inside Shorebird

  1. Overview of Shorebird packages

    main

    Shorebird is a monorepo containing several specialized packages:

    • shorebird_cli: Command-line interface for interacting with Shorebird services.
    • shorebird_code_push_client: Dart library for Dart applications to interact with the Shorebird CodePush API.
    • shorebird_code_push_protocol: Dart library containing common interfaces used by Shorebird CodePush.
    • artifact_proxy: Dart server for intercepting and proxying Flutter artifact requests.
    • discord_gcp_alerts: Dart server for forwarding GCP alerts to Discord.
    • flutter_version_resolver: CLI utility to determine the correct Flutter version for a project.
    • jwt: Dart library for verifying JSON Web Tokens.
    • redis_client: Dart library for interacting with Redis.
    • scoped_deps: Dependency injection library built on Zones.
    • stripe_api: Dart library for interacting with Stripe.
  2. Overview of Shorebird Stripe Client

    main
    The Shorebird Stripe Client is a Dart library designed for interacting with the Stripe API. It provides a subset of the Stripe API specifically tailored to meet the needs of the Shorebird ecosystem. It is intended for server-side Dart environments where a comprehensive Stripe package might be unavailable.
  3. Understand the shorebird_ci workflow structure

    main

    The shorebird_ci.yaml workflow produced by shorebird_ci generate typically consists of the following job sequence:

    • setup: Activates shorebird_ci on the runner, runs verify (to fail the build if CI coverage has drifted from the dependency graph), and runs affected_packages to generate a JSON matrix of packages that need testing.
    • dart_ci: A fan-out job that runs format, analyze, and test for every package identified in the affected packages matrix. This includes transitive dependents (e.g., if core changes, app is also tested).

    Additional features based on project configuration:

    • Flutter support: If Flutter packages are detected, a flutter_ci job is added. If a flutter_version is pinned in the pubspec, it is resolved automatically.
    • Code Coverage: If codecov is configured, coverage upload steps are included.
    • Spell Checking: If a cspell configuration is present, a cspell job is added.
  4. Quick Start with shorebird_ci

    main

    Use shorebird_ci to generate GitHub Actions workflows that automatically detect package changes and run relevant CI jobs.

    1. Preview changes: Run with --dry-run to see what the tool would write without modifying files.
    2. Generate workflow with aggregator: Run with --required to write the workflow and add a single required aggregator check. This check is designed to be used in your GitHub branch protection rules to ensure all affected packages pass CI without needing to update protection rules every time packages change.
    shorebird_ci generate --dry-run            # review what it would write
    shorebird_ci generate --required           # write + add a single aggregator check
  5. Avoid using mixins in Shorebird Dart code

    main
    To improve testability and dependency management, avoid using mixins. Mixins cannot be tested directly and act as unmockable dependencies for the classes they are mixed into, forcing every consumer to mock the mixin's dependencies. Instead, prefer creating a new class as a scoped dependency or adding the logic to an existing scoped dependency.
  6. Generate and view coverage reports

    main

    To generate a coverage report, first install lcov (e.g., via brew install lcov), then run tests with the --coverage flag and generate the HTML report.

    1. Install lcov: brew install lcov
    2. Run tests: very_good test -r --coverage
    3. Generate HTML: genhtml coverage/lcov.info -o coverage
    4. View report: open coverage/index.html
    brew install lcov
    very_good test -r --coverage
    genhtml coverage/lcov.info -o coverage
    open coverage/index.html
  7. Diff two DEX files with DexDiffer

    main

    Use DexDiffer to perform a structural comparison between two parsed DEX files. The differ uses full index remapping to handle string table reordering (e.g., caused by different build paths).

    Check the isSafe property of the result to determine if the differences are non-breaking (such as source_file attributes or debug_info offsets). If isSafe is false, use describe() to get a description of the differences.

    import 'package:dex/dex.dart';
    
    const parser = DexParser();
    final oldDex = parser.parse(oldBytes);
    final newDex = parser.parse(newBytes);
    
    final result = const DexDiffer().diff(oldDex, newDex);
    
    if (result.isSafe) {
      print('Only safe differences (e.g. source file paths)');
    } else {
      print(result.describe());
    }