dev
Build, check and test a repository from what it declares about itself.
What it does
dev is the development command line for a repository laid out on the framework. The repository says what it is in two documents, and dev does the work from them:
manifest.yml, at the repository’s root, declares the project, its modules, what each module depends on and which repo adapter builds it..dev-tool/config.ymlholds this tool’s settings for the repository: the roots it reads, the libraries it obtains, the checks its gate runs.
One command surface then serves every repository, whatever language it is written in. dev knows what a lint, a build or a test run is asked to cover; the repository’s repo adapter knows how that language does it.
Install it with toolchain install dev-tool. It is run as dev, from anywhere inside the repository:
dev --help
dev <command> --help
Concepts
A module. The unit the manifest declares: a library other code imports, an executable that is built, or a repository pinned inside this one. Most commands take --modules to work on the modules named and --paths to work on the paths named; with neither, a command covers the repository’s own roots.
A repo adapter. The package that carries a language’s tooling: its formatter, linter, type checker, test runner and builder. The manifest names one by coordinate, <namespace>:<name>, and dev vendor obtains it. dev hands the adapter the same question for every language and reports its answer the same way.
A coordinate. How a package is named wherever it is published: <namespace>:<name>, with @<major>.<minor>.<patch> to name one release. A repository lists the libraries it uses by coordinate, and dev vendor places each in lib/.
A tier. Tests are kept in tiers, each a folder inside a test directory. unit holds the tests that start no process and is what a run collects unless asked otherwise; integration holds the ones that do. A repository may declare its own tiers under testTiers.
A pinned repository. A repository checked out inside this one as a git submodule. A command stops at that boundary unless it is given --recurse, which runs the same command in each pinned repository by that repository’s own settings.
Everyday commands
| Command | What it does |
|---|---|
dev vendor |
Obtain the libraries and the repo adapter the repository declares |
dev sync |
Install the repository’s dependencies into its environment |
dev format |
Format sources |
dev lint |
Run the linter and the repository’s custom rules; --fix repairs what it can |
dev type check |
Validate the repository’s schema documents and type-check its sources |
dev test |
Run tests and report the outcome and how long the run took |
dev build |
Build each executable module, and publish each library module to the repository’s build catalog |
dev gate |
Run the repository’s verification gate |
dev selection |
Report what a run of the tests, the linter or the type check would cover, and run nothing |
dev todos |
Report TODO and LATER comments |
A fresh clone is brought up with dev vendor and then dev sync. After that, dev gate and dev test are the two commands an edit is owed.
The gate
dev gate runs a list of checks, each a command of this tool, and ends with one line per check: whether it passed and how long it took. The gate holds no test; dev test is run beside it.
The list is the tool’s default unless the repository states its own:
# .dev-tool/config.yml
gateAdditions:
- after: lint
commands:
- command: build
args:
- --libraries-only
gateAdditions adds checks to the default, each group after the command it names. gate replaces the default list whole. Each check may state a placement: local for a check a developer’s run makes, ci for one left to continuous integration, and both where it states none. A plain dev gate runs the both and local checks and names the ones it left to CI; dev gate --ci runs the both and ci checks; dev gate --all runs every one.
--only and --skip name checks by their command. --check refuses a run that had to change a file, which is how CI holds a commit to having been formatted before it was pushed.
Tests
dev test
dev test --paths packages/app/src/login
dev test --all-tiers
dev test --tier integration
A run that names nothing covers the default tier. --select affected covers only the tests that the uncommitted work reaches, worked out from the dependencies the manifest declares; --since <ref> asks the same of everything changed since a commit. --select all runs the whole suite. dev selection --of test --select affected reports what such a run would cover without running it.
A test kept in no declared tier’s folder is refused by name, and a test in a tier declared isolated that starts a process is failed by the run.
What the repository declares, checked
These report by default and refuse with the flag shown, so each can stand in the gate.
| Command | What it holds |
|---|---|
dev module declared-dependencies --validate |
The manifest’s dependencies are well formed: no unknown module, no cycle, no dependency on an executable |
dev module detect-dependencies --validate |
What the code imports is what the manifest declares |
dev module exports --validate |
A parent module’s surface re-exports nothing straight through from a submodule |
dev project crossings --check |
The repository declares and configures nothing inside a repository it pins |
dev project markers --check |
A project whose content has moved since its release says so in its version |
dev gitignore gen --check |
The repository’s .gitignore is the one generated from the shared set and its own additions |
dev module list, dev module graph, dev module published and dev module executables report what the manifest declares and what a build of it produces. dev project dependencies reports what a release of the repository depends on, and dev project test-files which tracked files the repo adapter calls tests.
Settings
.dev-tool/config.yml is read from the repository’s root. The settings most repositories state:
| Key | What it says |
|---|---|
ownRoots |
The directories that are this repository’s own source |
vendoredLibraries |
The libraries dev vendor obtains, by coordinate |
gate, gateAdditions |
The gate’s checks, as above |
testTiers |
The tiers tests are kept in, and which a plain run collects |
inertPaths |
Paths whose changes reach no test and no check |
gitignoreAdditions |
Lines the generated .gitignore carries beyond the shared set |
dev config init writes a starting configuration. A standing value for a command’s argument is stated in .dev-tool/cli.config.yml, under argDefaults, and the same argument on the command line overrides it.
Output
Every command answers in plain text by default and as one JSON document with --response-format json: the command’s own answer under data, exitCode, and errors, each a code and a message. A refusal is always a named code, and the message says what was found and what to change. --verbose and --log-level say how much of the work is narrated on the way.
The tool’s own version
dev version show prints the version in use, dev version list the releases there are for this machine, and dev update moves an installed one to the newest.