@sous-io/sous 0.2.0 → 0.2.2
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/README.md +4 -0
- package/docs/markdown/_sidebar.md +4 -1
- package/docs/markdown/commands.md +293 -274
- package/docs/markdown/configuration.md +7 -0
- package/docs/markdown/repositories-authoring.md +210 -301
- package/docs/markdown/repositories-consuming.md +219 -468
- package/docs/markdown/repositories-file-formats.md +216 -980
- package/docs/markdown/repositories-providers.md +322 -0
- package/docs/markdown/repositories-quickstart.md +340 -0
- package/docs/markdown/repositories-troubleshooting.md +336 -0
- package/docs/markdown/repositories-variables.md +229 -296
- package/docs/markdown/repositories.md +262 -228
- package/package.json +1 -1
- package/recipes/core/sous-skills/sous.recipe.yaml +1 -1
- package/src/commands/repo/release.ts +14 -8
- package/src/lib/repos/scaffold/templates.ts +9 -7
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Troubleshooting Repositories
|
|
2
|
+
|
|
3
|
+
The situations below are the ones people actually hit. Each gives the shape of the message, what
|
|
4
|
+
caused it, and what to do about it. For the model behind any of them read
|
|
5
|
+
[Repositories](repositories.md); for the schema of any file named here read
|
|
6
|
+
[Repository file formats](repositories-file-formats.md). One habit saves time: read the indented
|
|
7
|
+
lines under the first sentence of a failure, because that is where the remedy is.
|
|
8
|
+
|
|
9
|
+
## A repository this project does not trust
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Error: No added repository publishes the recipe 'workflow/nope'.
|
|
13
|
+
Repositories searched: qa-recipes, sous-recipes.
|
|
14
|
+
Add the repository that publishes it with 'sous repo add <url>', then try again.
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
A browsing command given a qualified ref whose qualifier is unknown says `This project trusts no
|
|
18
|
+
repository called 'acme'`; a subscribe says `Sous does not know where the repository 'acme' lives,
|
|
19
|
+
so it cannot add it for you`, and prints the `sous repo add <url> --name acme` line to run. Either
|
|
20
|
+
way, added equals trusted: sous reads nothing from a repository, not even its index, until the
|
|
21
|
+
project's `repos` map names it.
|
|
22
|
+
|
|
23
|
+
If a dependency of what you are installing lives in a repository you have not added, sous stops
|
|
24
|
+
before fetching anything and asks about all of them in one question, listing each URL and the recipe
|
|
25
|
+
that requires it; declining any of them stops the whole install.
|
|
26
|
+
|
|
27
|
+
!> Trusting a repository trusts every namespace and recipe in it, including ones published later.
|
|
28
|
+
Trusting alone runs nothing; subscribing to something inside it can run scripts on this machine.
|
|
29
|
+
See [Trust](repositories.md#trust).
|
|
30
|
+
|
|
31
|
+
## A ref that names more than one thing
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
Error: Sous has to ask which 'task-files' you meant, and it is not running where it can ask.
|
|
35
|
+
Why: neither input nor output is a terminal.
|
|
36
|
+
'task-files' matched 2 things:
|
|
37
|
+
acme:workflow/task-files (the recipe 'task-files' in the namespace 'workflow' of the
|
|
38
|
+
repository 'acme')
|
|
39
|
+
sous-recipes:workflow/task-files (the recipe 'task-files' in the namespace 'workflow' of
|
|
40
|
+
the repository 'sous-recipes')
|
|
41
|
+
Answer it ahead of time: write the full reference (for example 'acme:workflow/task-files'), or
|
|
42
|
+
pass '--accept-first' to take the first candidate listed above.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
At a terminal that same list is offered as a choice instead; sous never picks a winner on its own,
|
|
46
|
+
because a short name is a label your project chose. Three ways to settle it:
|
|
47
|
+
|
|
48
|
+
- Write the qualified ref, `acme:workflow/task-files`, which is the durable fix.
|
|
49
|
+
- Pass `--accept-first` to take the first candidate in the listing order printed above the error.
|
|
50
|
+
- Remove the repository you did not mean, with `sous repo remove <name>`.
|
|
51
|
+
|
|
52
|
+
The browsing commands, `sous recipe show` and `sous namespace show`, offer no choice and have no
|
|
53
|
+
`--accept-first`; they stop with `'task-files' names a recipe in more than one repository this
|
|
54
|
+
project trusts`, so there the qualified ref is the only fix.
|
|
55
|
+
|
|
56
|
+
## A version range nothing satisfies
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
Error: No published version of 'workflow/qa-helper' satisfies what was asked for.
|
|
60
|
+
Version range asked for:
|
|
61
|
+
^2 (required by project)
|
|
62
|
+
Versions this repository publishes: 0.1.0.
|
|
63
|
+
Prerelease versions were not considered. A subscription may opt into them with
|
|
64
|
+
'prerelease: true', and 'sous subscribe' with '--prerelease'.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The range comes from your own subscription or from a dependency of the recipe you asked for, and the
|
|
68
|
+
parenthetical says which: `required by project` is your subscription, anything else names the recipe
|
|
69
|
+
that asked. Widen or correct the range, or opt into prereleases with `prerelease: true` on the
|
|
70
|
+
subscription or `--prerelease` on the command.
|
|
71
|
+
|
|
72
|
+
## A question sous cannot ask
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
Error: Sous has to ask whether to go ahead with subscribing to 'workflow/task-files', and it is
|
|
76
|
+
not running where it can ask.
|
|
77
|
+
Why: neither input nor output is a terminal.
|
|
78
|
+
Answer it ahead of time: pass '--yes' (spelled '-y', '--force' or '--trust' if you prefer) to
|
|
79
|
+
accept the plan above without being asked.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The `Why:` line says which of the three non-interactive conditions applied; they are listed under
|
|
83
|
+
[Run sous in CI, or from an agent](repositories-consuming.md#run-sous-in-ci-or-from-an-agent).
|
|
84
|
+
Answer ahead of time:
|
|
85
|
+
|
|
86
|
+
| Question | Answer it ahead of time with |
|
|
87
|
+
|----------|------------------------------|
|
|
88
|
+
| Confirm this plan, or trust this repository | `--yes` (or `-y`, `--force`, `--trust`) |
|
|
89
|
+
| Which candidate did you mean | `--accept-first`, or write the fully qualified ref |
|
|
90
|
+
| What is the value of this recipe variable | `--answer name=value`, `--answers-file`, or the variable's environment variable |
|
|
91
|
+
|
|
92
|
+
Unanswered variables have their own page, [Recipe variables](repositories-variables.md).
|
|
93
|
+
|
|
94
|
+
## A dependency written as a path
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
Error: Invalid dependency 'local:///home/me/recipes/workflow/sat': a local repository is a
|
|
98
|
+
consumer's convenience, not a published location, so a manifest cannot depend on one. Publish
|
|
99
|
+
the recipe and depend on it by its published location.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
A published manifest is read on other machines, so it can only name locations those machines can
|
|
103
|
+
reach. Two neighboring mistakes get their own messages: a `repo:` qualifier is refused, because a
|
|
104
|
+
short name is a label only the consuming project knows, and an unknown scheme is refused with the
|
|
105
|
+
providers sous ships named (see [Providers](repositories-providers.md)). The legal forms:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
depends:
|
|
109
|
+
- workflow/sat # a sibling in this repository
|
|
110
|
+
- github://acme/recipes/workflow/sat@^1.1 # a recipe in another repository
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
While developing both sides, use
|
|
114
|
+
[`sous repo link`](repositories-authoring.md#edit-a-repository-in-place); it redirects resolution
|
|
115
|
+
at a working copy without changing what you publish.
|
|
116
|
+
|
|
117
|
+
## A published version whose content changed
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
Error: The content of github.com/acme/recipes:workflow/sat@1.2.0 does not match the hash it is
|
|
121
|
+
pinned to.
|
|
122
|
+
Expected: sha256-...
|
|
123
|
+
Actual: sha256-...
|
|
124
|
+
Nothing was written to the store. Either the upstream files changed under a published version,
|
|
125
|
+
or the download was corrupted.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
A version is immutable: the lockfile pins each recipe's content hash, and a restore verifies what
|
|
129
|
+
arrives against it before anything is written. Retry once, in case the download was truncated; if it
|
|
130
|
+
fails again, the tag upstream has moved, so tell the publisher rather than editing the hash in your
|
|
131
|
+
lockfile. A related message appears when the store already holds that version with other content:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
Error: The store already holds github.com/acme/recipes:workflow/sat@1.2.0 with different content.
|
|
135
|
+
Stored: sha256-...
|
|
136
|
+
Incoming: sha256-...
|
|
137
|
+
A published version is immutable, so sous will not overwrite it. Remove the entry deliberately
|
|
138
|
+
if the upstream version was genuinely republished.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## A sibling with no tag
|
|
142
|
+
|
|
143
|
+
Releasing a recipe whose sibling in the same repository has never been published fails:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
Error: recipes/workflow/task-files/sous.recipe.yaml:
|
|
147
|
+
it depends on 'workflow/sat', which has never been published: this repository carries no tag
|
|
148
|
+
for it. Release it first, which cuts the tag 'workflow/sat@1.0.0'.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Every problem is printed with the manifest it was found in, and the run ends with
|
|
152
|
+
`Error: This repository cannot be released yet: 1 problem is listed above.` Release the sibling
|
|
153
|
+
first, or widen the scope so one run publishes both; sous tags a sibling before whatever depends on
|
|
154
|
+
it. A sibling that HAS been tagged but has changed since is only a warning:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
WARNING:
|
|
158
|
+
recipes/workflow/task-files/sous.recipe.yaml:
|
|
159
|
+
'workflow/sat' has changes since 'workflow/sat@1.0.0' that are outside this release's scope;
|
|
160
|
+
'workflow/task-files@2.0.0' will depend on 'workflow/sat@1.0.0'.
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
If that is not what you want, include the sibling in the release scope.
|
|
164
|
+
|
|
165
|
+
## A release with no git identity
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
Error: Cannot release: git does not know who is making the commit.
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
A release commits the version bumps and the index, and cuts an annotated tag for every version it
|
|
172
|
+
publishes; git refuses to do either without an author identity. The check runs after the plan is
|
|
173
|
+
accepted and before anything is committed or tagged, so a run that stops here has written nothing.
|
|
174
|
+
Set `git config user.name` and `git config user.email` and run the command again; in a continuous
|
|
175
|
+
integration job, configure the identity of the account the release runs as, which the workflow
|
|
176
|
+
`sous repo init` scaffolds already does.
|
|
177
|
+
|
|
178
|
+
## An index older than you expected
|
|
179
|
+
|
|
180
|
+
Sous re-checks a repository's index only once its freshness window has lapsed; the window and its
|
|
181
|
+
default are described under
|
|
182
|
+
[Control freshness and the store](repositories-consuming.md#control-freshness-and-the-store).
|
|
183
|
+
A check is due when the repository has never been checked, when the window has lapsed, or when the
|
|
184
|
+
last recorded check time is in the future (a clock moved under sous). Re-adding an already-trusted
|
|
185
|
+
repository forces one; it refreshes the index and changes nothing else:
|
|
186
|
+
|
|
187
|
+
```term
|
|
188
|
+
$ sous repo add https://github.com/acme/recipes --name acme-recipes
|
|
189
|
+
Repository: acme-recipes
|
|
190
|
+
Namespaces: workflow
|
|
191
|
+
|
|
192
|
+
This project already trusted 'acme-recipes', so only its index was refreshed.
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
A failed check never breaks a build. Sous falls back to the copy it already has, says so, and
|
|
196
|
+
records the failure, so an unreachable host is not retried on every single build:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
Sous could not check the repository 'acme-recipes' for updates, so it is using the copy of its
|
|
200
|
+
index that it already had.
|
|
201
|
+
fatal: unable to access 'https://github.com/acme/recipes/': Could not resolve host github.com
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## A store entry that fails its hash
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
The cached copy of github.com/sous-io/sous-recipes:core/sous-skills@0.2.0 did not match its
|
|
208
|
+
recorded content hash, so it was removed from the store and will be fetched again.
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
This is a warning, not an error, and the build carries on. Every store entry records the hash of its
|
|
212
|
+
own content and sous verifies the tree on every lookup, so a store damaged by a crash, a partial copy
|
|
213
|
+
or a stray edit heals itself on the next run. Never edit files inside `$SOUS_HOME/cache`; the edit is
|
|
214
|
+
discarded, and `sous repo link` is the supported way to work against a checkout. A warning on every
|
|
215
|
+
build points at the machine: a filesystem that reorders writes, or two accounts sharing one store.
|
|
216
|
+
|
|
217
|
+
To reclaim space rather than repair, run `sous repo gc --dry-run` to see what would go, then
|
|
218
|
+
`sous repo gc`; what it evicts, and what it protects, is described under
|
|
219
|
+
[Control freshness and the store](repositories-consuming.md#control-freshness-and-the-store).
|
|
220
|
+
|
|
221
|
+
## A lockfile written by an older sous
|
|
222
|
+
|
|
223
|
+
Older lockfiles recorded only a repository's URL; each entry now also carries the canonical identity
|
|
224
|
+
the machine-wide store is keyed by. Reading an old lockfile is not an error: sous derives the
|
|
225
|
+
identity from the URL, and the field fills itself in on the next write. It fails only when the URL
|
|
226
|
+
belongs to no provider sous knows:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
repos.acme.identity is missing, and sous could not work one out from the url
|
|
230
|
+
'svn://example.com/recipes' because no provider recognizes it. Add an 'identity' to this entry,
|
|
231
|
+
or remove the lockfile and subscribe again to have sous rebuild it.
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The repair for a lockfile that has drifted from the config, whether from a hand edit, a bad merge or
|
|
235
|
+
a subscription removed by hand, is `sous lock rebuild`, with `--dry-run` first. It resolves every
|
|
236
|
+
subscription against the cached indexes and replaces the lockfile outright, downloading nothing,
|
|
237
|
+
asking nothing and granting no trust; a subscription whose repository is not added, or whose index is
|
|
238
|
+
missing, is reported by name.
|
|
239
|
+
|
|
240
|
+
## Core skills missing after a sous upgrade
|
|
241
|
+
|
|
242
|
+
Every project is subscribed to the `core` namespace, and the matching recipe ships inside the sous
|
|
243
|
+
package, so a first run with no network still gets it. Right after an upgrade the official
|
|
244
|
+
repository has usually not published the matching version yet, so sous folds the packaged version
|
|
245
|
+
into that repository's index in memory and leaves the cached file untouched; see
|
|
246
|
+
[The official repository](repositories.md#the-official-repository-and-the-built-in-core). Seeding
|
|
247
|
+
never fails a build, and when it genuinely fails it says so and carries on:
|
|
248
|
+
|
|
249
|
+
```text
|
|
250
|
+
Sous could not seed the core recipe it ships with, so the skills in the 'core' namespace are
|
|
251
|
+
unavailable until this is fixed.
|
|
252
|
+
EACCES: permission denied, mkdir '/home/me/.sous/cache'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The second line is the underlying failure, and it is nearly always a store that cannot be written:
|
|
256
|
+
`$SOUS_HOME` pointing somewhere read-only, a full disk, or a permissions problem left by running sous
|
|
257
|
+
once under `sudo`.
|
|
258
|
+
|
|
259
|
+
## Every build says a repository is linked
|
|
260
|
+
|
|
261
|
+
```text
|
|
262
|
+
WARNING:
|
|
263
|
+
One repository is LINKED to a working copy on this machine.
|
|
264
|
+
Their recipes are read from those checkouts, so versions, the lockfile and
|
|
265
|
+
freshness checks do not apply to them.
|
|
266
|
+
|
|
267
|
+
acme-recipes -> /home/me/Projects/acme-recipes
|
|
268
|
+
|
|
269
|
+
Run 'sous repo unlink <name>' to go back to the published versions.
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
This is working as intended and cannot be suppressed. A link makes a build read a repository from a
|
|
273
|
+
working copy instead of a published version, so it can produce something different from what a
|
|
274
|
+
colleague's build produces from the same commit, and a silent change of that size would be worse than
|
|
275
|
+
a noisy one. Run `sous repo unlink <name>` when you are done editing; a colleague seeing this warning
|
|
276
|
+
is seeing a link on their own machine. Links are never committed: they live in
|
|
277
|
+
`.sous/sous.links.json` (this project) or `$SOUS_HOME/sous.links.json` (every project on the machine),
|
|
278
|
+
and sous keeps the project's own map out of version control through the managed block it maintains in
|
|
279
|
+
`.sous/.gitignore`; the machine-wide map lives outside any working copy.
|
|
280
|
+
|
|
281
|
+
## A variable pattern that runs out of time
|
|
282
|
+
|
|
283
|
+
```text
|
|
284
|
+
apiUrl could not be checked: the pattern ^(([a-z]+)+)+$, published by the recipe
|
|
285
|
+
workflow/task-files, took longer than 100 milliseconds to run, so sous stopped waiting for it.
|
|
286
|
+
The pattern is too slow to run, and the answer was not the problem; this needs to be reported to
|
|
287
|
+
whoever publishes the recipe.
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Recipe variables may declare a validation pattern, and sous runs each under a time budget (100
|
|
291
|
+
milliseconds by default) so a backtracking regular expression cannot hang a build. No answer you can
|
|
292
|
+
type would finish a runaway pattern, so this is a bug report for the publisher; until it is fixed,
|
|
293
|
+
pin the recipe to a version published before the pattern arrived.
|
|
294
|
+
|
|
295
|
+
## A local repository named by a relative path
|
|
296
|
+
|
|
297
|
+
On the command line a relative path is fine; `sous repo add ../recipes` expands it and stores the
|
|
298
|
+
absolute result (see [The local provider](repositories-providers.md#the-local-provider) for what a
|
|
299
|
+
bad path prints). Inside a config file a bare relative path never reaches a provider: config
|
|
300
|
+
validation rejects it first, as `repos.acme.url: Invalid input` inside the `Invalid sous config at
|
|
301
|
+
<path>:` block. An entry that does name the local provider, through a `file://` URL or
|
|
302
|
+
`provider: local`, gets the fuller explanation; either way, write the absolute path:
|
|
303
|
+
|
|
304
|
+
```text
|
|
305
|
+
Error: 'file://../recipes' is not a local repository path that sous can read.
|
|
306
|
+
A local repository is named by an absolute path, or by the same path in 'file:///...' form. A
|
|
307
|
+
relative path is not accepted, because a repository entry is read from a config file that
|
|
308
|
+
several working directories may run against.
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## A store two accounts share
|
|
312
|
+
|
|
313
|
+
Permission failures writing the store, entries that keep failing their hash, `sous repo gc`
|
|
314
|
+
evicting entries another user's project was using (it keeps only what the lockfile in front of it
|
|
315
|
+
pins), and machine-wide links nobody on that project created all point at one cause: two accounts
|
|
316
|
+
sharing a `SOUS_HOME`.
|
|
317
|
+
|
|
318
|
+
`$SOUS_HOME` defaults to `~/.sous`, and what it holds is laid out under
|
|
319
|
+
[The store on disk](repositories-file-formats.md#the-store-on-disk). It is
|
|
320
|
+
per-user state, and nothing in it is locked against two people writing at once. It is also the one
|
|
321
|
+
`SOUS_*` variable that may be set in an env file, because it does not decide which project is
|
|
322
|
+
active, so a project needing its own store can say `SOUS_HOME=~/caches/sous-home` in
|
|
323
|
+
`.sous/.env.local`. A bare or whitespace-only value counts as unset, and a leading `~` expands;
|
|
324
|
+
compare [Discovery and overrides](config-discovery.md), where `SOUS_CONFIG`, `SOUS_DIR` and
|
|
325
|
+
`SOUS_CONFD` are read from the real environment only.
|
|
326
|
+
|
|
327
|
+
## Where to go next
|
|
328
|
+
|
|
329
|
+
- [Quickstart](repositories-quickstart.md): the shortest path from an empty project to a skill
|
|
330
|
+
- [Repositories](repositories.md): the model, and what lives where
|
|
331
|
+
- [Consuming recipes](repositories-consuming.md): adding, subscribing, updating, removing
|
|
332
|
+
- [Recipe variables](repositories-variables.md): answers, env files, unanswered questions
|
|
333
|
+
- [Authoring a repository](repositories-authoring.md): publishing, linking, releasing
|
|
334
|
+
- [Providers](repositories-providers.md): which URLs sous recognizes, and what `local` can do
|
|
335
|
+
- [Repository file formats](repositories-file-formats.md) and the
|
|
336
|
+
[command reference](commands.md): every schema, every command, every flag
|