Gradient v2.0.0
First stable release. Nix flakes evaluated, derivations built on remote workers, outputs in a built-in binary cache.
New Features
Teams
- Teams with grants on projects and caches, invitations, join requests and a team Admin role.
- Team workers: registered workers with access to every granted project.
- OIDC and SCIM groups mapped onto team membership instead of project roles.
- Teams, grants, workers and members declarable in
services.gradient.state. - Team creation behind
--permissions-create-team. - Team pages in the web UI: overview, members, workers, settings and recent evaluations of granted projects.
- Mail actions addressable as
team:<name>.
Gradient.CI Servers
- A connection token linking an instance to a team.
- A server connection to a worker, with the caller's tokens checked against
acceptedServerTokensFile. - An admin page for base workers, with Connect base server.
- The state and last error of each connection in the web UI.
SSH builds
- An SSH server for
ssh-ngclients andnixos-rebuildbuild hosts. - A build request as an evaluation on the worker pool, with an evaluation per connection.
nix copyinto the project caches.nix.gradient-sshas a remote builder.- Build logs streamed to the Nix client as build activities.
Evaluations
- Import from derivation: a derivation built on the fleet, its outputs awaited by the evaluation (#668).
- Live progress: thunks, flake input downloads, the
nar_fetchandnar_importphases, upload progress (#658). - An entry point per attribute, with imported derivations tagged.
- Abort and retry of a single build from the log page (#673). A whole evaluation is retryable too.
retry_failed_buildsper task: permanent failures stay failed until a retry.- Wildcard grammar:
*for any attribute,**for a nested set below it,x86_64-*for part of a name,!to exclude. - Evaluation summary and entry point search.
- Parallel evaluations from
gradient evalandgradient build, with fork workers.
Scheduling
- A time estimate per build over download, build and upload, learned per path and per megabyte.
- Build resource usage from the Nix daemon build result, in place of the cgroup sampler (#357).
- Large transfers held back while the upload or download slots are full.
- A RAM reservation per build. A retry for an out-of-memory build. An early failure for an oversized build.
- A QoS bonus from the scheduler for prioritized builds and evaluations.
- Cluster jobs: a multi-worker cluster per evaluation, on idle workers of a zone, with reservations and member signals.
Caching and storage
- Pull-through as a cache option.
- Refusal codes from upstream caches. An unresponsive upstream: another probe instead of a build.
- Deep GC over storage, shard by shard, paced and resumable.
- S3 build log sharding, the same as for local logs.
- Download concurrency from storage: 16 connections. Upload concurrency: 8.
- A configurable NAR transfer chunk size on server and worker.
Web UI
- A storage and transport health board.
- A job board with scheduler and health rows, job decisions and live worker load.
- A full-width log page, with the builds list in a drawer on phones (#766).
- Phone layouts: swipeable stat rows, icon-only buttons, row menus, two-line entry point rows.
- Skeletons for the dashboard, cache stats, NAR tables and the task page.
- An SSH keys settings page.
frontend.logoUrlfor a custom logo on the sign-in pages.- Editable Matrix and Slack actions (#689).
- Missing worker connections marked on the task page (#716).
Nix and deployment
- The standalone host as a VM with
nix run .#standaloneand as an OCI image on ghcr. environmentVariablesoptions for the server and the worker.- A public URL option for a deployment behind a port mapping.
- The deploy module renamed to
gradient-clientandnix.gradient-sshas a remote builder. - Gradient as the preferred remote builder, with
speedFactor 128. - gradient-evalbench: a VM benchmark with an HTML report and a published bundle.
- A
latestbranch for stable releases and abetabranch for every release, moved by the release workflow. - A signed build provenance and an SBOM for the standalone image.
API and protocol
- A protocol version agreement before the first message, with per-field protocol versions.
Authenticatewith the caller's tokens, out of traces.- Cluster membership, roster and signals, with handover and path list messages for shared workers.
- New endpoints for teams, ssh keys, upstream caches and admin draining.
POST /builds/{build}/abort,/builds/{build}/retry,/evals/{evaluation}/retryand/evals/{evaluation}/summary./caches/{cache}/upstream-cachesin place of/caches/{cache}/upstreamsand/hooks/{git_host}/...in place of/hooks/{forge}/....
Bug Fixes
- A retry for the builds of a failed or aborted evaluation. An abort for queued builds.
- Substituted outputs out of the build history. Unmeasured values as null.
- A crashing evaluation attribute: only itself failed. Every failed attribute under its own source (#788).
- The evaluation memory cap during a call. A crashed batch member, listed member by member.
- Exit code 2 as an out-of-memory kill.
- A worker after a lost network: reconnect (#782).
- An outdated upstream file size on a NAR body: accept it when the hash matches.
- An upstream cache with reset HTTP/2 streams: pin it to HTTP/1.1 and resume its broken NAR body (#698).
- First stored content for a store path. An upload order until the row commit.
- A failed build's reason as an error line in its log. Missing log chunks as placeholder lines.
- Streamed build log lines, with the package named once.
- Job offers chunked by encoded size. No worker connection lost to a large offer.
- A job failure behind its log chunks, keeping the end of a failed build log.
- Worker ids owned by base workers or other connections: refused. Frames read before authentication: capped.
- An integration dropped from the state file: deleted or unmanaged. Teams applied before projects.
- A custom role in use by a team grant: no deletion.
- A hand-managed team Admin: out of OIDC and SCIM group removals.
- A deleted team's workers: jobs stopped on the granted projects.
- The frontend session over a 429 from
/user. Rate-limited requests retried. Search state over an evaluation switch. - Percent charts capped at 100% (#678).
- The dependency graph from build inputs only, laid out in linear time.
- Umlauts as ae/oe/ue in name slugs.
ssh://repository URLs with owner and repository parsed. An approval in Gradient without a PR review submission.- The Slack webhook URL: out of delivery errors (#751).
- An SSH build without a connected worker: abort. Nix clients learn the reason (#717).
- The full error chain for Nix clients. Build logs as build activities (#718).
- A request's error: out of the shared evaluation.
- The standalone container with a console, bound to localhost and with a persisted VM store. A PATH for
docker exec(#729). - An eval cache shared between the evaluators of a flake. A failed attribute evaluated again, not read from a cached failure. A new copy of a fetched source after garbage collection of an earlier copy.
- Evalbench Postgres plan output in a file instead of the serial console.
update-versionwith pre-release versions and every frontend workspace package.
Performance
- Queued NARs committed in a single transaction, narinfo rows signed inside the batched commit, each ingest step on the actor's transaction.
- Graph rows locked
FOR NO KEY UPDATE, so foreign-key checks wait behind no flush. - Dependency counting from a single read of the evaluation's jobs. Counters in a single SQL call per level.
- A new evaluation estimated from the evaluations outside the most common values. Status counting for the evaluation list from the index alone.
- Startable build offers without waiting on the graph writer. Eval dispatch woken on evaluation creation.
- The derivation closure walked concurrently in waves of 256, each batch's .drv files and sources pushed during the evaluation.
- A window of 128 in flight for small uploads. An upload slot freed after its transfer.
- Cache signing keys and stored secrets decrypted once, not per signature.
- Derivation paths resolved in the eval worker's list call, without the resolve phase.
@gradient/uifree of side effects. Unused UI parts leave the initial bundle.- No
nix flake archivewhen every locked input is in the store. A cloned tree added as its source path directly. - The upstream probe woken on commit, asking about the dependencies of wanted jobs in the same round.