Skip to content

Feature rustler precompiled#71

Merged
ocean merged 9 commits intomainfrom
feature-rustler-precompiled
Feb 1, 2026
Merged

Feature rustler precompiled#71
ocean merged 9 commits intomainfrom
feature-rustler-precompiled

Conversation

@ocean
Copy link
Owner

@ocean ocean commented Jan 31, 2026

Summary by CodeRabbit

  • New Features

    • Deliver precompiled native libraries for macOS and Linux (x86_64, aarch64), built automatically on tags and via manual dispatch.
  • Chores

    • Added CI workflow to build, upload and publish precompiled artifacts on release.
    • Introduced a release build profile with LTO for optimized binaries.
    • Added an environment toggle to force local native builds and improved cross-compilation support.

✏️ Tip: You can customize this high-level summary in your review settings.

ricardo-valero and others added 4 commits January 29, 2026 14:09
Replace source compilation with prebuilt NIF downloads so users no longer
need Rust, cmake, or pkg-config installed. First compile drops from 5-10
minutes to seconds.

Changes:
- mix.exs: add rustler_precompiled dep, make rustler optional, include
  checksum files in hex package
- native.ex: use RustlerPrecompiled with 6 Linux/macOS targets
- Cargo.toml: pin NIF version 2.15 feature, add release LTO profile
- .cargo/config.toml: cross-compilation flags for macOS and musl
- release.yml: GitHub Actions workflow to build NIFs for all targets
  on tag push using philss/rustler-precompiled-action

Users can force local compilation with ECTO_LIBSQL_BUILD=true.
- Revert .gitignore changes (not part of this PR)
- Bump Cargo.toml rustler from 0.37.0 to 0.37.1 (0.37.0 was retired)
- Add ECTO_MIGRATION_GUIDE.md and SECURITY.md to hex package files
- Use lto = "thin" instead of "true" for better build-time trade-off
- Remove unused id-token and attestations permissions from release.yml
- Add version extraction validation to fail fast on parse errors
…ries

The rustler-precompiled-action post-build script expects compiled binaries
in target/<target>/release, but Cargo was placing them in target/release
instead, causing 'cd: target/<target>/release: No such file or directory' errors.

Changes:
- Add CARGO_BUILD_TARGET env var to force consistent target-specific directory
  structure (more reliable than --target flag alone)
- Install target via dtolnay/rust-toolchain to ensure target is available
- Update macOS runners to latest LTS:
  - aarch64-apple-darwin: macos-14 → macos-15 (Apple Silicon)
  - x86_64-apple-darwin: macos-13 → macos-15-intel (Intel x86)
- Update Ubuntu runners from 22.04 to 24.04 (latest LTS)

This ensures all 6 platform targets build correctly with up-to-date runners.

Fixes #70

Amp-Thread-ID: https://ampcode.com/threads/T-019c13c5-09fc-748e-84d9-59b30e8bc1a7
Co-authored-by: Amp <amp@ampcode.com>
The standard CI workflow runs on every commit/PR and was failing trying
to download precompiled NIFs that don't exist until after a release is
tagged and the build workflow completes.

Solution: Set ECTO_LIBSQL_BUILD=true in the CI workflow so all builds
compile the NIF from source. This ensures:

- Regular CI (commits/PRs) always compiles from source and works
- Release workflow (on tags) builds precompiled NIFs for distribution
- No circular dependency between CI and precompilation
- Users get faster installation via precompiled NIFs after release
- Developers/CI always have fresh builds from source

This aligns with the rustler_precompiled design: precompiled binaries
are optional for end-users, but CI should always build from source.

Amp-Thread-ID: https://ampcode.com/threads/T-019c13c5-09fc-748e-84d9-59b30e8bc1a7
Co-authored-by: Amp <amp@ampcode.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 31, 2026

Walkthrough

Adds precompiled NIF distribution: GitHub Actions workflow to build and publish precompiled Rust NIFs, switches Elixir loader to RustlerPrecompiled, adjusts build/config for cross-compilation, and exposes ECTO_LIBSQL_BUILD to CI to optionally force local NIF builds.

Changes

