Use this guide for host-runtime dependencies before Rindle background jobs process variants. Image processing uses libvips (via Vix). AV processing uses FFmpeg.
Image runtime (libvips)
Image-only adopters need libvips on the host before ProcessVariant jobs run:
- install libvips for the target platform
- run
mix rindle.doctor - only then start background jobs that generate image variants
| Platform | Install |
|---|---|
| macOS (Homebrew) | brew install vips |
| Ubuntu / Debian (apt) | sudo apt-get update && sudo apt-get install -y libvips-dev |
| Alpine (apk) | apk add --no-cache vips-dev |
| GitHub Actions | sudo apt-get install -y libvips-dev (same as CI quality job) |
AV runtime (FFmpeg)
Use this section when your adopter app enables video or audio processing. The AV runtime contract is small and explicit:
- install
FFmpeg >= 6.0for the target platform - run
mix rindle.doctor - only then start background jobs that process AV variants
README stays the narrow quickstart. Getting Started is the canonical deep onboarding guide. This file is the shared install/runtime matrix both of those entrypoints link to.
Maintainer: CI lane severity
Adopters can skip this section. It documents how this repository gates merges and releases.
.github/workflows/ci.yml is the source of truth for job wiring; GitHub branch protection and required-check settings live outside the repo.
| Job / step | Severity | When it runs | Notes |
|---|---|---|---|
quality — Compile, Check formatting | merge-blocking | Every PR/push; Elixir 1.15/OTP 26 and 1.17/OTP 27 matrix | Both matrix cells must pass |
quality — Credo (strict) | advisory | Same job | Step-level continue-on-error |
quality — Doctor (full, raise) | advisory | Same job | Step-level continue-on-error |
quality — Verify AV runtime with public doctor task | advisory | Same job | Step-level continue-on-error |
quality — Run tests with coverage | merge-blocking | Same job | Default mix test suite via Coveralls; both matrix cells must pass |
quality — Dialyzer | advisory | Same job | Step-level continue-on-error |
integration | merge-blocking | needs: quality | Lifecycle + MinIO adapter tests |
contract — Run AV hygiene gate | merge-blocking | needs: quality | scripts/assert_av_hygiene.sh |
contract — Run contract tests | advisory | Same job | Step-level continue-on-error; job still required in graph |
proof | merge-blocking | needs: quality | docs_parity_test.exs, adoption proof matrix drift gate, batch_owner_erasure_task_test.exs; Postgres only; Elixir 1.17/OTP 27 |
package-consumer — repo hygiene gate | merge-blocking | Same job | scripts/maintainer/repo_hygiene_check.sh --ci |
package-consumer | merge-blocking | needs: quality | Install-smoke matrix + release preflight |
adoption-demo-e2e | merge-blocking | needs: quality; repo szTheory/rindle only | Playwright browser proof for examples/adoption_demo (image, tus, stretch journeys) |
adopter | merge-blocking | needs: [quality, integration, contract] | Canonical adopter lifecycle only (doc parity in proof job) |
mux-soak | secret-gated soak | Label streaming on PR; needs: quality | Not in branch protection required checks; fails closed when secrets absent |
gcs-soak | secret-gated soak | needs: quality; repo + secrets | Skipped when secrets absent; test step advisory when it runs |
package-consumer-gcs-live | secret-gated soak | needs: quality; repo + secrets | Job-level continue-on-error; live GCS install-smoke when secrets present |
Static analysis policy (CI-04)
Decision: Credo (strict) and Dialyzer remain advisory in the quality
job. Wiring uses step-level continue-on-error: true in
.github/workflows/ci.yml.
Making either tool merge-blocking is explicitly rejected for the current release train.
Rationale:
- Signal value: Static analysis catches style and typespec drift; failures remain visible in CI logs for maintainers without blocking adopter-critical merge lanes.
- Fork latency: Dialyzer PLT build is slow; merge-blocking would raise contributor and fork PR cost disproportionate to adopter impact.
- Green-main honesty: Adopter-critical lanes are already merge-blocking (
mix coveralls,proof,package-consumer,adopter,integration, contract AV hygiene). Static analysis is maintainer hygiene, not adopter contract.
Doctor and AV doctor steps remain advisory without a separate CI-04 decision record (CI-04 names Credo and Dialyzer only). See matrix rows above.
Release train
.github/workflows/release.yml gate-ci-green waits for
ci.yml on the release SHA to finish with conclusion success. When the latest run is
not green, or the wait times out, publish fails closed — there is no bypass path.
Branch protection required checks (enforced via scripts/setup_branch_protection.sh) include
Quality (both matrix cells), Integration, Contract, Proof, Package Consumer Proof Matrix +
Release Preflight, and Adopter.
Verify The Runtime
Run this in the adopter app after mix deps.get and after installing FFmpeg:
mix rindle.doctor
The command must pass before you debug Oban workers, variant failures, or delivery URLs.
FFmpeg Install Matrix
macOS (Homebrew)
brew install ffmpeg
mix rindle.doctor
Ubuntu / Debian (apt)
sudo apt-get update
sudo apt-get install -y ffmpeg
mix rindle.doctor
Alpine (apk)
apk add --no-cache ffmpeg
mix rindle.doctor
Fly.io Dockerfile
Add FFmpeg to the image build:
RUN apt-get update \
&& apt-get install -y ffmpeg \
&& rm -rf /var/lib/apt/lists/*Run mix rindle.doctor during build or release validation before the app
starts workers.
Heroku Aptfile
Add an Aptfile at the app root with:
ffmpegThen run mix rindle.doctor as part of release validation.
Render Dockerfile
Add FFmpeg to the Render image build:
RUN apt-get update \
&& apt-get install -y ffmpeg \
&& rm -rf /var/lib/apt/lists/*Run mix rindle.doctor in the build or pre-deploy command.
GitHub Actions
Use FedericoCarboni/setup-ffmpeg so CI exercises the same runtime posture:
- name: Install FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v3
with:
ffmpeg-version: 6.0
- name: Verify Rindle runtime
run: mix rindle.doctorCanonical AV Profile Shape
The onboarding story stays on the stock web_720p plus poster surface. The
explicit variant declarations are:
variants: [
web_720p: [kind: :video, preset: :web_720p],
poster: [kind: :image, preset: :video_poster_scene]
]That is the same public posture taught in README and Getting Started.