Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

In CI

One command makes drift fail a build:

devset status --exit-code

It exits 1 exactly when devset apply --force would write a file, or an update is unfinished: an owned file edited, deleted or never recorded; a file a profile added and the target has not applied; a conflict waiting in .devset/conflicts/. A local edit that is the target’s to make, to a merge or a once file, never fails it, and neither does a change of whitespace alone.

Installing devset

Pin devset in the repository’s mise configuration, so every machine and every job runs the same version:

mise use github:atomix-labs/devset@0.5.3

Then a GitHub Actions job installs it with the rest of the repository’s tools:

jobs:
  devset:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: jdx/mise-action@v4
      - run: devset status --exit-code

GitHub Actions

Under GitHub Actions, devset also annotates each file that needs doing on the pull request, as an error where the gate fails and a warning where apply would write, and adds a table of them to the job’s summary page:

::error title=devset,file=a.toml::a.toml is edited; `devset apply --force` would restore it
::warning title=devset,file=c.toml::c.toml is new; `devset apply` would create it

Credentials

A git source’s repository is fetched with the job’s own git, so its credential helpers, SSH keys and insteadOf rules apply as they do to any git fetch. devset never lets git prompt where there is no terminal to answer, so a private repository needs a credential helper or an SSH key set up before devset runs.

Status as JSON

devset status --json prints the survey for scripts:

FieldHolds
layersEach layer, in order: name, profile as source/name, features, configured, required_by, version, source, rev, digest, and applied, one of current, changed and never
filesEach managed file or part: path, scope, part, layer, policy, state, what apply and apply --force would do to it, apply and force, and gate, why its gate released it
settingson-conflict, and the merge driver: builtin, or its command line
answersEvery variable’s answer
suggestionsMerge drivers a layer suggests that the target has not set
driftedWhether apply --force would write a file
unfinishedWhether an update is unfinished

A file’s state is one of unchanged, cosmetic, edited, missing, new, untracked, dropped and conflict. What apply would do is one of create, adopt, update, restore, overwrite, merge, record, untrack, remove and conflict, or null for nothing. status --exit-code fails when drifted or unfinished is true.