Workspaces
A workspace is a root repository with other repositories mounted in it as submodules, declared beside the repos: list in repos.yaml.
repos:
- path: /home/you/code/product
id: product
setup_command: "make setup"
test_command: "make test"
- path: /home/you/code/api
id: api
setup_command: "make setup"
test_command: "make test"
workspaces:
product:
root: product
root_pointer_default: ignore # or bump
members:
api: { repository: api, path: services/api }
root and repository each name a repos: entry by its id.
| Key | Type | Default | Meaning |
|---|---|---|---|
workspaces.<name> | mapping | The workspace. Its name is the key. | |
workspaces.<name>.root | string, a repo id | (required) | The root repository's repos: entry. |
workspaces.<name>.root_pointer_default | ignore or bump | ignore | What happens to the root's submodule pointers after members merge. See Publication. |
workspaces.<name>.members | mapping | {} | The members, each keyed by its own name. |
workspaces.<name>.members.<name>.repository | string, a repo id | (required) | The member's repos: entry. |
workspaces.<name>.members.<name>.path | string | (required) | Where the member mounts in the root. See Member paths. |
A repos.yaml from before workspaces still loads, but an item with submodules needs a declared workspace. Declare it in workspaces:, or reconnect the root, which loses its settings.
Connecting a workspace
Connecting a repo that has submodules declares its workspace for you, each submodule a member.
A submodule you already connected on its own (a clone elsewhere with the same origin) is that member, with its settings. Kraft adds an entry for the submodule's own checkout only when it finds none.
Filing a work item against the root
When you file a work item against the root, you choose:
- which members it changes
- its root-pointer policy (the workspace's
root_pointer_defaultunless you pick one)
Both are frozen into the item. The item's worktree holds exactly those members, each on the item's branch. A task with scope: each_repository runs once per selected repository.
Member checkouts
- Kraft checks each member out as a worktree of its connected repository, the same way it checks out the root. The item's branch exists in that repository too.
- Abandoning or archiving the item deletes the member's worktree and branch there, as long as the member is still connected. If you disconnect or move it first, remove them by hand.
- Archiving keeps a member's branch that has commits nowhere else.
- A member whose repository is not connected any more is checked out with
git submodule updateinstead.
Member paths
Every member mounts directly in the root. repos.yaml fails to load, and filing an item against that workspace is refused, when:
- one member's
pathis inside another member's (libs/a/vendor/xinsidelibs/a) - two members share a
path
The error names both members. A submodule nested in a member is part of that member's repository, so leave it out of members:.
Policy layers
Each selected repository applies its own policy layer to the tasks that run in it. A task running in the assembled worktree, which holds every selected repository, gets the tightest combination of those layers: allowlists intersect, deny lists add up, and numbers take their minimum.
Sandboxing
A workspace with members can be sandboxed like a single repository: a sandbox on the root or on any member, or one that comes from a chain, node or task, wraps the item's whole checkout. Each member's refs go through a ref store of its own, and a member that is not the checkout Kraft made, or not connected, stops the item.
Git in a sandbox tells how members are mounted, and what Kraft's git does there, a nested repository Kraft did not create included.
Publication
Publication goes members first: a member's merge request merges before the root moves.
- A member that fails to merge stops publication and leaves the root untouched.
- A root with source changes of its own gets its own merge request. It stays a draft until every member has merged and the root names their merged revisions.
- A root whose only change is the members' pointers follows the item's root-pointer policy:
| Policy | What happens to the root |
|---|---|
ignore | It is left alone. |
bump | Kraft pushes the new pointers to its default branch. If that push is refused, it opens a merge request for them instead. |
Related
- repos.yaml: the
idfield and the rest of arepos:entry. - Sandboxed workers: what reaches a sandboxed container.
- Git in a sandbox: refs, members and the clean check under a sandbox.
- Repo verbs:
kraft repo connect, which declares a workspace for a repo with submodules.