@sous-io/sous 0.1.0 → 0.2.0
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/README.md +121 -35
- package/bin/run.js +10 -1
- package/docs/markdown/README.md +27 -0
- package/docs/markdown/_sidebar.md +18 -0
- package/docs/markdown/commands.md +308 -0
- package/docs/markdown/config-discovery.md +74 -0
- package/docs/markdown/config-inspection.md +69 -0
- package/docs/markdown/config-layers.md +92 -0
- package/docs/markdown/config-variables.md +79 -0
- package/docs/markdown/configuration.md +71 -0
- package/docs/markdown/design-principles.md +59 -0
- package/docs/markdown/repositories-authoring.md +408 -0
- package/docs/markdown/repositories-consuming.md +580 -0
- package/docs/markdown/repositories-file-formats.md +1084 -0
- package/docs/markdown/repositories-variables.md +387 -0
- package/docs/markdown/repositories.md +303 -0
- package/docs/markdown/skill-categories.md +58 -0
- package/package.json +73 -9
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/SKILL.tpl.md +20 -20
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/examples/about-something.md +2 -2
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/examples/do-something.md +1 -1
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/advanced-patterns.md +6 -6
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/commands.md +5 -5
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/frontmatter.md +3 -3
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-liquid-templates/SKILL.tpl.md +40 -25
- package/recipes/core/sous-skills/skills/about-sous/SKILL.tpl.md +70 -0
- package/recipes/core/sous-skills/skills/about-sous-configuration/SKILL.tpl.md +75 -0
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/create-skill/SKILL.tpl.md +8 -9
- package/recipes/core/sous-skills/sous.recipe.yaml +45 -0
- package/sous.config.schema.json +337 -0
- package/src/base-command.ts +220 -67
- package/src/commands/build.ts +150 -73
- package/src/commands/clear.ts +23 -15
- package/src/commands/compile.ts +74 -16
- package/src/commands/config/get.ts +110 -0
- package/src/commands/config/show.ts +32 -0
- package/src/commands/config/validate.ts +53 -0
- package/src/commands/help.ts +46 -0
- package/src/commands/launch.ts +36 -14
- package/src/commands/lock/rebuild.ts +241 -0
- package/src/commands/lock/show.ts +115 -0
- package/src/commands/namespace/list.ts +117 -0
- package/src/commands/namespace/show.ts +110 -0
- package/src/commands/prune.ts +3 -11
- package/src/commands/recipe/list.ts +95 -0
- package/src/commands/recipe/show.ts +301 -0
- package/src/commands/repo/add.ts +145 -0
- package/src/commands/repo/gc.ts +172 -0
- package/src/commands/repo/init.ts +136 -0
- package/src/commands/repo/link.ts +500 -0
- package/src/commands/repo/list.ts +179 -0
- package/src/commands/repo/release.ts +619 -0
- package/src/commands/repo/remove.ts +193 -0
- package/src/commands/repo/search.ts +189 -0
- package/src/commands/repo/submit.ts +133 -0
- package/src/commands/repo/unlink.ts +147 -0
- package/src/commands/subscription/add.ts +285 -0
- package/src/commands/subscription/list.ts +129 -0
- package/src/commands/subscription/remove.ts +181 -0
- package/src/commands/vars/ask.ts +374 -0
- package/src/commands/vars/index.ts +79 -0
- package/src/commands/vars/list.ts +67 -0
- package/src/commands/vars/show.ts +77 -0
- package/src/config-command.ts +30 -0
- package/src/lib/build-service.ts +206 -54
- package/src/lib/config-discovery.ts +220 -27
- package/src/lib/config-inspect.ts +145 -0
- package/src/lib/config-kernel.mjs +377 -0
- package/src/lib/config-schema.ts +361 -0
- package/src/lib/env-file.ts +328 -0
- package/src/lib/env-local.ts +18 -1
- package/src/lib/errors.ts +32 -0
- package/src/lib/include-resolver.ts +108 -15
- package/src/lib/interactive.ts +165 -0
- package/src/lib/markdown-compiler.ts +118 -37
- package/src/lib/package-info.ts +25 -0
- package/src/lib/pid-service.ts +32 -21
- package/src/lib/refs/find.ts +589 -0
- package/src/lib/refs/index.ts +12 -0
- package/src/lib/refs/pick.ts +147 -0
- package/src/lib/refs/scopes.ts +61 -0
- package/src/lib/repos/catalog-display.ts +116 -0
- package/src/lib/repos/catalog-inputs.ts +160 -0
- package/src/lib/repos/catalog.ts +722 -0
- package/src/lib/repos/core-recipe.ts +105 -0
- package/src/lib/repos/defaults.ts +175 -0
- package/src/lib/repos/formats/common.ts +389 -0
- package/src/lib/repos/formats/index-file.ts +215 -0
- package/src/lib/repos/formats/links-map.ts +96 -0
- package/src/lib/repos/formats/lockfile.ts +167 -0
- package/src/lib/repos/formats/patterns.ts +57 -0
- package/src/lib/repos/formats/recipe-manifest.ts +395 -0
- package/src/lib/repos/formats/repo-manifest.ts +88 -0
- package/src/lib/repos/formats/store-entry.ts +84 -0
- package/src/lib/repos/freshness.ts +208 -0
- package/src/lib/repos/git-clone.ts +312 -0
- package/src/lib/repos/identity.ts +89 -0
- package/src/lib/repos/index.ts +58 -0
- package/src/lib/repos/links.ts +353 -0
- package/src/lib/repos/load-manifest.ts +236 -0
- package/src/lib/repos/lock-service.ts +453 -0
- package/src/lib/repos/locked-namespace-resolver.ts +90 -0
- package/src/lib/repos/locked-recipes.ts +254 -0
- package/src/lib/repos/managed-layer.ts +422 -0
- package/src/lib/repos/namespace-resolver.ts +370 -0
- package/src/lib/repos/providers/base.ts +206 -0
- package/src/lib/repos/providers/git.ts +233 -0
- package/src/lib/repos/providers/github.ts +294 -0
- package/src/lib/repos/providers/gitlab.ts +263 -0
- package/src/lib/repos/providers/http.ts +102 -0
- package/src/lib/repos/providers/index-cache.ts +382 -0
- package/src/lib/repos/providers/index.ts +106 -0
- package/src/lib/repos/providers/local.ts +391 -0
- package/src/lib/repos/providers/provider.ts +401 -0
- package/src/lib/repos/recipe-config-layers.ts +287 -0
- package/src/lib/repos/recipe-targets.ts +223 -0
- package/src/lib/repos/ref-search.ts +46 -0
- package/src/lib/repos/ref.ts +513 -0
- package/src/lib/repos/reference-report.ts +122 -0
- package/src/lib/repos/release/bump.ts +161 -0
- package/src/lib/repos/release/git-state.ts +305 -0
- package/src/lib/repos/release/index-builder.ts +635 -0
- package/src/lib/repos/release/index.ts +16 -0
- package/src/lib/repos/release/plan.ts +512 -0
- package/src/lib/repos/release/submit-service.ts +496 -0
- package/src/lib/repos/release/tags.ts +243 -0
- package/src/lib/repos/release/validate.ts +463 -0
- package/src/lib/repos/resolver.ts +789 -0
- package/src/lib/repos/scaffold/index.ts +238 -0
- package/src/lib/repos/scaffold/templates.ts +413 -0
- package/src/lib/repos/seed.ts +414 -0
- package/src/lib/repos/store/contract.ts +64 -0
- package/src/lib/repos/store/hash.ts +114 -0
- package/src/lib/repos/store/recipe-store.ts +599 -0
- package/src/lib/repos/store/settings.ts +58 -0
- package/src/lib/repos/subscription-service.ts +2678 -0
- package/src/lib/repos/trust.ts +447 -0
- package/src/lib/settings.ts +546 -189
- package/src/lib/sous-home.ts +104 -0
- package/src/lib/state.ts +52 -20
- package/src/lib/vars/ask.ts +1152 -0
- package/src/lib/vars/definition-source.ts +252 -0
- package/src/lib/vars/display.ts +233 -0
- package/src/lib/vars/index.ts +18 -0
- package/src/lib/vars/ladder.ts +282 -0
- package/src/lib/vars/mappings.ts +265 -0
- package/src/lib/vars/names.ts +94 -0
- package/src/lib/vars/preanswers.ts +395 -0
- package/src/lib/vars/question-plan.ts +218 -0
- package/src/lib/vars/report.ts +228 -0
- package/src/lib/vars/safe-regex.ts +235 -0
- package/src/lib/vars/validate.ts +312 -0
- package/src/lib/watch-loop.ts +148 -0
- package/src/templating/init-liquid-engine.ts +58 -16
- package/src/utils/choice-prompt.ts +143 -0
- package/src/utils/command-errors.ts +186 -0
- package/src/utils/command-help.ts +45 -0
- package/src/utils/confirm-prompt.ts +110 -0
- package/src/utils/flags.ts +153 -0
- package/src/utils/formatting.ts +540 -55
- package/src/utils/prompts.ts +35 -1
- package/src/utils/sous-directory.ts +245 -0
- package/src/utils/table.ts +603 -0
- package/src/utils/value-prompt.ts +119 -0
- package/bin/xcv +0 -5
- package/shared-prompts/_partials/resume-task.md +0 -51
- package/shared-prompts/_partials/sub-agent-delegation.md +0 -32
- package/shared-prompts/_partials/update-task-file.md +0 -52
- package/shared-prompts/memories/automated-browser-tasks/INDEX.tpl.md +0 -52
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/SKILL.tpl.md +0 -102
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/auth-failure-handling.mjs +0 -81
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/chained-workflow.mjs +0 -126
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/simple-fetch.mjs +0 -92
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/architecture.md +0 -61
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/auth-and-sessions.md +0 -65
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/ctx-api.md +0 -96
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/installation.md +0 -104
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/script-conventions.md +0 -243
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/chrome-state.mjs +0 -148
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.mjs +0 -383
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.spec.mjs +0 -267
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/eslint.config.mjs +0 -56
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/harness.mjs +0 -169
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/keyring.mjs +0 -59
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/logger.mjs +0 -25
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/params.mjs +0 -140
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/run.mjs +0 -140
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/settings.tpl.mjs +0 -1
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/utils.mjs +0 -185
- package/shared-prompts/skills/automated-browser-tasks/create-automated-browser-task/SKILL.tpl.md +0 -52
- package/shared-prompts/skills/automated-browser-tasks/running-automated-browser-tasks/SKILL.tpl.md +0 -59
- package/shared-prompts/skills/automated-browser-tasks/update-automated-browser-task/SKILL.tpl.md +0 -47
- package/shared-prompts/skills/control-flow/approve/SKILL.tpl.md +0 -26
- package/shared-prompts/skills/control-flow/opine/SKILL.tpl.md +0 -58
- package/shared-prompts/skills/control-flow/repeat/SKILL.tpl.md +0 -27
- package/shared-prompts/skills/control-flow/research/SKILL.tpl.md +0 -34
- package/shared-prompts/skills/sous-skills/about-sous/SKILL.tpl.md +0 -51
- package/shared-prompts/skills/task-files/about-task-files/SKILL.tpl.md +0 -122
- package/shared-prompts/skills/task-files/continue-task-in-new-branch/SKILL.tpl.md +0 -80
- package/shared-prompts/skills/task-files/go/SKILL.tpl.md +0 -14
- package/shared-prompts/skills/task-files/resume-task/SKILL.tpl.md +0 -13
- package/shared-prompts/skills/task-files/start-task/SKILL.tpl.md +0 -93
- package/shared-prompts/skills/task-files/update/SKILL.tpl.md +0 -14
- package/shared-prompts/skills/task-files/update-task-file/SKILL.tpl.md +0 -13
- /package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/substitutions.md +0 -0
- /package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-liquid-templates/references/liquid-filters.md +0 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# Recipe Variables
|
|
2
|
+
|
|
3
|
+
A recipe that needs a value from your project publishes a **variable definition**: a
|
|
4
|
+
specification with a name, a type, a question and a set of constraints. You supply an **answer**.
|
|
5
|
+
A "question" is only the interactive moment; sous asks one only when a subscribed recipe needs a
|
|
6
|
+
variable and nothing in scope answers it, or when the answer in scope no longer fits.
|
|
7
|
+
|
|
8
|
+
?> This page is about variables that recipes publish. Your project's own `${var}` configuration
|
|
9
|
+
variables are a different, older, deliberately ceremony-free system; see
|
|
10
|
+
[Variables](config-variables.md) for those. The two never mix.
|
|
11
|
+
|
|
12
|
+
## Where answers live
|
|
13
|
+
|
|
14
|
+
Answers are stored in your project's env files, and nowhere else:
|
|
15
|
+
|
|
16
|
+
| File | Committed | Holds |
|
|
17
|
+
|------|-----------|-------|
|
|
18
|
+
| `.sous/.env` | yes | Shared answers (`scope: shared`), the team's defaults |
|
|
19
|
+
| `.sous/.env.local` | no, gitignored | Machine-specific answers (`scope: local`) and every secret |
|
|
20
|
+
|
|
21
|
+
Sous edits these files the way a careful person would. Exactly one value line is rewritten or
|
|
22
|
+
appended; comments, blank lines, ordering and quoting all survive untouched. A newly added entry
|
|
23
|
+
gets a short generated header comment above it saying where the value came from:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Set by sous for workflow/task-files: Where should task files live?
|
|
27
|
+
# One file per git branch is written here.
|
|
28
|
+
# Edit freely; sous only rewrites the value line.
|
|
29
|
+
SOUS_VAR_TASK_FILE_ROOT=.sous/tasks
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Those comments are output only. Sous never reads one back, so editing or deleting a comment
|
|
33
|
+
changes nothing, and editing the value line is a perfectly normal way to change an answer.
|
|
34
|
+
|
|
35
|
+
## The ladder
|
|
36
|
+
|
|
37
|
+
For each variable, sous generates a list of environment variable names and tries them in order,
|
|
38
|
+
most specific first. The first name that holds a value wins.
|
|
39
|
+
|
|
40
|
+
| Rung | Name | Example | When it applies |
|
|
41
|
+
|------|------|---------|-----------------|
|
|
42
|
+
| 1. mapping record | whatever the record names | `TEAM_API_URL` | Only when a record exists for this variable |
|
|
43
|
+
| 2. recipe scope | `SOUS_VAR_<NAMESPACE>_<RECIPE>_<VARIABLE>` | `SOUS_VAR_WORKFLOW_TASK_FILES_API_URL` | Answers this one recipe's variable and nothing else |
|
|
44
|
+
| 3. namespace scope | `SOUS_VAR_<NAMESPACE>_<VARIABLE>` | `SOUS_VAR_WORKFLOW_API_URL` | Answers every recipe in the namespace at once |
|
|
45
|
+
| 4. shared scope | `SOUS_VAR_<VARIABLE>` | `SOUS_VAR_API_URL` | Answers every recipe that declares that variable name |
|
|
46
|
+
| 5. declared name | the definition's own `env` field | `GITHUB_TOKEN` | How a recipe binds a value the environment already carries |
|
|
47
|
+
|
|
48
|
+
Read from the bottom up, the ladder is a story about sharing. One `SOUS_VAR_API_URL` answers
|
|
49
|
+
every recipe that wants an `apiUrl`, which is what you want most of the time. When two recipes
|
|
50
|
+
want the same name and mean different things, move one answer up a rung to the namespace or the
|
|
51
|
+
recipe form, and the more specific name wins for that recipe alone. When even that is not enough,
|
|
52
|
+
a mapping record settles it.
|
|
53
|
+
|
|
54
|
+
!> Candidate names are only ever GENERATED and looked up, never parsed back into scopes. The
|
|
55
|
+
underscore is both the delimiter and a legal identifier character, so no parse of a name would be
|
|
56
|
+
trustworthy: `SOUS_VAR_TASK_FILES_ROOT` could be three different things. Sous therefore builds the
|
|
57
|
+
five candidates it knows are correct and asks the environment about each one.
|
|
58
|
+
|
|
59
|
+
## The three sources, within a rung
|
|
60
|
+
|
|
61
|
+
Each rung is looked up in three places, in this order:
|
|
62
|
+
|
|
63
|
+
1. **The real shell environment.** `SOUS_VAR_API_URL=... sous build` beats both files.
|
|
64
|
+
2. **`.sous/.env.local`.** Gitignored; your machine, your secrets.
|
|
65
|
+
3. **`.sous/.env`.** Committed; the team's shared defaults.
|
|
66
|
+
|
|
67
|
+
No load ever overwrites a value that is already set, so the first writer wins. This is the same
|
|
68
|
+
precedence the rest of sous uses for env files; see
|
|
69
|
+
[Discovery and overrides](config-discovery.md).
|
|
70
|
+
|
|
71
|
+
## Mapping records
|
|
72
|
+
|
|
73
|
+
A mapping record binds one environment variable, of any name at all, to one fully qualified
|
|
74
|
+
variable. It is the top rung and the universal conflict resolver: two recipes wanting the same
|
|
75
|
+
name, or a name that already means something else in your environment.
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"varMappings": {
|
|
80
|
+
"TEAM_API_URL": "sous-recipes:misc/stuff/apiUrl"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
A target is written `namespace/recipe/variableName`, optionally qualified as
|
|
86
|
+
`repo:namespace/recipe/variableName`. Records live under the top-level `varMappings` config key.
|
|
87
|
+
Sous writes the ones it creates into `.sous/conf.d/520-var-mappings.jsonc`, editing one record at
|
|
88
|
+
a time so each name has exactly one, and you may hand-write `varMappings` in your primary config
|
|
89
|
+
too; the two merge like any other config layer.
|
|
90
|
+
|
|
91
|
+
You rarely write one yourself, because sous offers one at the moment the conflict appears. When
|
|
92
|
+
the name an answer would use already holds a value that does not fit the definition, you are
|
|
93
|
+
asked where the answer should go:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
SERVICE_TOKEN already holds a value that does not fit serviceToken. Where should this answer go?
|
|
97
|
+
SOUS_VAR_TOOLING_DEPLOY_SERVICE_TOKEN, with a mapping record (recommended)
|
|
98
|
+
SERVICE_TOKEN, replacing what is there
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Choosing the record writes both the answer under the scoped name and the record binding it, and
|
|
102
|
+
the run reports the pair. Where there is no terminal, the record is written, because overwriting
|
|
103
|
+
a value something else is already using would be the worse of the two guesses.
|
|
104
|
+
|
|
105
|
+
## `sous vars list`
|
|
106
|
+
|
|
107
|
+
Lists every variable in play: its name, the recipe that published it, the environment variable
|
|
108
|
+
that answered it, the value, and where the value came from. A secret's value is hidden.
|
|
109
|
+
|
|
110
|
+
```term
|
|
111
|
+
$ sous vars list
|
|
112
|
+
Variable Recipe Answered by Value Source
|
|
113
|
+
apiUrl workflow/task-files SOUS_VAR_API_URL https://api.example.com shared scope, the .env file
|
|
114
|
+
taskFileRoot workflow/task-files SOUS_VAR_TASK_... .sous/tasks shared scope, the .env file
|
|
115
|
+
serviceToken tooling/deploy nothing yet
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`--file <path>` reads definitions from a standalone definitions file instead of the project's
|
|
119
|
+
recipes. The file holds the same `variables:` array a recipe manifest carries, which is how a
|
|
120
|
+
project asks questions no recipe publishes yet.
|
|
121
|
+
|
|
122
|
+
## `sous vars show <name>`
|
|
123
|
+
|
|
124
|
+
Shows one variable in full: its question, the publisher's description and example, the recipe and
|
|
125
|
+
version that published it, the value in scope and whether it fits, then the same labeled facts the
|
|
126
|
+
advanced view of a question prints, and finally every name on the ladder with the rung that
|
|
127
|
+
actually answered.
|
|
128
|
+
|
|
129
|
+
```term
|
|
130
|
+
$ sous vars show apiUrl
|
|
131
|
+
Question : Which API should sous talk to?
|
|
132
|
+
About : Every request this recipe generates is sent to one deployment of
|
|
133
|
+
the API, and this setting says which one. The default points at
|
|
134
|
+
the public production host, but any deployment you can reach works.
|
|
135
|
+
For example: https://api.example.com
|
|
136
|
+
Recipe : workflow/task-files version 1.2.0 from sous-recipes
|
|
137
|
+
Stored in : .env
|
|
138
|
+
Value : https://api.example.com
|
|
139
|
+
|
|
140
|
+
example : https://api.example.com
|
|
141
|
+
required-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
|
|
142
|
+
defined-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
|
|
143
|
+
storage-path: /home/you/project/.sous/.env
|
|
144
|
+
stored-as : SOUS_VAR_API_URL
|
|
145
|
+
constraints : • must be a value of the type url (type: url)
|
|
146
|
+
|
|
147
|
+
Environment variable Rung Status
|
|
148
|
+
SOUS_VAR_WORKFLOW_TASK_FILES_API_URL recipe scope not set
|
|
149
|
+
SOUS_VAR_WORKFLOW_API_URL namespace scope not set
|
|
150
|
+
SOUS_VAR_API_URL shared scope answered it, from the .env file
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`required-by` and `defined-by` are the same links the advanced view of a question shows, so the
|
|
154
|
+
two views say the same thing in the same words.
|
|
155
|
+
|
|
156
|
+
The name may be the bare variable name or its full `namespace/recipe.name` key, which is what you
|
|
157
|
+
use when two recipes publish the same name.
|
|
158
|
+
|
|
159
|
+
?> Three names cannot be reached by the `sous vars <name>` shorthand: `list`, `show` and `ask`,
|
|
160
|
+
because each of those is a subcommand. A variable with one of those names is reached the long
|
|
161
|
+
way, as `sous vars show ask`.
|
|
162
|
+
|
|
163
|
+
## `sous vars ask`
|
|
164
|
+
|
|
165
|
+
Asks the questions the project's definitions imply and stores the answers.
|
|
166
|
+
|
|
167
|
+
| Invocation | What it does |
|
|
168
|
+
|------------|--------------|
|
|
169
|
+
| `sous vars ask` | Asks only what is unanswered, or what no longer fits its definition |
|
|
170
|
+
| `sous vars ask <name>` | Asks everything the name covers; see the forms below |
|
|
171
|
+
| `sous vars ask --repo <name>` | Asks every variable one repository publishes |
|
|
172
|
+
| `sous vars ask --namespace <name>` | Asks every variable one namespace publishes |
|
|
173
|
+
| `sous vars ask --var <name>` | Asks one variable; repeat it for each variable |
|
|
174
|
+
| `sous vars ask --accept-first` | When the name matches several things, takes the first one listed |
|
|
175
|
+
| `sous vars ask --all` | Asks every variable again, including the ones already answered |
|
|
176
|
+
| `sous vars ask --file <path>` | Reads definitions from a standalone definitions file |
|
|
177
|
+
| `sous vars ask --answer <name>=<value>` | Answers one question ahead of time; repeat it for each answer |
|
|
178
|
+
| `sous vars ask --answers-file <path>` | Reads answers from a YAML or JSON file of `name: value` pairs |
|
|
179
|
+
| `sous vars ask --dry-run` | Reports what would be asked and written, without writing anything |
|
|
180
|
+
|
|
181
|
+
### What the name may be
|
|
182
|
+
|
|
183
|
+
The name is a reference, resolved the way every sous command resolves one. It may name a
|
|
184
|
+
variable, an environment variable that answers one, a recipe, a namespace or a repository, and
|
|
185
|
+
anything larger than a variable asks every question it publishes:
|
|
186
|
+
|
|
187
|
+
```term
|
|
188
|
+
$ sous vars ask taskFileRoot
|
|
189
|
+
// one variable, by the name its recipe gave it
|
|
190
|
+
$ sous vars ask SOUS_VAR_TASK_FILE_ROOT
|
|
191
|
+
// the same variable, by an environment variable in use that answers it
|
|
192
|
+
$ sous vars ask workflow/task-files.taskFileRoot
|
|
193
|
+
// the same variable again, spelled out
|
|
194
|
+
$ sous vars ask task-files
|
|
195
|
+
// every question that one recipe asks
|
|
196
|
+
$ sous vars ask workflow
|
|
197
|
+
// every question every recipe in that namespace asks
|
|
198
|
+
$ sous vars ask sous-recipes
|
|
199
|
+
// every question that repository's recipes ask
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Every reference may be written at any level of qualification, up to the fully qualified
|
|
203
|
+
`repository:namespace/recipe.variable`, and matching is case-sensitive. An environment variable
|
|
204
|
+
name resolves when the definition declares it (a recipe may bind an existing variable such as
|
|
205
|
+
`GITHUB_TOKEN`) or when it is one of the generated ladder names that `.sous/.env` or
|
|
206
|
+
`.sous/.env.local` actually sets.
|
|
207
|
+
|
|
208
|
+
`--repo`, `--namespace` and `--var` say outright which kind of thing is meant, and narrow the
|
|
209
|
+
same way. Each one resolves against what the one before it left, so
|
|
210
|
+
`sous vars ask --namespace workflow apiUrl` asks about that namespace's `apiUrl` even when
|
|
211
|
+
another namespace publishes one too.
|
|
212
|
+
|
|
213
|
+
When a name matches more than one thing, sous lists what it could have meant and asks which one
|
|
214
|
+
you meant. `--accept-first` takes the first one listed, and a run with no terminal fails naming
|
|
215
|
+
that flag rather than guessing.
|
|
216
|
+
|
|
217
|
+
### How the questions run
|
|
218
|
+
|
|
219
|
+
Every trust decision is settled first. A subscribe resolves the whole dependency closure and runs
|
|
220
|
+
the trust ceremony for each new repository before the first question is printed, so a question is
|
|
221
|
+
never interleaved with a decision about who you are trusting.
|
|
222
|
+
|
|
223
|
+
Questions then run one recipe at a time: the recipe you subscribed to first, then each recipe it
|
|
224
|
+
depends on, each opening with how many answers it needs. When the closure covers more than one
|
|
225
|
+
recipe, a single lead-in says so before anything is asked:
|
|
226
|
+
|
|
227
|
+
```term
|
|
228
|
+
workflow/task-files needs 4 answers, and workflow/sub-agent-delegation, which it depends on, needs 2.
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Each question then prints its own view: the header, the publisher's description wrapped to your
|
|
232
|
+
terminal, and four labeled facts (the default, the example, and exactly where the answer will be
|
|
233
|
+
stored and under what name). The keys that do anything are named by the legend the question draws
|
|
234
|
+
under its own input line, in the style the stock prompts use. Those facts are drawn by the renderer
|
|
235
|
+
the advanced view uses, so the same label means the same thing and lines up the same way on both.
|
|
236
|
+
|
|
237
|
+
```term
|
|
238
|
+
workflow/task-files needs 4 answers before it can be used.
|
|
239
|
+
|
|
240
|
+
Question 1 of 4: taskFileRoot
|
|
241
|
+
|
|
242
|
+
This recipe mandates the creation of task files that are stored locally and, in
|
|
243
|
+
general, should not be committed. This setting dictates the path in which agents
|
|
244
|
+
will store and search for your task files. The default value stores task files in
|
|
245
|
+
the project's .sous directory, but you can specify any local path, either relative
|
|
246
|
+
to the project root or absolute.
|
|
247
|
+
|
|
248
|
+
default : .sous/tasks
|
|
249
|
+
example : ~/my-task-files
|
|
250
|
+
stored-as : SOUS_VAR_TASK_FILE_ROOT
|
|
251
|
+
storage-path: /home/you/project/.sous/.env
|
|
252
|
+
|
|
253
|
+
? Where should task files be stored? (.sous/tasks):
|
|
254
|
+
⏎ accept default • ⇥ advanced
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Enter accepts what is typed, or the default when nothing is. A question with no default drops
|
|
258
|
+
the Enter half of the legend, since there is nothing for Enter alone to accept, and shows
|
|
259
|
+
`⇥ advanced` alone. A question answered from a list rather than typed names the arrow keys
|
|
260
|
+
instead:
|
|
261
|
+
|
|
262
|
+
```term
|
|
263
|
+
? Which ticket system do you use?
|
|
264
|
+
> github
|
|
265
|
+
jira
|
|
266
|
+
linear
|
|
267
|
+
↑↓ navigate • ⏎ select • ⇥ advanced
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Tab opens the advanced view from every kind of question: a typed one, a pick-one list, and a
|
|
271
|
+
yes-or-no confirmation alike. The word is always "Advanced". Once an answer is stored, two lines
|
|
272
|
+
say what was stored and where:
|
|
273
|
+
|
|
274
|
+
```term
|
|
275
|
+
Answer : SOUS_VAR_TASK_FILE_ROOT=.sous/tasks
|
|
276
|
+
Saved to: /home/you/project/.sous/.env
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
An answer that was already in scope is never asked about again; it is reported with its scope and
|
|
280
|
+
its source instead.
|
|
281
|
+
|
|
282
|
+
### The advanced view
|
|
283
|
+
|
|
284
|
+
Tab opens the advanced view of the same question: every fact about the variable, laid out by the
|
|
285
|
+
same renderer `sous vars show` uses, and a menu for changing where the answer goes.
|
|
286
|
+
|
|
287
|
+
```term
|
|
288
|
+
[Advanced Variable Settings]
|
|
289
|
+
|
|
290
|
+
Question 1 of 4: taskFileRoot
|
|
291
|
+
|
|
292
|
+
This recipe mandates the creation of task files that are stored locally and, in
|
|
293
|
+
general, should not be committed. This setting dictates the path in which agents
|
|
294
|
+
will store and search for your task files. The default value stores task files in
|
|
295
|
+
the project's .sous directory, but you can specify any local path, either relative
|
|
296
|
+
to the project root or absolute.
|
|
297
|
+
|
|
298
|
+
default : .sous/tasks
|
|
299
|
+
example : ~/my-task-files
|
|
300
|
+
required-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
|
|
301
|
+
defined-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
|
|
302
|
+
storage-path: /home/you/project/.sous/.env
|
|
303
|
+
stored-as : SOUS_VAR_TASK_FILE_ROOT
|
|
304
|
+
constraints : • must be a value of the type path (type: path)
|
|
305
|
+
• must be at least 1 character long (minLength: 1)
|
|
306
|
+
|
|
307
|
+
? What would you like to do?
|
|
308
|
+
Return to value entry
|
|
309
|
+
Change the storage file
|
|
310
|
+
Change the stored variable name
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
`required-by` names the recipe you subscribed to whose closure pulled this variable in, and spells
|
|
314
|
+
out the chain when it arrived through a dependency; `defined-by` names the recipe that declares
|
|
315
|
+
the definition. Both carry the location beside the recipe key, in muted grey: a repository URL with
|
|
316
|
+
the recipe's folder for a hosted repository, and a filesystem path for one read from this machine.
|
|
317
|
+
|
|
318
|
+
Changing the stored name offers every rung the ladder looks up, with the one sous would use
|
|
319
|
+
already selected, plus a name of your own; a name the ladder would never look at is bound with a
|
|
320
|
+
mapping record, so resolution still finds it. Changing the storage file offers the committed
|
|
321
|
+
`.sous/.env` and the gitignored `.sous/.env.local`. Once anything has changed, the first menu item
|
|
322
|
+
becomes "Save changes and return to value entry" and a "Discard changes" item joins it.
|
|
323
|
+
|
|
324
|
+
A secret, or a variable the publisher declared machine-specific, may still be pointed at the
|
|
325
|
+
committed file. Sous does not prevent it; it says plainly that the value would enter your git
|
|
326
|
+
history and asks you to confirm, which is informed consent rather than a locked door. Returning to
|
|
327
|
+
the value question prints its view again, with the updated `stored-as` and `storage-path`
|
|
328
|
+
facts.
|
|
329
|
+
|
|
330
|
+
Every run ends with the same three-part report: what was inherited from an answer already in
|
|
331
|
+
scope, what was stored and under which name in which file, and what was left unanswered and why.
|
|
332
|
+
|
|
333
|
+
Subscribing runs the same machinery, so in normal use you rarely invoke `vars ask` by hand;
|
|
334
|
+
reach for it after editing an env file, after a recipe upgrade tightened a constraint, or when
|
|
335
|
+
you want to re-answer something deliberately with `--all`.
|
|
336
|
+
|
|
337
|
+
### Answering ahead of the questions
|
|
338
|
+
|
|
339
|
+
`--answer <name>=<value>` answers a question before it is asked, and repeats for as many answers
|
|
340
|
+
as there are questions; `--answers-file <path>` reads the same pairs from a YAML or JSON file
|
|
341
|
+
(comments allowed), and an `--answer` wins over the same name in the file. Both flags work the
|
|
342
|
+
same way on `sous subscription add`, which is where a run with no terminal usually meets them;
|
|
343
|
+
[Consuming recipes](repositories-consuming.md#answering-questions-ahead-of-time) walks through
|
|
344
|
+
that flow, dry run first.
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
sous vars ask --answer taskFileRoot=.sous/tasks --answer apiUrl=https://api.example.com
|
|
348
|
+
sous vars ask --answers-file ./answers.yaml
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
The name is spelled exactly as the recipe declares it, in camelCase, or as its full
|
|
352
|
+
`namespace/recipe.name` key; everything after the first `=` is the answer. Every supplied answer
|
|
353
|
+
is checked against its definition before anything is written, so a value that does not fit fails
|
|
354
|
+
the run naming the constraint and the publisher's example, and a name no recipe declares fails
|
|
355
|
+
naming every variable that is in play. An answer for a variable that already has one replaces it,
|
|
356
|
+
where that answer lives, and the report says what it replaced. Whatever is left over is asked for
|
|
357
|
+
as usual.
|
|
358
|
+
|
|
359
|
+
## Without a terminal
|
|
360
|
+
|
|
361
|
+
Sous never hangs waiting on a prompt it cannot show. A run with no terminal and an unanswered
|
|
362
|
+
required variable fails, and the failure names every environment variable that would satisfy it,
|
|
363
|
+
most specific first, which is the message a continuous integration log needs to be useful:
|
|
364
|
+
|
|
365
|
+
```text
|
|
366
|
+
One variable still needs an answer, and there is no terminal to ask on.
|
|
367
|
+
|
|
368
|
+
Set one of the environment variables listed under each variable, or run
|
|
369
|
+
'sous vars ask' from a terminal.
|
|
370
|
+
|
|
371
|
+
apiUrl (workflow/task-files): Where does the API live?
|
|
372
|
+
SOUS_VAR_WORKFLOW_TASK_FILES_API_URL (recipe scope)
|
|
373
|
+
SOUS_VAR_WORKFLOW_API_URL (namespace scope)
|
|
374
|
+
SOUS_VAR_API_URL (shared scope)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Set one of those names as a secret or a variable in your pipeline and the build proceeds. For an
|
|
378
|
+
answer the whole team shares and nothing about it is sensitive, committing it to `.sous/.env` is
|
|
379
|
+
simpler still: a fresh clone then needs no pipeline configuration at all.
|
|
380
|
+
|
|
381
|
+
## Where to go next
|
|
382
|
+
|
|
383
|
+
- [Consuming recipes](repositories-consuming.md): subscribing, building, and what lands where
|
|
384
|
+
- [Authoring a repository](repositories-authoring.md): declaring the definitions this page
|
|
385
|
+
resolves
|
|
386
|
+
- [Variable definitions](repositories-file-formats.md#variable-definitions): the full field table
|
|
387
|
+
- [Command reference](commands.md): every command and flag
|