valise-sh 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/CHANGELOG.md +170 -9
- package/README.md +48 -24
- package/bin/valise +2453 -333
- package/docs/architecture.md +78 -9
- package/docs/contrib-modules.md +68 -15
- package/docs/installation.md +120 -33
- package/docs/module-abi.md +103 -39
- package/docs/release-policy.md +110 -6
- package/docs/shared-modules.md +124 -2
- package/docs/variants.md +318 -54
- package/examples/README.md +11 -0
- package/examples/e2e/README.md +7 -7
- package/examples/e2e/build-manifest.sh +45 -157
- package/examples/profile-project/README.md +181 -0
- package/examples/profile-project/shell/layers/demo/module.d/contrib_demo_greeting.meta +10 -0
- package/examples/profile-project/shell/layers/demo/modules/shared/contrib_demo_greeting.sh +4 -0
- package/examples/profile-project/shell/module.d/greeting.meta +10 -0
- package/examples/profile-project/shell/module.d/profile_main.meta +9 -0
- package/examples/profile-project/shell/modules/greeting.sh +5 -0
- package/examples/profile-project/shell/release/bundle-roots +9 -0
- package/examples/profile-project/shell/release/install-variants +3 -0
- package/examples/profile-project/shell/release/module-registry.tsv +4 -0
- package/examples/profile-project/shell/release/project.conf +3 -0
- package/examples/shared/README.md +2 -2
- package/lib/compiler.awk +341 -20
- package/lib/fish/loader.fish +94 -19
- package/lib/fish/metadata.fish +13 -14
- package/lib/loader.sh +737 -157
- package/lib/metadata.sh +27 -51
- package/package.json +2 -1
|
@@ -3,63 +3,29 @@
|
|
|
3
3
|
# Copyright (c) 2026 Joseph Cumines
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
-
# build-manifest.sh: vendor engine files into
|
|
6
|
+
# build-manifest.sh: vendor engine files into an e2e release tree and
|
|
7
7
|
# generate a profile-release.manifest with correct sizes and SHA-256 digests.
|
|
8
8
|
#
|
|
9
|
-
# Usage:
|
|
10
|
-
#
|
|
9
|
+
# Usage: sh build-manifest.sh [output-dir]
|
|
10
|
+
# Default output-dir: examples/e2e/build/release
|
|
11
11
|
|
|
12
12
|
set -eu
|
|
13
13
|
|
|
14
14
|
_script_dir=$(cd "$(dirname "$0")" && pwd -P)
|
|
15
15
|
_repo_root=$(cd "$_script_dir/../.." && pwd -P)
|
|
16
16
|
_e2e_root="$_script_dir"
|
|
17
|
+
_out_dir="${1:-$_e2e_root/build/release}"
|
|
18
|
+
_valise="$_repo_root/bin/valise"
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
# Match bin/valise fallback chain: sha256sum, shasum -a 256, sha256 (BSD).
|
|
20
|
-
_sha_cmd=""
|
|
21
|
-
if command -v sha256sum >/dev/null 2>&1; then
|
|
22
|
-
_sha_cmd="sha256sum"
|
|
23
|
-
elif command -v shasum >/dev/null 2>&1; then
|
|
24
|
-
_sha_cmd="shasum"
|
|
25
|
-
elif command -v sha256 >/dev/null 2>&1; then
|
|
26
|
-
_sha_cmd="sha256"
|
|
27
|
-
else
|
|
28
|
-
printf 'ERROR: no SHA-256 utility found (need sha256sum, shasum, or sha256)\n' >&2
|
|
29
|
-
exit 1
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
file_sha256() {
|
|
33
|
-
_sha_output=""
|
|
34
|
-
if [ "$_sha_cmd" = "sha256sum" ]; then
|
|
35
|
-
_sha_output=$(sha256sum "$1")
|
|
36
|
-
elif [ "$_sha_cmd" = "shasum" ]; then
|
|
37
|
-
_sha_output=$(shasum -a 256 "$1")
|
|
38
|
-
else
|
|
39
|
-
_sha_output=$(sha256 "$1")
|
|
40
|
-
fi
|
|
41
|
-
# BSD sha256 prints "SHA256 (filename) = digest"; sha256sum/shasum print
|
|
42
|
-
# "digest filename". Gate the BSD strip behind the SHA256 ( prefix to
|
|
43
|
-
# avoid corrupting output when the filename contains "= ".
|
|
44
|
-
case "$_sha_output" in
|
|
45
|
-
"SHA256 ("*) _sha_output=${_sha_output##* = } ;;
|
|
46
|
-
esac
|
|
47
|
-
_sha_output=${_sha_output%% *}
|
|
48
|
-
_sha_output=${_sha_output%%$(printf '\t')*}
|
|
49
|
-
printf '%s\n' "$_sha_output"
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
file_bytes() {
|
|
53
|
-
wc -c < "$1" | tr -d '[:space:]'
|
|
54
|
-
}
|
|
20
|
+
[ -x "$_valise" ] || { printf 'ERROR: valise CLI not found at %s\n' "$_valise" >&2; exit 1; }
|
|
55
21
|
|
|
56
|
-
#
|
|
57
|
-
|
|
58
|
-
|
|
22
|
+
# Prepare clean output directory
|
|
23
|
+
rm -rf "$_out_dir"
|
|
24
|
+
mkdir -p "$_out_dir"
|
|
59
25
|
|
|
60
26
|
_vendor_copy() {
|
|
61
27
|
_src="$_repo_root/$1"
|
|
62
|
-
_dst="$
|
|
28
|
+
_dst="$_out_dir/$1"
|
|
63
29
|
_dst_dir=$(dirname "$_dst")
|
|
64
30
|
[ -f "$_src" ] || { printf 'ERROR: engine source missing: %s\n' "$_src" >&2; exit 1; }
|
|
65
31
|
mkdir -p "$_dst_dir"
|
|
@@ -67,7 +33,7 @@ _vendor_copy() {
|
|
|
67
33
|
chmod 0644 "$_dst"
|
|
68
34
|
}
|
|
69
35
|
|
|
70
|
-
printf 'Vendoring engine files
|
|
36
|
+
printf 'Vendoring engine files into %s...\n' "$_out_dir"
|
|
71
37
|
|
|
72
38
|
# Core libraries
|
|
73
39
|
_vendor_copy lib/metadata.sh
|
|
@@ -79,8 +45,7 @@ _vendor_copy lib/compiler.awk
|
|
|
79
45
|
_vendor_copy lib/fish/loader.fish
|
|
80
46
|
_vendor_copy lib/fish/metadata.fish
|
|
81
47
|
|
|
82
|
-
# Generic Fish entrypoint adapter
|
|
83
|
-
# integration after it authenticates the active release)
|
|
48
|
+
# Generic Fish entrypoint adapter
|
|
84
49
|
_vendor_copy entrypoints/fish/profile.fish
|
|
85
50
|
|
|
86
51
|
# Entrypoint
|
|
@@ -115,14 +80,37 @@ if [ "$_engine_contrib_count" -eq 0 ]; then
|
|
|
115
80
|
exit 1
|
|
116
81
|
fi
|
|
117
82
|
|
|
118
|
-
# ---
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
83
|
+
# --- Native e2e example modules ---
|
|
84
|
+
_e2e_meta_count=0
|
|
85
|
+
mkdir -p "$_out_dir/module.d"
|
|
86
|
+
for _meta in "$_e2e_root"/module.d/e2e_*.meta; do
|
|
87
|
+
[ -f "$_meta" ] || continue
|
|
88
|
+
cp "$_meta" "$_out_dir/module.d/"
|
|
89
|
+
chmod 0644 "$_out_dir/module.d/$(basename "$_meta")"
|
|
90
|
+
_e2e_meta_count=$((_e2e_meta_count + 1))
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
_e2e_body_count=0
|
|
94
|
+
mkdir -p "$_out_dir/modules/e2e"
|
|
95
|
+
for _body in "$_e2e_root"/modules/e2e/*.sh "$_e2e_root"/modules/e2e/*.fish; do
|
|
96
|
+
[ -f "$_body" ] || continue
|
|
97
|
+
cp "$_body" "$_out_dir/modules/e2e/"
|
|
98
|
+
chmod 0644 "$_out_dir/modules/e2e/$(basename "$_body")"
|
|
99
|
+
_e2e_body_count=$((_e2e_body_count + 1))
|
|
100
|
+
done
|
|
123
101
|
|
|
102
|
+
if [ "$_e2e_meta_count" -eq 0 ]; then
|
|
103
|
+
printf 'ERROR: no e2e module metadata found in %s\n' "$_e2e_root/module.d" >&2
|
|
104
|
+
exit 1
|
|
105
|
+
fi
|
|
106
|
+
if [ "$_e2e_body_count" -eq 0 ]; then
|
|
107
|
+
printf 'ERROR: no e2e module bodies found in %s\n' "$_e2e_root/modules/e2e" >&2
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# --- Vendor shared layer (cross-repo composition) ---
|
|
124
112
|
_shared_src="$_repo_root/examples/shared"
|
|
125
|
-
_shared_dst="$
|
|
113
|
+
_shared_dst="$_out_dir/layer/shared"
|
|
126
114
|
[ -d "$_shared_src/module.d" ] || { printf 'ERROR: shared provider missing: %s\n' "$_shared_src" >&2; exit 1; }
|
|
127
115
|
mkdir -p "$_shared_dst/module.d" "$_shared_dst/modules"
|
|
128
116
|
for _shared_meta in "$_shared_src"/module.d/*.meta; do
|
|
@@ -142,109 +130,9 @@ done
|
|
|
142
130
|
_shared_rev=$(cd "$_shared_src" && git rev-parse HEAD 2>/dev/null || printf 'unknown')
|
|
143
131
|
printf 'provider=examples/shared\nrevision=%s\n' "$_shared_rev" > "$_shared_dst/layer-pin.txt"
|
|
144
132
|
chmod 0644 "$_shared_dst/layer-pin.txt"
|
|
145
|
-
printf 'Vendored shared layer from %s (revision %s)\n' "$_shared_src" "$_shared_rev"
|
|
146
|
-
|
|
147
|
-
# --- Generate manifest ---
|
|
148
|
-
_manifest_dir="$_e2e_root/shell/install"
|
|
149
|
-
mkdir -p "$_manifest_dir"
|
|
150
|
-
_manifest="$_manifest_dir/profile-release.manifest"
|
|
151
|
-
|
|
152
|
-
printf 'Generating manifest...\n'
|
|
153
|
-
|
|
154
|
-
# Collect all files to include in the manifest.
|
|
155
|
-
# Engine files (vendored) + e2e example modules (native).
|
|
156
|
-
_file_list=""
|
|
157
|
-
|
|
158
|
-
# Engine files
|
|
159
|
-
for _f in \
|
|
160
|
-
lib/metadata.sh lib/loader.sh lib/capabilities.sh lib/compiler.awk \
|
|
161
|
-
lib/fish/loader.fish lib/fish/metadata.fish \
|
|
162
|
-
entrypoints/profile.sh entrypoints/fish/profile.fish \
|
|
163
|
-
module.d/platform_posix.meta module.d/platform_macos.meta \
|
|
164
|
-
module.d/platform_linux.meta module.d/platform_bsd.meta \
|
|
165
|
-
modules/platform/posix.sh \
|
|
166
|
-
modules/platform/macos/capabilities.sh \
|
|
167
|
-
modules/platform/linux/capabilities.sh \
|
|
168
|
-
modules/platform/bsd/capabilities.sh \
|
|
169
|
-
; do
|
|
170
|
-
_file_list="$_file_list $_f"
|
|
171
|
-
done
|
|
172
133
|
|
|
173
|
-
#
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
# Shareable engine catalog (vendored above)
|
|
177
|
-
for _f in "$_e2e_root"/module.d/contrib_*.meta "$_e2e_root"/modules/system/contrib_*.sh; do
|
|
178
|
-
[ -f "$_f" ] || continue
|
|
179
|
-
_rel=${_f#"$_e2e_root"/}
|
|
180
|
-
_file_list="$_file_list $_rel"
|
|
181
|
-
done
|
|
182
|
-
for _f in "$_e2e_root"/module.d/e2e_*.meta; do
|
|
183
|
-
[ -f "$_f" ] || continue
|
|
184
|
-
_rel=${_f#"$_e2e_root"/}
|
|
185
|
-
_file_list="$_file_list $_rel"
|
|
186
|
-
_e2e_meta_count=$((_e2e_meta_count + 1))
|
|
187
|
-
done
|
|
188
|
-
|
|
189
|
-
# E2e example module bodies (POSIX)
|
|
190
|
-
_e2e_sh_count=0
|
|
191
|
-
for _f in "$_e2e_root"/modules/e2e/*.sh; do
|
|
192
|
-
[ -f "$_f" ] || continue
|
|
193
|
-
_rel=${_f#"$_e2e_root"/}
|
|
194
|
-
_file_list="$_file_list $_rel"
|
|
195
|
-
_e2e_sh_count=$((_e2e_sh_count + 1))
|
|
196
|
-
done
|
|
197
|
-
|
|
198
|
-
# E2e example module bodies (Fish)
|
|
199
|
-
_e2e_fish_count=0
|
|
200
|
-
for _f in "$_e2e_root"/modules/e2e/*.fish; do
|
|
201
|
-
[ -f "$_f" ] || continue
|
|
202
|
-
_rel=${_f#"$_e2e_root"/}
|
|
203
|
-
_file_list="$_file_list $_rel"
|
|
204
|
-
_e2e_fish_count=$((_e2e_fish_count + 1))
|
|
205
|
-
done
|
|
206
|
-
|
|
207
|
-
# Shared layer files (cross-repo composition): provider metadata, bodies,
|
|
208
|
-
# and the pin file recording the vendored revision.
|
|
209
|
-
_shared_count=0
|
|
210
|
-
for _f in "$_e2e_root"/layer/shared/module.d/*.meta "$_e2e_root"/layer/shared/modules/*/*.sh "$_e2e_root"/layer/shared/layer-pin.txt; do
|
|
211
|
-
[ -f "$_f" ] || continue
|
|
212
|
-
_rel=${_f#"$_e2e_root"/}
|
|
213
|
-
_file_list="$_file_list $_rel"
|
|
214
|
-
_shared_count=$((_shared_count + 1))
|
|
215
|
-
done
|
|
216
|
-
|
|
217
|
-
# Fail closed when a glob collected nothing: POSIX sh leaves a non-matching
|
|
218
|
-
# glob unexpanded, so without this an empty or missing e2e directory would
|
|
219
|
-
# build a manifest silently missing e2e files.
|
|
220
|
-
if [ "$_e2e_meta_count" -eq 0 ]; then
|
|
221
|
-
printf 'ERROR: no e2e module metadata found in %s\n' "$_e2e_root/module.d" >&2
|
|
222
|
-
exit 1
|
|
223
|
-
fi
|
|
224
|
-
if [ "$((_e2e_sh_count + _e2e_fish_count))" -eq 0 ]; then
|
|
225
|
-
printf 'ERROR: no e2e module bodies found in %s\n' "$_e2e_root/modules/e2e" >&2
|
|
226
|
-
exit 1
|
|
227
|
-
fi
|
|
228
|
-
if [ "$_shared_count" -eq 0 ]; then
|
|
229
|
-
printf 'ERROR: no shared layer files found in %s\n' "$_e2e_root/layer/shared" >&2
|
|
230
|
-
exit 1
|
|
231
|
-
fi
|
|
232
|
-
|
|
233
|
-
# Write manifest header
|
|
234
|
-
printf 'shell-profile-release-manifest-v1\n' > "$_manifest"
|
|
235
|
-
printf 'destination\tsource\tsource_mode\tinstall_mode\tbytes\tsha256\n' >> "$_manifest"
|
|
236
|
-
|
|
237
|
-
# Write data rows
|
|
238
|
-
for _rel in $_file_list; do
|
|
239
|
-
_full="$_e2e_root/$_rel"
|
|
240
|
-
[ -f "$_full" ] || { printf 'ERROR: file missing: %s\n' "$_full" >&2; exit 1; }
|
|
241
|
-
[ ! -L "$_full" ] || { printf 'ERROR: symlink in release: %s\n' "$_full" >&2; exit 1; }
|
|
242
|
-
_bytes=$(file_bytes "$_full")
|
|
243
|
-
_sha=$(file_sha256 "$_full")
|
|
244
|
-
# destination == source for this flat release layout
|
|
245
|
-
# All release files are 0644 source -> 0444 installed (immutable)
|
|
246
|
-
printf '%s\t%s\t0644\t0444\t%s\t%s\n' "$_rel" "$_rel" "$_bytes" "$_sha" >> "$_manifest"
|
|
247
|
-
done
|
|
134
|
+
# Normalise file modes before manifesting
|
|
135
|
+
find "$_out_dir" -type f -exec chmod 0644 {} +
|
|
248
136
|
|
|
249
|
-
|
|
250
|
-
|
|
137
|
+
# --- Generate manifest using valise CLI ---
|
|
138
|
+
"$_valise" make-manifest "$_out_dir"
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# profile-project: a complete valise project
|
|
2
|
+
|
|
3
|
+
This is a small but complete consuming project. It shows every piece a
|
|
4
|
+
profile project needs: metadata that describes the modules, module bodies,
|
|
5
|
+
a provider layer contributed by somebody else, a bundle that says which
|
|
6
|
+
roots load, a variant that says what to leave out, and project defaults.
|
|
7
|
+
|
|
8
|
+
Everything here is plain text. There is no build script and no hand-written
|
|
9
|
+
registry. `valise` reads the metadata and generates what it needs.
|
|
10
|
+
|
|
11
|
+
## What is in it
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
shell/
|
|
15
|
+
module.d/ the project's own modules
|
|
16
|
+
profile_main.meta the entry module
|
|
17
|
+
greeting.meta a dependency of profile_main
|
|
18
|
+
modules/ the bodies of those modules
|
|
19
|
+
greeting.sh
|
|
20
|
+
layers/demo/ a provider layer
|
|
21
|
+
module.d/contrib_demo_greeting.meta
|
|
22
|
+
modules/shared/contrib_demo_greeting.sh
|
|
23
|
+
release/
|
|
24
|
+
bundle-roots which roots load, per shell
|
|
25
|
+
install-variants named exclusion sets
|
|
26
|
+
project.conf defaults for build and apply
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`profile_main` is a meta module: it has `requires=greeting` and no body of
|
|
30
|
+
its own, so there is no `modules/profile_main.sh`. It exists only to name
|
|
31
|
+
what the project loads. `greeting` is an ordinary module that defines
|
|
32
|
+
`greet`.
|
|
33
|
+
|
|
34
|
+
The layer under `shell/layers/demo/` is a provider layer. Its module is
|
|
35
|
+
named `contrib_demo_greeting`, following the `contrib_<owner>_<thing>`
|
|
36
|
+
convention, and its body lives under `layers/demo/` in the installed
|
|
37
|
+
release, so it never collides with the project's own modules.
|
|
38
|
+
|
|
39
|
+
## Build it
|
|
40
|
+
|
|
41
|
+
From this directory:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
valise build
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
That compiles a plan for each supported shell and writes a release under
|
|
48
|
+
`build/release/`. The release contains:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
build/release/
|
|
52
|
+
generated/installed-modules.bash compiled plan for bash
|
|
53
|
+
generated/installed-modules.zsh compiled plan for zsh
|
|
54
|
+
generated/installed-modules.ksh compiled plan for ksh
|
|
55
|
+
vendor/shell-profile/lib/capabilities.sh
|
|
56
|
+
module.d/ the project's metadata
|
|
57
|
+
modules/ the project's bodies
|
|
58
|
+
layers/demo/module.d/ the layer's metadata
|
|
59
|
+
layers/demo/modules/shared/ the layer's bodies
|
|
60
|
+
shell/release/ registry, bundle, variants, defaults
|
|
61
|
+
shell/install/profile-release.manifest
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The plans are plain POSIX shell. You can read one to see exactly what will
|
|
65
|
+
run.
|
|
66
|
+
|
|
67
|
+
## Load it
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
valise apply
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`apply` builds the release, installs it under your XDG data directory, and
|
|
74
|
+
writes a managed block into the startup files your shells read. It prints
|
|
75
|
+
what it changed and where.
|
|
76
|
+
|
|
77
|
+
The managed block is guarded by a source-once variable, so your login shell
|
|
78
|
+
loads the profile exactly once. It prefers the compiled plan for your shell
|
|
79
|
+
and falls back to the loader if the release has no compiled plan.
|
|
80
|
+
|
|
81
|
+
zsh does not read `~/.profile` on its own, so when zsh is present `apply`
|
|
82
|
+
writes the same managed block to `~/.zprofile`. bash reads `~/.profile` only
|
|
83
|
+
when no `~/.bash_profile` exists; `apply` never creates one, so it does not
|
|
84
|
+
shadow your `~/.profile`.
|
|
85
|
+
|
|
86
|
+
Now open a new login shell:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
bash -l
|
|
90
|
+
greet
|
|
91
|
+
# hello from the valise profile project
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The same works in zsh and ksh. It does not work in dash: the plans are
|
|
95
|
+
compiled for bash, zsh and ksh, and dash is not one of them.
|
|
96
|
+
|
|
97
|
+
To undo it, remove the managed block from every startup file `apply`
|
|
98
|
+
reported.
|
|
99
|
+
|
|
100
|
+
To check the current state:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
valise status
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
project: /path/to/profile-project
|
|
108
|
+
variant: default
|
|
109
|
+
bundle: default
|
|
110
|
+
integration: /home/you/.profile: managed block present
|
|
111
|
+
integration: /home/you/.zprofile: managed block present
|
|
112
|
+
registry: up to date
|
|
113
|
+
active release: 0a723dcb0860bcae3ea259c631aaa76ce8e0b4e6991448979018c1d08fc35802
|
|
114
|
+
build output: /path/to/profile-project/build/release
|
|
115
|
+
drift: active release matches build output
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`status` reports the active release, the startup files, and whether the
|
|
119
|
+
installed release still matches what the project would build. If you edit a
|
|
120
|
+
module and re-apply, the release changes and the drift line tells you the
|
|
121
|
+
active release is no longer the one you built.
|
|
122
|
+
|
|
123
|
+
## Try a variant
|
|
124
|
+
|
|
125
|
+
The project ships two variants. `default` loads everything;
|
|
126
|
+
`workstation-lean` leaves out the provider layer:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
valise explain-variant workstation-lean
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
To use the lean variant, set it in `shell/release/project.conf`:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
variant=workstation-lean
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Then re-apply. The `contrib_demo_greeting` module disappears from the plan
|
|
139
|
+
and the rest still loads.
|
|
140
|
+
|
|
141
|
+
An exclusion that removes a module something else still depends on is an
|
|
142
|
+
error, not a silent surprise:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
ERROR: variant exclusion breaks a required dependency: profile_main requires contrib_demo_greeting
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Try a bundle
|
|
149
|
+
|
|
150
|
+
`shell/release/bundle-roots` says which roots load for each shell:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
default bash profile_main contrib_demo_greeting@shell/layers/demo/module.d
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The first root is a bare name, meaning a module from the project's own
|
|
157
|
+
`shell/module.d/`. The second is qualified with its source, so it is
|
|
158
|
+
unambiguous even though it lives in a layer.
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
valise explain-bundles
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Check the layer
|
|
165
|
+
|
|
166
|
+
A provider layer has rules: the `contrib_` prefix, a version, a body that
|
|
167
|
+
exists, and no dependency that escapes the layer.
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
valise layer-lint demo
|
|
171
|
+
# layer demo: 1 module(s) validated
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Where to go next
|
|
175
|
+
|
|
176
|
+
- [The module ABI](../../docs/module-abi.md) — every metadata field.
|
|
177
|
+
- [The authoring guide](../../docs/contrib-modules.md) — writing modules.
|
|
178
|
+
- [The compile and build contract](../../docs/variants.md) — the registry,
|
|
179
|
+
bundles, variants, and what a compiled plan contains.
|
|
180
|
+
- [Shared modules](../../docs/shared-modules.md) — how layer modules are
|
|
181
|
+
named and owned.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# bundle shell roots
|
|
2
|
+
# The first row is a header, not a bundle definition. Each row names a
|
|
3
|
+
# bundle, a shell, and the space-separated root modules for that shell.
|
|
4
|
+
#
|
|
5
|
+
# A layer module is named by its qualified identity so the source directory
|
|
6
|
+
# is unambiguous: name@shell/layers/<provider>/module.d
|
|
7
|
+
default bash profile_main contrib_demo_greeting@shell/layers/demo/module.d
|
|
8
|
+
default zsh profile_main contrib_demo_greeting@shell/layers/demo/module.d
|
|
9
|
+
default ksh profile_main contrib_demo_greeting@shell/layers/demo/module.d
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
name version side_effect requires optional shells platforms exports load updates source
|
|
2
|
+
greeting 1.0.0 read-only sh bash zsh ksh any greet modules/greeting.sh shell/module.d
|
|
3
|
+
profile_main 1.0.0 read-only greeting bash zsh ksh any shell/module.d
|
|
4
|
+
contrib_demo_greeting 1.0.0 read-only sh bash zsh ksh any contrib_demo_greeting_ready modules/shared/contrib_demo_greeting.sh shell/layers/demo/module.d
|
|
@@ -26,9 +26,9 @@ level README).
|
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
28
|
sh examples/e2e/build-manifest.sh
|
|
29
|
-
cd examples/e2e
|
|
29
|
+
cd examples/e2e/build/release
|
|
30
30
|
valise install
|
|
31
|
-
valise verify
|
|
31
|
+
valise release verify
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Then load the shared modules from a POSIX shell. The active release path
|