-
Notifications
You must be signed in to change notification settings - Fork 7
Internal precompile binaries hook #22
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?
Internal precompile binaries hook #22
Conversation
|
This is looking nice, added a bunch of comments/questions, and if you can run I’ll set up the signing secret later, let me know if any other maintainer setup is needed. |
| on: | ||
| push: | ||
| branches: [main, "**"] | ||
| branches: [main] |
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.
Did you remove ** to reduce duplicate CI runs on branch pushes?
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.
Yes, but this is something you can assess and configure.
| GITHUB_TOKEN: ${{ github.token }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions-rs/toolchain@v1 |
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.
This uses toolchain: stable, but native/rust-toolchain.toml pins 1.85.1 and the CLI reads that channel when running rustup run. Should we switch to toolchain-file: native/rust-toolchain.toml (or set toolchain: 1.85.1) so precompiled artifacts are built with the pinned toolchain? Same applies to the Android job.
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.
We switched both precompile jobs from stable to the pinned 1.85.1 toolchain. Pinning to 1.85.1 keeps a single source of truth and avoids subtle build/compatibility drift.
README.md
Outdated
| ``` | ||
|
|
||
| `mode` controls when the precompiled path is used: | ||
| - `auto` prefers precompiled binaries when available, otherwise builds locally |
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.
auto is described as preferring precompiled, but the hook currently disables precompiled when rustup is present (UserOptions.defaultUsePrecompiledBinaries). Should we update this wording to reflect the rustup heuristic, or change the behavior to match the doc
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.
I suggest updating the wording in README.md. It now explicitly states that auto prefers local builds when the Rust toolchain (rustup) is detected; otherwise, it uses precompiled binaries.
docs/precompiled_binaries.md
Outdated
| - CI builds and uploads precompiled binaries via `.github/workflows/precompile_binaries.yml`. | ||
| - Artifacts are tagged by the crate hash and uploaded to a GitHub release. | ||
| - Each binary is signed with an Ed25519 key; the public key is embedded in `pubspec.yaml`. | ||
| - The build hook tries to download a verified binary first and falls back to a local build if needed. |
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.
The doc says ‘download verified binary first and fall back’; should we note that mode: always is intended to disable fallback (once that behavior is enforced), or explicitly call out the rustup heuristic for auto?
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.
Added a “Mode behavior” section. It clarifies that always currently falls back but is intended to fail if a verified binary isn’t present, and reiterates how never operates.
| ); | ||
| } | ||
|
|
||
| if (precompiled.mode == PrecompiledBinaryMode.never) { |
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.
mode: always currently just returns null on download/verify failure, which triggers fallback in PrecompiledBuilder. Should always fail the build instead so it truly requires precompiled binaries?
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.
lib/src/precompiled/artifacts_provider.dart now tracks when mode == PrecompiledBinaryMode.always and throws PrecompiledBinaryRequiredException on any download/verification failure instead of returning null. Since PrecompiledBuilder does not catch that exception, the build fails rather than falling back whenever mode=always cannot obtain a signed artifact—so the builder enforces the “require precompiled” promise.
| exitCode = 2; | ||
| return; | ||
| } | ||
| if (repository == null || repository.trim().isEmpty) { |
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.
--repository is required but never used in any gh release calls; should we pass --repo $repository to view/create/upload (or drop the flag if it’s not needed)?
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.
Forgot to call it out earlier: --repository was left unused in the release commands by mistake, but we’ve since wired it back in. This lets us rerun the tool against another repo (e.g., for testing or experimentation) without editing the workflow. In production it still defaults to the current repo, so the rest of the release flow behaves as before.
| '--package', | ||
| cratePackage, | ||
| '--release', | ||
| '--locked', |
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.
We pass --locked to cargo, but there’s no committed native/Cargo.lock in this repo; cargo build --locked will fail without it. Should we add native/Cargo.lock or remove --locked?
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.
Lock file added and .gitignore updated to allow lock file changes.
| final output = AccumulatorSink<Digest>(); | ||
| final input = sha256.startChunkedConversion(output); | ||
|
|
||
| void addTextFile(File file) { |
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.
We concatenate lines from multiple files without a delimiter or filename marker which could (rarely) lead to hash collisions if file boundaries change. Should we consider prefixing each file with its path (or a separator) before hashing to make the hash more robust?
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.
That scenario is extremely rare isn't it? we would have to arrange contents to collide via a prefix/suffix shift. I believe a lightweight fix ( a separator before its contents) should be sufficient.
| ); | ||
|
|
||
| final downloaded = await provider.tryGetPrecompiledArtifact(); | ||
| if (downloaded != null) { |
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.
If we enforce mode: always, should we be surfacing a hard failure here (or in PrecompiledArtifactProvider) so the build doesn’t silently fall back when always is set?
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.
PrecompiledArtifactProvider now throws PrecompiledBinaryRequiredException on any download/verify failure when mode == always. Since PrecompiledBuilder already propagates provider exceptions, the build will now fail fast instead of silently falling back—honoring the “require precompiled binaries” promise.
|
Thanks for the review 🧡 PR updated to address review comments and to provide more info. |
Precompiled Binaries Feature
Resolves #20
This PR introduces a comprehensive precompiled binaries system that significantly improves the developer experience by reducing build times and providing secure, signed artifacts.
Key Features
Secure Distribution
Performance Improvements
auto,always, orneverDeveloper Experience
Configuration
Users can configure precompiled binaries in their
pubspec.yaml:Defaulting to auto which most users would want.