Cohort / File(s) Summary
GitHub Actions Workflows
.github/workflows/ci.yml, .github/workflows/release.yml
Adds ECTO_LIBSQL_BUILD env in CI and a release.yml workflow ("Build Precompiled NIFs") to build NIFs on tag/manual dispatch using a target matrix, validate mix.exs version vs tag, install Rust toolchains, run rustler-precompiled-action, upload artifacts, and publish archives on tag builds.
Elixir NIF loader & mix config
lib/ecto_libsql/native.ex, mix.exs
Replaces Rustler with RustlerPrecompiled and configures otp_app, crate, version, base_url (GitHub releases), targets, nif_versions, mode (dev/test => :debug, else :release), and force_build driven by ECTO_LIBSQL_BUILD. Makes rustler optional, adds rustler_precompiled dependency, introduces @dev? and @force_build? attributes, and expands package files list.
Workspace & Rust build config
Cargo.toml, native/ecto_libsql/Cargo.toml, native/ecto_libsql/.cargo/config.toml
Enables thin LTO in workspace release profile. Updates rustler dependency to 0.37.1 with default-features = false and features derive and nif_version_2_15. Adds per-target rustflags for macOS (allow undefined symbols) and musl targets (disable crt-static) to support cross-compilation for BEAM loading.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(135,206,250,0.5)
    participant Dev
    participant GH_Actions as "GitHub Actions (release.yml)"
    participant Rust_Toolchain as "Rust toolchain"
    participant Rustler_Action as "rustler-precompiled-action"
    participant GH_Releases as "GitHub Releases"
  end

  rect rgba(144,238,144,0.5)
    participant Elixir_App as "Elixir app runtime"
    participant GH as "GitHub (download)"
    participant NIF as "Precompiled NIF artifact"
  end

  Dev->>GH_Actions: Push tag / manual dispatch
  GH_Actions->>Rust_Toolchain: Install target toolchains
  GH_Actions->>Rustler_Action: Build NIFs for matrix targets
  Rustler_Action->>GH_Releases: Upload artifacts
  GH_Releases-->>GH_Actions: Release published

  Note over Elixir_App,GH: At runtime
  Elixir_App->>GH: Request precompiled NIF (base_url)
  GH->>Elixir_App: Serve artifact
  Elixir_App->>NIF: Load precompiled NIF via RustlerPrecompiled
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through CI with a tiny cheer,
I fetched prebuilt NIFs from releases near,
Tags set the pace, targets wide,
Cross-built crates now at my side,
🥕 — a rabbit's nibble of deploy-time cheer.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarises the main change: introducing Rustler Precompiled support across the codebase, which is evident from the modifications to NIF loading, workflow automation, and build configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature-rustler-precompiled

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/release.yml:
- Around line 40-50: The workflow currently extracts mix.exs into the VERSION
variable and writes PROJECT_VERSION to GITHUB_ENV but doesn’t check the git tag
— add a guard that derives the pushed tag (from GITHUB_REF or GITHUB_REF_NAME)
and compares it to VERSION; if they differ, emit an error and exit non‑zero so
the job fails fast, and only export PROJECT_VERSION when the tag matches the
extracted VERSION. Reference the existing VERSION variable, the environment ref
(GITHUB_REF / GITHUB_REF_NAME), and PROJECT_VERSION in your fix.

ocean and others added 4 commits January 31, 2026 23:03
…ispatch

Previously triggered on:
- Every push to main with native changes (wasteful)
- Every PR that touched the workflow file (not needed)

Now triggers only on:
- Version tag pushes (v*) - for actual releases
- Manual workflow_dispatch - for testing/ad-hoc builds

This aligns with the workflow's purpose: building precompiled NIFs for
distribution. Regular CI (on commits/PRs) is handled separately by ci.yml.

Simplifies the trigger logic and avoids wasted CI time on main branch updates.

Amp-Thread-ID: https://ampcode.com/threads/T-019c13c5-09fc-748e-84d9-59b30e8bc1a7
Co-authored-by: Amp <amp@ampcode.com>
Added version validation in the release workflow to prevent mismatches
between git tags and project version. The workflow now:

1. Extracts VERSION from mix.exs @Version attribute
2. Extracts GIT_TAG from GITHUB_REF_NAME (e.g., 'v0.8.10')
3. Compares TAG_VERSION (tag without 'v' prefix) with VERSION
4. Fails fast with error if they don't match
5. Only exports PROJECT_VERSION if validation passes

This prevents accidental releases with mismatched versions, ensuring:
- Git tag (v0.8.10) matches mix.exs (0.8.10)
- Clear error messages if mismatch is detected
- Job fails immediately before building artifacts

Example error:
  Version mismatch: mix.exs version is '0.8.10' but git tag is 'v0.8.9'

Amp-Thread-ID: https://ampcode.com/threads/T-019c13c5-09fc-748e-84d9-59b30e8bc1a7
Co-authored-by: Amp <amp@ampcode.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/release.yml:
- Around line 32-55: The version check fails for workflow_dispatch because
GITHUB_REF_NAME is a branch name; update the validation to first detect tags by
checking GITHUB_REF (e.g., only run the tag-vs-mix.exs comparison when
GITHUB_REF starts with "refs/tags/"). In the shell block that extracts VERSION,
add a conditional using GITHUB_REF to skip the tag comparison when not a tag
(keep setting PROJECT_VERSION and printing a message), otherwise proceed with
the existing GIT_TAG/TAG_VERSION comparison logic (variables VERSION, GIT_TAG,
TAG_VERSION) and error/exit on mismatch.

@ocean ocean merged commit 6db9204 into main Feb 1, 2026
14 checks passed
@ocean ocean deleted the feature-rustler-precompiled branch February 1, 2026 23:25
@coderabbitai coderabbitai bot mentioned this pull request Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants