Target selection
Goals run against targets selected by an address or package path. Exact target
selectors use :name; package selectors omit the colon. A selector without a
leading // is relative to the current package, while // is relative to the
workspace root.
Illustrative example
# One target
imp build //apps/server:server
# Every target in a package, or recursively below it
imp test //apps/server
imp fmt //apps/...
# Every target in the workspace that supports the requested goal
imp lint //...
Package selectors automatically skip targets that do not implement the goal. An exact target selector instead reports that the target has no such workflow, which is usually a sign that the wrong goal or target was chosen.
A target may expose more than one root for the same goal. Two suffixes select between them:
# A named facet, when a workflow exposes several
imp test //crates/imp-store:imp_store@doctests
# One child of an expansion, by its key
imp run //rules/python/example:scripts#rules/python/example/scripts/demo.py
An expansion key is minted by the ruleset, so it is not always a bare name — an expansion keyed by source file uses that file's workspace-relative path, as above.
Give more than one selector
A command accepts any number of selectors and runs the union of what they select.
imp test //apps/server:server //libraries/parser:parser
Each selector must resolve on its own. If one of them matches nothing, the command fails and runs no work, even when the other selectors resolved — a mistyped address in a list is a mistake, not an empty set. An exact selector naming an address that exists but has no work for the requested goal reports what the address does provide:
$ imp test //apps/server:assets
error: //apps/server:assets has no 'test' workflow; it exports: build
Package and recursive selectors keep their filtering behaviour: imp test //... over a workspace of mostly non-test targets succeeds and runs the test
targets it found. Such a selector only fails when its address space is empty,
for example when it names a directory that does not exist.
Select changes from Git
--changed-since REF selects targets that own files changed since the merge
base of REF and HEAD, including committed, staged, unstaged, deleted, and
untracked non-ignored files in the working tree.
imp test --changed-since origin/main
imp lint --changed-since HEAD~1
Imp requires a Git checkout for this option. A changed source file selects
every target whose source globs own it. Changing a BUILD.js file selects its
whole package; changing imp.workspace.js selects the whole workspace.
Changing an imported JavaScript rule module selects packages that transitively
import it. Files with no owner produce a warning but do not fail the command.
Use --changed-dependents direct to include targets that directly depend on
the changed targets, or --changed-dependents transitive for the full reverse
dependency closure.
Scope changed targets
Path selectors and --changed-since can be combined. The selector narrows the
changed target set, which is useful when CI runs separate jobs for different
parts of a workspace.
imp test //apps/... --changed-since origin/main
imp targets //libraries/... --changed-since origin/main
A nonexistent or invalid selector is still an error. If a valid selector has
no changed targets in scope, the command succeeds without running work.
A changed run always uses the goal's own workflow, so the legacy
//pkg:target#product override is not supported with --changed-since.
Goals declared with selection: "none" are independent of target selection:
their callbacks still run with an empty selection when --changed-since is
present.