@sous-io/sous 0.2.15 → 0.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/markdown/commands.md +63 -16
- package/docs/markdown/repositories-authoring.md +52 -11
- package/docs/markdown/repositories-consuming.md +32 -1
- package/docs/markdown/repositories-file-formats.md +20 -0
- package/docs/markdown/repositories-providers.md +20 -10
- package/package.json +1 -1
- package/recipes/core/sous-skills/sous.recipe.yaml +8 -1
- package/src/commands/namespace/list.ts +42 -21
- package/src/commands/namespace/show.ts +32 -12
- package/src/commands/recipe/list.ts +40 -23
- package/src/commands/recipe/show.ts +28 -6
- package/src/commands/repo/list.ts +67 -10
- package/src/commands/repo/release.ts +41 -0
- package/src/commands/repo/search.ts +68 -15
- package/src/commands/repo/submit.ts +245 -35
- package/src/commands/subscription/list.ts +98 -19
- package/src/lib/build-preparation.ts +44 -1
- package/src/lib/repos/catalog-display.ts +101 -2
- package/src/lib/repos/catalog-inputs.ts +145 -17
- package/src/lib/repos/catalog.ts +92 -5
- package/src/lib/repos/formats/common.ts +20 -0
- package/src/lib/repos/formats/recipe-manifest.ts +7 -0
- package/src/lib/repos/formats/repo-manifest.ts +8 -0
- package/src/lib/repos/freshness.ts +56 -0
- package/src/lib/repos/providers/base.ts +33 -1
- package/src/lib/repos/providers/github.ts +276 -3
- package/src/lib/repos/providers/gitlab.ts +1 -0
- package/src/lib/repos/providers/http.ts +7 -2
- package/src/lib/repos/providers/index-cache.ts +56 -17
- package/src/lib/repos/providers/provider.ts +121 -3
- package/src/lib/repos/release/changelog.ts +448 -0
- package/src/lib/repos/release/git-state.ts +101 -15
- package/src/lib/repos/release/index.ts +2 -0
- package/src/lib/repos/release/submissions.ts +214 -0
- package/src/lib/repos/release/submit-checkout.ts +271 -0
- package/src/lib/repos/release/submit-questions.ts +153 -0
- package/src/lib/repos/release/submit-service.ts +581 -174
- package/src/lib/repos/subscription-service.ts +138 -9
- package/src/utils/flags.ts +24 -0
|
@@ -17,7 +17,8 @@ Every command that works on a project takes these four. `SOUS_CONFIG`, `SOUS_DIR
|
|
|
17
17
|
a flag beats its variable, and both beat walk-up discovery. See [Discovery and overrides](config-discovery.md).
|
|
18
18
|
|
|
19
19
|
?> `repo init`, `repo release` and `repo submit` take none of these. They run inside a recipe repository, which
|
|
20
|
-
has no `.sous/` directory to discover. All three still take `--non-interactive`.
|
|
20
|
+
has no `.sous/` directory to discover. All three still take `--non-interactive`. `repo submit` may also be run
|
|
21
|
+
from a project, which it finds by walking up from the working directory.
|
|
21
22
|
|
|
22
23
|
## Flags that answer questions
|
|
23
24
|
|
|
@@ -41,6 +42,22 @@ Help has four spellings. `sous --help` prints the root screen; `sous repo add --
|
|
|
41
42
|
`sous --version` prints the version alone, as `v1.2.3`; `sous --version --verbose` adds the package name, where
|
|
42
43
|
it is installed, the platform and the Node build under it.
|
|
43
44
|
|
|
45
|
+
## Flags that browse
|
|
46
|
+
|
|
47
|
+
Every command that shows published versions takes the same two flags: `sous recipe list`, `sous recipe show`,
|
|
48
|
+
`sous namespace list`, `sous namespace show`, `sous repo list`, `sous repo search` (and `sous search`) and
|
|
49
|
+
`sous subscription list`. The flags combine.
|
|
50
|
+
|
|
51
|
+
| Flag | What it does |
|
|
52
|
+
|------|--------------|
|
|
53
|
+
| `--latest` | Read each repository's index from upstream instead of the cache. `--remote` is the same flag. What it fetches is never written to the cache; a repository that cannot be reached is shown from the cache and named as not checked |
|
|
54
|
+
| `--installed` | Show only what this project has installed, at the version its lockfile pins. A recipe whose repository is linked is marked `linked`, because builds read it from the checkout rather than the pinned version |
|
|
55
|
+
|
|
56
|
+
Without either flag a browsing command reads only the cached indexes, so it works offline and fast.
|
|
57
|
+
`sous recipe list --installed --latest` is the out-of-date view: each installed recipe with upstream's newest
|
|
58
|
+
version beside the installed one. With `--installed`, `recipe show` and `namespace show` look the reference up
|
|
59
|
+
among installed recipes only, and a reference to something published but not installed is an error saying so.
|
|
60
|
+
|
|
44
61
|
Every topic answers to both spellings of its name: `repo` and `repos`, `subscription` and `subscriptions`,
|
|
45
62
|
`namespace` and `namespaces`, `recipe` and `recipes`, `lock` and `locks`, `vars` and `var`, `config` and
|
|
46
63
|
`configs`. Three commands also answer to one word: `sous search`, `sous subscribe` and `sous unsubscribe`.
|
|
@@ -79,6 +96,12 @@ and the command you want almost always. Takes `--dry-run`.
|
|
|
79
96
|
- `--strict`: fail on any compilation error rather than reporting it and continuing.
|
|
80
97
|
- `-w, --watch`: rebuild on every change to a source file, a config layer or a linked checkout.
|
|
81
98
|
|
|
99
|
+
Before it compiles, a build lists each recipe this project uses that has a newer version within the range
|
|
100
|
+
declared for it, beside the version pinned. It moves no pin; only always-pull moves one. The build reads upstream
|
|
101
|
+
for this at most once per freshness window (`store.freshnessSeconds`, five minutes by default), gives a
|
|
102
|
+
repository three seconds to answer, and otherwise answers from the cached index without a word about the
|
|
103
|
+
failed check.
|
|
104
|
+
|
|
82
105
|
Example: `sous build --rebuild`
|
|
83
106
|
|
|
84
107
|
### `sous compile`
|
|
@@ -103,8 +126,10 @@ Example: `sous launch claude --continuous`
|
|
|
103
126
|
|
|
104
127
|
### `sous search TEXT`
|
|
105
128
|
Searches the recipes every trusted repository publishes, by name or description; reads the cached indexes only,
|
|
106
|
-
so it works offline. `--limit <n>` sets how many matches to show, defaulting to 25.
|
|
107
|
-
`
|
|
129
|
+
so it works offline. `--limit <n>` sets how many matches to show, defaulting to 25. Takes the
|
|
130
|
+
[browsing flags](#flags-that-browse): `--latest` searches the indexes upstream serves, and `--installed` searches
|
|
131
|
+
only installed recipes and adds an Installed column. Also spelled `sous repo search`.
|
|
132
|
+
Example: `sous search task --limit 50`
|
|
108
133
|
|
|
109
134
|
### `sous help [COMMAND]`
|
|
110
135
|
Prints the help for sous, or for one command or topic. Works from any directory, including one with no config
|
|
@@ -155,7 +180,9 @@ held, the files the next build prunes, and the linked checkout if one points at
|
|
|
155
180
|
### `sous repo list`
|
|
156
181
|
Lists the repositories this project trusts, with the provider, where the entry came from, whether it is linked,
|
|
157
182
|
how many recipes it publishes (`not fetched` until its index has been downloaded) and its URL. `--verbose` adds
|
|
158
|
-
the namespaces each one publishes, on a line under its row.
|
|
183
|
+
the namespaces each one publishes, on a line under its row. Takes the [browsing flags](#flags-that-browse):
|
|
184
|
+
`--installed` keeps only the repositories something is installed from and names each installed recipe and
|
|
185
|
+
version on a line under its row.
|
|
159
186
|
|
|
160
187
|
```term
|
|
161
188
|
$ sous repo list
|
|
@@ -165,7 +192,8 @@ $ sous repo list
|
|
|
165
192
|
```
|
|
166
193
|
|
|
167
194
|
### `sous repo search TEXT`
|
|
168
|
-
Same command as `sous search`, under its own topic; takes `--limit <n
|
|
195
|
+
Same command as `sous search`, under its own topic; takes `--limit <n>` and the
|
|
196
|
+
[browsing flags](#flags-that-browse). Example: `sous repo search browser --installed`
|
|
169
197
|
|
|
170
198
|
### `sous repo gc`
|
|
171
199
|
Collects the machine-wide recipe store down to its size cap. `--max-bytes <n>` collects to that cap instead of
|
|
@@ -227,17 +255,32 @@ and `git config user.email`), because it commits and cuts annotated tags. Takes
|
|
|
227
255
|
- `--no-bump`: raise nothing; a changed recipe that was never raised is then an error.
|
|
228
256
|
- `--include-unchanged`: release every recipe in scope, changed or not.
|
|
229
257
|
- `--tag`, `--push`: tag even on a non-default branch, and push the commit and this run's tags.
|
|
230
|
-
- `--check`: only validate. It fails on a problem the release would refuse, and
|
|
231
|
-
|
|
258
|
+
- `--check`: only validate. It fails on a problem the release would refuse, and on a change to a recipe that
|
|
259
|
+
takes no proposals (see [`submissions`](repositories-file-formats.md#the-submissions-block)), and reports,
|
|
260
|
+
without failing, how merging would rewrite the committed index.
|
|
232
261
|
- `--ci`: the merge preset. Never bump, never ask, and fail on anything unbumped. It still needs `--yes` to
|
|
233
262
|
accept the plan it prints, so a merge job runs `sous repo release --ci --yes --push`.
|
|
234
263
|
|
|
235
264
|
Example: `sous repo release --recipe workflow/task-files --bump minor --push`
|
|
236
265
|
|
|
237
|
-
### `sous repo submit`
|
|
238
|
-
Proposes
|
|
239
|
-
|
|
240
|
-
|
|
266
|
+
### `sous repo submit [REPO]`
|
|
267
|
+
Proposes a recipe repository's changes to its maintainers, and follows the proposal through: it opens one,
|
|
268
|
+
updates it when there is more to send, reports where it stands, and starts the next one once it was merged. Run
|
|
269
|
+
inside a recipe repository it works there; run inside a project, `REPO` names a linked repository and the
|
|
270
|
+
submission runs in its checkout (with no `REPO`, the only linked repository is used, and several are a
|
|
271
|
+
question). Takes `-y, --yes` and `--dry-run`.
|
|
272
|
+
|
|
273
|
+
- `--title <text>`, `--body <text>`: the proposal's title and description. Both are required for a new
|
|
274
|
+
proposal, and asked for at a terminal when missing; on an open proposal they are optional and replace its own.
|
|
275
|
+
The body is followed by a changelog sous generates.
|
|
276
|
+
- `--branch <name>`: work with this branch instead of the one checked out. A branch that does not exist is
|
|
277
|
+
created from the current commit.
|
|
278
|
+
- `--status`: only report where the branch's proposal stands; nothing is checked, written or sent.
|
|
279
|
+
- `--commit`: commit uncommitted changes for you, after listing them and asking once, with the title, the
|
|
280
|
+
description and the changelog as the message.
|
|
281
|
+
- `--draft`: open a new proposal as a draft.
|
|
282
|
+
|
|
283
|
+
Example: `sous repo submit --title "Add a linting recipe" --body "Adds lint rules for shell scripts." --draft`
|
|
241
284
|
|
|
242
285
|
## subscription
|
|
243
286
|
|
|
@@ -265,13 +308,16 @@ Removes a subscription and everything only it brought in, then rebuilds so those
|
|
|
265
308
|
|
|
266
309
|
### `sous subscription list`
|
|
267
310
|
Lists the subscriptions this project declares, switched-off ones included, with the range each resolves within,
|
|
268
|
-
the versions the lockfile pins,
|
|
269
|
-
|
|
311
|
+
the versions the lockfile pins, the latest version each of those recipes has published, where it came from and
|
|
312
|
+
whether it is on. Reads the config, the lockfile and the cached indexes only. Takes the
|
|
313
|
+
[browsing flags](#flags-that-browse): `--latest` reads the latest versions from upstream, and `--installed` keeps
|
|
314
|
+
only the subscriptions that have pinned something. Example: `sous subscription list --latest`
|
|
270
315
|
|
|
271
316
|
## namespace
|
|
272
317
|
|
|
273
318
|
`namespace` reads the cached indexes and the lockfile, so it works offline. A trusted repository whose index has
|
|
274
|
-
never been fetched is named at the end of a listing, not left out.
|
|
319
|
+
never been fetched is named at the end of a listing, not left out. Both commands take the
|
|
320
|
+
[browsing flags](#flags-that-browse); with `--installed` the recipe count is the number installed.
|
|
275
321
|
|
|
276
322
|
### `sous namespace list`
|
|
277
323
|
Lists every namespace the trusted repositories publish, how many recipes each holds, and how much of it this
|
|
@@ -284,11 +330,12 @@ Example: `sous namespace show sous-recipes:core`
|
|
|
284
330
|
|
|
285
331
|
## recipe
|
|
286
332
|
|
|
287
|
-
Browses the recipes the trusted repositories publish; like `namespace`, it works offline
|
|
333
|
+
Browses the recipes the trusted repositories publish; like `namespace`, it works offline, and both commands take
|
|
334
|
+
the [browsing flags](#flags-that-browse).
|
|
288
335
|
|
|
289
336
|
### `sous recipe list`
|
|
290
337
|
Lists the recipes the trusted repositories publish, across every namespace, with the same per-recipe columns
|
|
291
|
-
`namespace show` prints. Example: `sous recipe list`
|
|
338
|
+
`namespace show` prints. Example: `sous recipe list --installed --latest`
|
|
292
339
|
|
|
293
340
|
### `sous recipe show REF`
|
|
294
341
|
Describes one recipe completely: its repository and location, every published version, its dependencies as
|
|
@@ -4,8 +4,9 @@ The guide to publishing recipes of your own: creating a repository, writing a re
|
|
|
4
4
|
needs, cutting a release, editing a published repository in place, and proposing a change to somebody else's.
|
|
5
5
|
[Repository file formats](repositories-file-formats.md) holds the schemas; this page is the workflow.
|
|
6
6
|
|
|
7
|
-
?> A recipe repository is not a sous project. It has no `.sous/` directory, and `sous repo init
|
|
8
|
-
release`
|
|
7
|
+
?> A recipe repository is not a sous project. It has no `.sous/` directory, and `sous repo init` and `sous repo
|
|
8
|
+
release` do not look for one. Run them from inside the repository itself. `sous repo submit` runs there too, and
|
|
9
|
+
may also be run from a project that links the repository.
|
|
9
10
|
|
|
10
11
|
## Create a repository
|
|
11
12
|
|
|
@@ -196,8 +197,9 @@ third case is what a merge looks like to continuous integration: the bump is don
|
|
|
196
197
|
`--namespace <ns>` and `--recipe <ns/name>` narrow the run and both repeat; `--bump <level>` is `patch` (the
|
|
197
198
|
default), `minor`, `major` or `prerelease`; `--no-bump` raises nothing; `--include-unchanged` releases every
|
|
198
199
|
recipe in scope, changed or not; `--check` only reads, validating, failing on any problem the release would
|
|
199
|
-
refuse
|
|
200
|
-
|
|
200
|
+
refuse and on a change to a recipe whose [`submissions`](repositories-file-formats.md#the-submissions-block)
|
|
201
|
+
block says it takes no proposals, and reporting how merging would rewrite the committed index without failing
|
|
202
|
+
on it, since that index is the release's output; and `--ci` is the merge preset: never bump, accept the plan, never ask, fail on anything unbumped. Every flag
|
|
201
203
|
this command takes, `--tag`, `--push` and `--non-interactive` among them, is in the
|
|
202
204
|
[command reference](commands.md#sous-repo-release).
|
|
203
205
|
|
|
@@ -235,7 +237,8 @@ missing from the index is rebuilt from it whenever the index is regenerated, whi
|
|
|
235
237
|
publishes something. A bump edits the manifest in place, so comments, field order and layout survive; a folded
|
|
236
238
|
block of YAML prose may be re-wrapped and the space before a trailing comment collapsed to one.
|
|
237
239
|
|
|
238
|
-
!> A release commits the version bumps and the index, and nothing else
|
|
240
|
+
!> A release commits the version bumps and the index, and nothing else; the only other commit sous ever makes
|
|
241
|
+
for you is `sous repo submit --commit`. It refuses to run while anything else is
|
|
239
242
|
uncommitted, because a tag names one commit and the index records what each recipe folder holds right now. It also
|
|
240
243
|
refuses when git does not know who is committing: set `git config user.name` and `git config user.email` first, or
|
|
241
244
|
give that identity to the account a continuous integration job runs as (the scaffolded workflow already does).
|
|
@@ -344,22 +347,60 @@ changing its branch says it affects all of them.
|
|
|
344
347
|
|
|
345
348
|
## Contribute to someone else's repository
|
|
346
349
|
|
|
347
|
-
`sous repo submit` proposes
|
|
348
|
-
writes to a repository directly.
|
|
349
|
-
|
|
350
|
+
`sous repo submit` proposes a change to a repository's maintainers and follows it through; it never publishes
|
|
351
|
+
and never writes to a repository directly. Run it inside the recipe repository you changed, or from a project
|
|
352
|
+
that links it: `sous repo submit sous-recipes` runs in the linked checkout, and with no argument the project's
|
|
353
|
+
only linked repository is used (several are a question). A repository you have since unlinked is still
|
|
354
|
+
submitted from the checkout sous cloned for it, with a note saying so; with no checkout at all there is no
|
|
355
|
+
working copy to propose from, and `submit` says so.
|
|
356
|
+
|
|
357
|
+
It prints each step as it runs them:
|
|
350
358
|
|
|
351
359
|
1. **Preflight.** An `origin` remote exists, sous recognizes its provider, that provider's command line tool
|
|
352
|
-
(`gh` or `glab`) is installed and signed in, and everything is committed.
|
|
360
|
+
(`gh` or `glab`) is installed and signed in, and everything is committed. `--commit` lifts that last rule:
|
|
361
|
+
sous lists what is uncommitted, asks once (`--yes` answers), checks git knows who is committing before
|
|
362
|
+
writing anything, and commits it all with the proposal's title, description and changelog as the message.
|
|
353
363
|
2. **Validation.** The repository validates, and your change leaves `sous.index.json` as it found it, so a
|
|
354
364
|
proposal never fails the maintainer's own checks and wastes their review. The index is written by the
|
|
355
365
|
repository's own release after a merge; whether it agrees with the release tags is checked there, by
|
|
356
366
|
`sous repo release --check` on a full clone, not by `submit`. That is what lets `submit` run from the shallow
|
|
357
367
|
checkout `sous repo link` makes, which holds almost none of the tags. The comparison is made against the
|
|
358
368
|
copy of the default branch your checkout holds (`origin/main`, for example); when it holds none, `submit`
|
|
359
|
-
says the check was skipped.
|
|
369
|
+
says the check was skipped. A change that touches a recipe whose
|
|
370
|
+
[`submissions`](repositories-file-formats.md#the-submissions-block) block says it takes no proposals is
|
|
371
|
+
warned about, with where to send it instead, and proposed only if you carry on.
|
|
360
372
|
3. **Delegation.** Sous asks the provider whether you can push to the repository itself, forks it onto your
|
|
361
373
|
account when you cannot, pushes the branch, and asks the provider to open the proposal. A change sitting on
|
|
362
|
-
the default branch is moved to `sous/submit-<YYYYMMDD>-<HHMM
|
|
374
|
+
the default branch is moved to `sous/submit-<YYYYMMDD>-<HHMM>`, or to the branch `--branch` names.
|
|
375
|
+
|
|
376
|
+
**A title and a description are yours to write.** A new proposal needs both: pass `--title` and `--body`, or
|
|
377
|
+
answer the two questions at a terminal (Tab opens your editor for a longer description). Sous never borrows a
|
|
378
|
+
commit message. The body is your description followed by a changelog sous generates by comparing the manifests
|
|
379
|
+
your change carries with the default branch:
|
|
380
|
+
|
|
381
|
+
- recipes added, and recipes retired (a renamed recipe shows as one of each);
|
|
382
|
+
- version changes;
|
|
383
|
+
- recipes whose files changed without a version raise, which merging will release as the next patch;
|
|
384
|
+
- namespaces added or removed;
|
|
385
|
+
- variables added, removed or changed, with a warning that removing a variable or tightening its validation is
|
|
386
|
+
usually a major change.
|
|
387
|
+
|
|
388
|
+
The changelog explains; it never refuses. Only what the repository's own checks would reject stops a submission.
|
|
389
|
+
|
|
390
|
+
**One command for the proposal's whole life.** Every run looks up the proposal for the current branch (or the
|
|
391
|
+
one `--branch` names), by the fork's owner as well as the branch when you work through a fork, and then:
|
|
392
|
+
|
|
393
|
+
| The branch's proposal | What `submit` does |
|
|
394
|
+
|-----------------------|--------------------|
|
|
395
|
+
| none | Opens one |
|
|
396
|
+
| open, with new commits | Pushes them, which updates it; a given `--title` or `--body` replaces its own |
|
|
397
|
+
| open, with nothing new | Reports where it stands: review, checks, whether it can merge |
|
|
398
|
+
| merged | Says so, then continues on a new branch: you name one, sous generates one, or you cancel. `--yes` generates one |
|
|
399
|
+
| closed without merging | Says so, and opens a fresh one for the branch |
|
|
400
|
+
|
|
401
|
+
When the branch on the remote holds commits yours lacks (a maintainer pushed to it), git refuses the push and
|
|
402
|
+
`submit` passes git's own explanation through and stops. It never forces a push. `--status` only reports, and
|
|
403
|
+
`--dry-run` works everything out and writes and sends nothing.
|
|
363
404
|
|
|
364
405
|
Each step is the provider's own business, and what each one can do depends on the host; see
|
|
365
406
|
[Providers](repositories-providers.md#proposing-a-change). Sous sequences the steps and reports what came back. A
|
|
@@ -52,6 +52,19 @@ sous namespace show workflow # one namespace and the recipes in it
|
|
|
52
52
|
sous recipe list # every recipe, latest version, pinned version, subscribed
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
The cache can be behind what a repository has published since. Every one of these commands, plus
|
|
56
|
+
`sous recipe show`, `sous repo list` and `sous subscription list`, takes two flags that combine:
|
|
57
|
+
|
|
58
|
+
- `--latest` (also `--remote`) reads each index from upstream instead. Nothing it fetches is
|
|
59
|
+
written to the cache; only a command that resolves versions changes what the cache holds. A
|
|
60
|
+
repository that cannot be reached is shown from the cache and named as not checked.
|
|
61
|
+
- `--installed` narrows the listing to what this project has installed, at the version the
|
|
62
|
+
lockfile pins. A recipe from a linked repository is marked `linked`, because builds read it from
|
|
63
|
+
the checkout instead of that version.
|
|
64
|
+
|
|
65
|
+
`sous recipe list --installed --latest` is the out-of-date view: every installed recipe, with
|
|
66
|
+
upstream's newest version beside the installed one.
|
|
67
|
+
|
|
55
68
|
Read `sous recipe show` before subscribing: every published version, what it depends on (as
|
|
56
69
|
declared, beside the version the index resolved it to), and its questions and files once it has
|
|
57
70
|
them here.
|
|
@@ -201,7 +214,8 @@ $ sous subscription list
|
|
|
201
214
|
|
|
202
215
|
A namespace subscription names every recipe it holds, each with the version the lockfile pins. A
|
|
203
216
|
subscription that has never been built has nothing pinned yet, and its cell reads `pinned on first
|
|
204
|
-
build` instead.
|
|
217
|
+
build` instead. The `Latest version` column beside it is read from the cache, or from upstream with
|
|
218
|
+
`--latest`.
|
|
205
219
|
|
|
206
220
|
`sous repo list` shows each trusted repository with its provider, origin, whether it is linked, its
|
|
207
221
|
recipe count and its URL; `--verbose` adds a `Namespaces:` line under each row. `sous lock show`
|
|
@@ -278,6 +292,23 @@ happens after that check, not how often it happens: a repository or subscription
|
|
|
278
292
|
`alwaysPull` takes a newer in-range version rather than the locked one; set it with
|
|
279
293
|
`--always-pull`, or on either entry in the config.
|
|
280
294
|
|
|
295
|
+
Every other repository the lockfile pins from is checked on the same window, only to tell you what
|
|
296
|
+
is newer. A build lists each recipe with a newer version inside the range declared for it, beside
|
|
297
|
+
the version it pins, and moves nothing:
|
|
298
|
+
|
|
299
|
+
```term
|
|
300
|
+
$ sous build
|
|
301
|
+
▶ Newer versions published:
|
|
302
|
+
|
|
303
|
+
workflow/qa-variables: 0.2.0 this project pins 0.1.0
|
|
304
|
+
|
|
305
|
+
This version is within the range declared for the recipe. No pin was changed, so this build
|
|
306
|
+
uses the pinned version.
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
That check waits at most three seconds for a repository, and a check that fails or runs out of
|
|
310
|
+
time is not mentioned: the cached index answers instead, and the build carries on.
|
|
311
|
+
|
|
281
312
|
The store is machine-wide and disposable, because everything in it is re-fetchable from a
|
|
282
313
|
lockfile's pins. `sous repo gc` collects it back to its size cap, evicting least recently used
|
|
283
314
|
entries first, and protects everything this project's lockfile pins whatever that does to the
|
|
@@ -54,6 +54,7 @@ recipes: # every recipe folder, relative to the repos
|
|
|
54
54
|
| `description`, `contribute` | no | A summary for anyone reading the repository, and where to send a contribution when a provider cannot support `sous repo submit` |
|
|
55
55
|
| `namespaces` | yes | Keyed by namespace name; each entry takes an optional `description` |
|
|
56
56
|
| `recipes` | yes | Relative paths, each holding a recipe manifest; a path listed twice is an error |
|
|
57
|
+
| `submissions` | no | Whether the repository's recipes take proposed changes; see [The submissions block](#the-submissions-block) |
|
|
57
58
|
|
|
58
59
|
## `sous.recipe.yaml`: the recipe manifest
|
|
59
60
|
|
|
@@ -77,11 +78,30 @@ contents: # what a subscriber actually receives
|
|
|
77
78
|
| `description` | no | Copied into the index at release time; shown by `sous recipe list` and `sous repo search` |
|
|
78
79
|
| `depends`, `subscribes` | no | Build dependencies and co-subscriptions; within either list, no entry may repeat |
|
|
79
80
|
| `contents`, `variables` | no | Contents default to an empty list, which is what a curated bundle publishes; a duplicated variable name, or two definitions claiming one `env`, is an error |
|
|
81
|
+
| `submissions` | no | Whether this recipe takes proposed changes, winning over the repository's block; see [The submissions block](#the-submissions-block) |
|
|
80
82
|
|
|
81
83
|
`contents[].kind` is `skills`, `memories`, `prompts` or `config`. The first three are written to the
|
|
82
84
|
destinations named by [`recipeOutputs`](#recipeoutputs-where-the-files-land); `config` entries become config
|
|
83
85
|
layers instead. `include` needs at least one glob, and both lists are recipe-relative.
|
|
84
86
|
|
|
87
|
+
### The submissions block
|
|
88
|
+
|
|
89
|
+
Both manifests accept a `submissions` block. On `sous.repo.yaml` it covers every recipe in the repository; on
|
|
90
|
+
`sous.recipe.yaml` it covers that recipe, and wins over the repository's.
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
submissions:
|
|
94
|
+
allowed: false # defaults to true
|
|
95
|
+
instead: Propose changes in sous-io/sous, under recipes/core/sous-skills/.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
It exists for a recipe whose files are copied in from somewhere else: an edit merged into the copy is
|
|
99
|
+
overwritten by the next copy, and a version it tagged can collide with the one the real source publishes.
|
|
100
|
+
`sous repo submit` warns before proposing a change that touches such a recipe, prints the `instead` text, and
|
|
101
|
+
proposes it if the contributor carries on. `sous repo release --check` fails a pull request that changes one,
|
|
102
|
+
because a pull request can be opened without `submit`, and the check is the one gate every change passes. A
|
|
103
|
+
release itself is never restricted, so whatever publishes the recipe still releases it.
|
|
104
|
+
|
|
85
105
|
### Dependencies named by location
|
|
86
106
|
|
|
87
107
|
`depends` and `subscribes` share one grammar in two spellings: `workflow/qa-helper` is a sibling in this
|
|
@@ -21,8 +21,12 @@ Nothing there clones a whole repository. A provider that can also carry a contri
|
|
|
21
21
|
the **write path**: report whether its command line tool is installed and signed in, say whether
|
|
22
22
|
you may push to the repository itself, fork it onto your account, and open the proposal.
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
A provider may also answer the **proposals** path, which is what lets a submission follow a proposal
|
|
25
|
+
after it is opened: find the proposal a branch was pushed for, report where it stands, and replace its
|
|
26
|
+
title or body.
|
|
27
|
+
|
|
28
|
+
Each provider declares which of the three features, `fetch`, `submit` and `proposals`, it genuinely
|
|
29
|
+
answers, and sous consults that declaration rather than a provider's name. Asking for something outside a
|
|
26
30
|
provider's features is refused with a sentence naming it and what it cannot do, never a crash.
|
|
27
31
|
|
|
28
32
|
## How a URL is matched
|
|
@@ -184,11 +188,15 @@ finds the index but cannot clone has only the second half missing.
|
|
|
184
188
|
your repository, then hands the host-specific mechanics to the provider that owns its `origin`
|
|
185
189
|
remote. Providers differ, and sous says so rather than pretending otherwise:
|
|
186
190
|
|
|
187
|
-
| Provider | Tool | Push permission | Forking | Proposal |
|
|
188
|
-
|
|
189
|
-
| `github` | `gh` | read from GitHub, so a contributor without it is forked automatically | `gh repo fork`, with a `fork` remote added for you | pull request |
|
|
190
|
-
| `gitlab` | `glab` | sous cannot tell, so it pushes to `origin` and says so | not done for you | merge request |
|
|
191
|
-
| `local` | none | not applicable | not applicable | not applicable |
|
|
191
|
+
| Provider | Tool | Push permission | Forking | Proposal | Following it up |
|
|
192
|
+
|---|---|---|---|---|---|
|
|
193
|
+
| `github` | `gh` | read from GitHub, so a contributor without it is forked automatically | `gh repo fork`, with a `fork` remote added for you | pull request | `gh pr list`, `gh pr view` and `gh pr edit`, matching a fork's pull request by its owner |
|
|
194
|
+
| `gitlab` | `glab` | sous cannot tell, so it pushes to `origin` and says so | not done for you | merge request | not done: every run opens a merge request, and `--status` is refused |
|
|
195
|
+
| `local` | none | not applicable | not applicable | not applicable | not applicable |
|
|
196
|
+
|
|
197
|
+
**GitLab cannot follow a proposal up yet.** It does not declare `proposals`, so a submission cannot
|
|
198
|
+
look for a merge request that is already open; it says so, pushes, and opens one. When the branch
|
|
199
|
+
already has one, the push updates it and GitLab may refuse the second.
|
|
192
200
|
|
|
193
201
|
**GitLab reports "cannot tell" rather than guessing.** Sous has no cheap, reliable way to ask
|
|
194
202
|
whether you may push, and a wrong guess would send you down a fork path this provider cannot
|
|
@@ -297,14 +305,16 @@ subclass overrides it. Each member is documented where it lives, in
|
|
|
297
305
|
The subclass supplies the rest:
|
|
298
306
|
|
|
299
307
|
- `id`, the identifier a repository entry and a locator scheme use;
|
|
300
|
-
- `features`, the ones it genuinely answers (`fetch
|
|
301
|
-
are
|
|
308
|
+
- `features`, the ones it genuinely answers (`fetch`; `submit` only if all four write calls are
|
|
309
|
+
real; `proposals` only if `findProposal`, `proposalStatus` and `updateProposal` are);
|
|
302
310
|
- `matches(url)` and `canonicalize(url)`, the URL half;
|
|
303
311
|
- `fetchIndex(repo, options)` and `fetchRecipeTree(repo, recipePath, tag, destDir, options)`, the
|
|
304
312
|
read half;
|
|
305
313
|
- `cli` and `proposalNoun` when it submits, so messages can name the tool and call a proposal
|
|
306
314
|
what the host calls it;
|
|
307
|
-
- overrides of the four write-path calls when it submits
|
|
315
|
+
- overrides of the four write-path calls when it submits, and of the three proposals calls when
|
|
316
|
+
it can follow a proposal up. Each answers with plain data (a proposal's id, address, state,
|
|
317
|
+
title, review and check counts), never with a host's own vocabulary.
|
|
308
318
|
|
|
309
319
|
Every call takes an options object carrying the testing seams (`cwd`, `env`, `fetchImpl`, `run`),
|
|
310
320
|
which is why no provider reaches for `spawn` or the global `fetch` directly and no test in this
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ formatVersion: 1
|
|
|
11
11
|
|
|
12
12
|
namespace: core
|
|
13
13
|
name: sous-skills
|
|
14
|
-
version: 0.2.
|
|
14
|
+
version: 0.2.17
|
|
15
15
|
|
|
16
16
|
description: >-
|
|
17
17
|
The skills that teach an agent what sous is and how it works: which files sous
|
|
@@ -19,6 +19,13 @@ description: >-
|
|
|
19
19
|
debugged, the .tpl. template convention and LiquidJS syntax, what an agent
|
|
20
20
|
skill is, and how to create one.
|
|
21
21
|
|
|
22
|
+
# The copy in sous-io/sous-recipes is overwritten by every sous release, so a
|
|
23
|
+
# change proposed there would be lost, and a version it tagged would collide
|
|
24
|
+
# with the one the release publishes.
|
|
25
|
+
submissions:
|
|
26
|
+
allowed: false
|
|
27
|
+
instead: Propose changes in sous-io/sous, under recipes/core/sous-skills/.
|
|
28
|
+
|
|
22
29
|
contents:
|
|
23
30
|
- kind: skills
|
|
24
31
|
include:
|
|
@@ -3,17 +3,25 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Shows every namespace published by the repositories this project trusts, how
|
|
5
5
|
* many recipes each one holds, and how much of it the project subscribes to. It
|
|
6
|
-
* reads only the indexes sous already has on disk, so it works
|
|
7
|
-
* repository whose index has never been fetched is named at the end
|
|
8
|
-
* being silently left out.
|
|
6
|
+
* reads only the indexes sous already has on disk by default, so it works
|
|
7
|
+
* offline; a repository whose index has never been fetched is named at the end
|
|
8
|
+
* rather than being silently left out. `--latest` reads the indexes from
|
|
9
|
+
* upstream instead, without saving them, and `--installed` narrows the listing
|
|
10
|
+
* to the namespaces the lockfile pins a recipe from.
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
import { BaseCommand } from "../../base-command.js";
|
|
12
14
|
import { subscriptionServiceFor } from "../../lib/repos/subscription-service.js";
|
|
13
|
-
import {
|
|
14
|
-
import { listNamespaces } from "../../lib/repos/catalog.js";
|
|
15
|
-
import {
|
|
15
|
+
import { loadCatalogContext } from "../../lib/repos/catalog-inputs.js";
|
|
16
|
+
import { listNamespaces, narrowToInstalled } from "../../lib/repos/catalog.js";
|
|
17
|
+
import {
|
|
18
|
+
INDENT,
|
|
19
|
+
describeCoverage,
|
|
20
|
+
describeIndexSource,
|
|
21
|
+
printBrowsingNotes,
|
|
22
|
+
} from "../../lib/repos/catalog-display.js";
|
|
16
23
|
import { renderTable, type TableColumn } from "../../utils/table.js";
|
|
24
|
+
import { browsingFlags } from "../../utils/flags.js";
|
|
17
25
|
import {
|
|
18
26
|
blankLine,
|
|
19
27
|
footer,
|
|
@@ -53,19 +61,28 @@ export default class NamespaceList extends BaseCommand {
|
|
|
53
61
|
*/
|
|
54
62
|
static aliases = ["namespaces:list"];
|
|
55
63
|
|
|
56
|
-
static examples = [
|
|
64
|
+
static examples = [
|
|
65
|
+
"<%= config.bin %> namespace list",
|
|
66
|
+
"<%= config.bin %> namespace list --installed",
|
|
67
|
+
];
|
|
57
68
|
|
|
58
|
-
static flags = { ...BaseCommand.baseFlags };
|
|
69
|
+
static flags = { ...BaseCommand.baseFlags, ...browsingFlags() };
|
|
59
70
|
|
|
60
71
|
async run(): Promise<void> {
|
|
61
|
-
await this.parse(NamespaceList);
|
|
72
|
+
const { flags } = await this.parse(NamespaceList);
|
|
62
73
|
|
|
63
74
|
showCommandVars({
|
|
64
75
|
Project: this.projectLabel,
|
|
65
76
|
Config: this.configContext.configPath,
|
|
77
|
+
Reading: describeIndexSource(flags.latest),
|
|
78
|
+
...(flags.installed ? { Showing: "only what this project has installed" } : {}),
|
|
66
79
|
});
|
|
67
80
|
|
|
68
|
-
heading(
|
|
81
|
+
heading(
|
|
82
|
+
flags.installed
|
|
83
|
+
? "Namespaces this project has installed recipes from"
|
|
84
|
+
: "Namespaces in the repositories this project trusts"
|
|
85
|
+
);
|
|
69
86
|
|
|
70
87
|
const service = subscriptionServiceFor({
|
|
71
88
|
configContext: this.configContext,
|
|
@@ -73,13 +90,21 @@ export default class NamespaceList extends BaseCommand {
|
|
|
73
90
|
shellEnv: this.shellEnv,
|
|
74
91
|
});
|
|
75
92
|
|
|
76
|
-
const { inputs, notFetched } =
|
|
93
|
+
const { inputs, notFetched, notChecked } = await loadCatalogContext({
|
|
77
94
|
service,
|
|
78
95
|
sousDir: this.configContext.sousDir,
|
|
79
96
|
settings: this.settings,
|
|
97
|
+
latest: flags.latest,
|
|
80
98
|
});
|
|
81
99
|
|
|
82
|
-
|
|
100
|
+
// Narrowed to what is installed, a namespace's recipe count is the number
|
|
101
|
+
// of its recipes the project has installed, and the column says so.
|
|
102
|
+
const listings = listNamespaces(flags.installed ? narrowToInstalled(inputs) : inputs);
|
|
103
|
+
const columns = flags.installed
|
|
104
|
+
? COLUMNS.map((column) =>
|
|
105
|
+
column.key === "recipes" ? { ...column, header: "Installed" } : column
|
|
106
|
+
)
|
|
107
|
+
: COLUMNS;
|
|
83
108
|
|
|
84
109
|
blankLine();
|
|
85
110
|
|
|
@@ -88,7 +113,9 @@ export default class NamespaceList extends BaseCommand {
|
|
|
88
113
|
inputs.repos.length === 0
|
|
89
114
|
? "Sous has read no repository index for this project, so there are no " +
|
|
90
115
|
"namespaces to show."
|
|
91
|
-
:
|
|
116
|
+
: flags.installed
|
|
117
|
+
? "This project has installed no recipe from the repositories it trusts."
|
|
118
|
+
: "The repositories this project trusts publish no namespaces."
|
|
92
119
|
);
|
|
93
120
|
} else {
|
|
94
121
|
const rows = listings.map((entry) => ({
|
|
@@ -99,18 +126,12 @@ export default class NamespaceList extends BaseCommand {
|
|
|
99
126
|
description: entry.description ?? "no description published",
|
|
100
127
|
}));
|
|
101
128
|
|
|
102
|
-
for (const line of renderTable(
|
|
129
|
+
for (const line of renderTable(columns, rows, { indent: INDENT })) {
|
|
103
130
|
log(indent(line, INDENT));
|
|
104
131
|
}
|
|
105
132
|
}
|
|
106
133
|
|
|
107
|
-
|
|
108
|
-
blankLine();
|
|
109
|
-
paragraph(
|
|
110
|
-
`These repositories are trusted and their index has not been fetched yet, so ` +
|
|
111
|
-
`nothing in them is listed: ${notFetched.join(", ")}.`
|
|
112
|
-
);
|
|
113
|
-
}
|
|
134
|
+
printBrowsingNotes({ notFetched, notChecked });
|
|
114
135
|
|
|
115
136
|
footer();
|
|
116
137
|
}
|