@ouro.bot/cli 0.1.0-alpha.748 → 0.1.0-alpha.749
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.json
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.749",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Fix Unraid Butler autostart updates through the root-local Docker manager backend with durable rollback and ghost-entry preservation.",
|
|
8
|
+
"Align the packaged Sanctuary template and bundle runtime metadata with alpha.749."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
4
11
|
{
|
|
5
12
|
"version": "0.1.0-alpha.748",
|
|
6
13
|
"changes": [
|
package/deploy/unraid/README.txt
CHANGED
|
@@ -52,12 +52,55 @@ Effective-spec audit helper:
|
|
|
52
52
|
trap - EXIT || return $?
|
|
53
53
|
)
|
|
54
54
|
}
|
|
55
|
-
Define these helpers in the same root shell. Each
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
Define these helpers in the same root shell. Each profile change calls Unraid's
|
|
56
|
+
own root-local Docker manager backend, after proving exact durable identities.
|
|
57
|
+
A missing Butler entry is a no-op when disabling; this avoids the backend's
|
|
58
|
+
false-to-index-zero behavior. The helper preserves every non-Butler row byte
|
|
59
|
+
for byte and restores the complete captured file atomically on any failure:
|
|
60
|
+
butler_autostart_counts() {
|
|
61
|
+
(
|
|
62
|
+
AUTOSTART_FILE=/var/lib/docker/unraid-autostart
|
|
63
|
+
test -f "$AUTOSTART_FILE" || return $?
|
|
64
|
+
awk '
|
|
65
|
+
$1 == "ouro-butler" { production++ }
|
|
66
|
+
$1 == "ouro-butler-staging" { staging++ }
|
|
67
|
+
$1 == "ouro-butler-rollback" { rollback++ }
|
|
68
|
+
$1 == "ouro-butler-legacy-evidence" { legacy++ }
|
|
69
|
+
END { printf "%d %d %d %d", production + 0, staging + 0, rollback + 0, legacy + 0 }
|
|
70
|
+
' "$AUTOSTART_FILE"
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
snapshot_nonbutler_autostart() {
|
|
74
|
+
awk '
|
|
75
|
+
$1 != "ouro-butler" && $1 != "ouro-butler-staging" && $1 != "ouro-butler-rollback" && $1 != "ouro-butler-legacy-evidence" { print }
|
|
76
|
+
' /var/lib/docker/unraid-autostart
|
|
77
|
+
}
|
|
78
|
+
run_unraid_autostart_backend() {
|
|
79
|
+
(
|
|
80
|
+
AUTOSTART_ACTION=$1
|
|
81
|
+
AUTOSTART_CONTAINER=$2
|
|
82
|
+
AUTOSTART_VALUE=$3
|
|
83
|
+
case "$AUTOSTART_ACTION:$AUTOSTART_VALUE" in wait:0|autostart:true|autostart:false) ;; *) return 1 ;; esac
|
|
84
|
+
case "$AUTOSTART_CONTAINER" in
|
|
85
|
+
ouro-butler|ouro-butler-staging|ouro-butler-rollback|ouro-butler-legacy-evidence) ;;
|
|
86
|
+
*) return 1 ;;
|
|
87
|
+
esac
|
|
88
|
+
timeout -s KILL 20 /usr/bin/php -r '
|
|
89
|
+
[$action, $container, $value] = array_slice($argv, 1);
|
|
90
|
+
$allowed = ["ouro-butler", "ouro-butler-staging", "ouro-butler-rollback", "ouro-butler-legacy-evidence"];
|
|
91
|
+
if (!in_array($container, $allowed, true)) exit(2);
|
|
92
|
+
if ($action === "wait" && $value === "0") {
|
|
93
|
+
$_POST = ["action" => "wait", "container" => $container, "wait" => "0"];
|
|
94
|
+
} elseif ($action === "autostart" && ($value === "true" || $value === "false")) {
|
|
95
|
+
$_POST = ["action" => "autostart", "container" => $container, "auto" => $value, "wait" => "0"];
|
|
96
|
+
} else exit(2);
|
|
97
|
+
$_SERVER["DOCUMENT_ROOT"] = "/usr/local/emhttp";
|
|
98
|
+
$_SERVER["REQUEST_URI"] = "docker";
|
|
99
|
+
require "/usr/local/emhttp/plugins/dynamix.docker.manager/include/UpdateConfig.php";
|
|
100
|
+
' "$AUTOSTART_ACTION" "$AUTOSTART_CONTAINER" "$AUTOSTART_VALUE"
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
mutate_butler_autostart() {
|
|
61
104
|
(
|
|
62
105
|
AUTOSTART_CONTAINER=$1
|
|
63
106
|
AUTOSTART_ENABLED=$2
|
|
@@ -66,35 +109,102 @@ Effective-spec audit helper:
|
|
|
66
109
|
*) return 1 ;;
|
|
67
110
|
esac
|
|
68
111
|
case "$AUTOSTART_ENABLED" in true|false) ;; *) return 1 ;; esac
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
test
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
112
|
+
AUTOSTART_COUNT=$(awk -v name="$AUTOSTART_CONTAINER" '$1 == name { count++ } END { print count + 0 }' /var/lib/docker/unraid-autostart) || return $?
|
|
113
|
+
case "$AUTOSTART_COUNT" in 0|1) ;; *) return 1 ;; esac
|
|
114
|
+
if test "$AUTOSTART_ENABLED" = false && test "$AUTOSTART_COUNT" -eq 0; then
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
if test "$AUTOSTART_COUNT" -eq 1; then
|
|
118
|
+
run_unraid_autostart_backend wait "$AUTOSTART_CONTAINER" 0 || return $?
|
|
119
|
+
fi
|
|
120
|
+
if test "$AUTOSTART_ENABLED" = false; then
|
|
121
|
+
run_unraid_autostart_backend autostart "$AUTOSTART_CONTAINER" false || return $?
|
|
122
|
+
AUTOSTART_EXPECTED_COUNT=0
|
|
123
|
+
else
|
|
124
|
+
if test "$AUTOSTART_COUNT" -eq 0; then
|
|
125
|
+
run_unraid_autostart_backend autostart "$AUTOSTART_CONTAINER" true || return $?
|
|
126
|
+
fi
|
|
127
|
+
AUTOSTART_EXPECTED_COUNT=1
|
|
128
|
+
fi
|
|
129
|
+
AUTOSTART_COUNT=$(awk -v name="$AUTOSTART_CONTAINER" '$1 == name { count++ } END { print count + 0 }' /var/lib/docker/unraid-autostart) || return $?
|
|
130
|
+
test "$AUTOSTART_COUNT" -eq "$AUTOSTART_EXPECTED_COUNT" || return $?
|
|
85
131
|
)
|
|
86
132
|
}
|
|
87
|
-
|
|
133
|
+
set_butler_autostart() {
|
|
88
134
|
(
|
|
135
|
+
AUTOSTART_PROFILE=$1
|
|
136
|
+
case "$AUTOSTART_PROFILE" in disabled|production) ;; *) return 1 ;; esac
|
|
137
|
+
test "$(id -u)" -eq 0 || return $?
|
|
89
138
|
AUTOSTART_FILE=/var/lib/docker/unraid-autostart
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
139
|
+
AUTOSTART_INCLUDE=/usr/local/emhttp/plugins/dynamix.docker.manager/include/UpdateConfig.php
|
|
140
|
+
test -f "$AUTOSTART_FILE" && test ! -L "$AUTOSTART_FILE" || return 1
|
|
141
|
+
test "$(stat -c '%u:%g:%a' "$AUTOSTART_FILE")" = 0:0:644 || return $?
|
|
142
|
+
test -f "$AUTOSTART_INCLUDE" && test ! -L "$AUTOSTART_INCLUDE" || return 1
|
|
143
|
+
test "$(stat -c '%u:%g:%a' "$AUTOSTART_INCLUDE")" = 0:0:644 || return $?
|
|
144
|
+
AUTOSTART_COUNTS=$(butler_autostart_counts) || return $?
|
|
145
|
+
set -- $AUTOSTART_COUNTS
|
|
146
|
+
test "$#" -eq 4 || return $?
|
|
147
|
+
for AUTOSTART_COUNT in "$@"; do case "$AUTOSTART_COUNT" in 0|1) ;; *) return 1 ;; esac; done
|
|
148
|
+
if test "$AUTOSTART_PROFILE" = production; then
|
|
149
|
+
docker container inspect ouro-butler >/dev/null 2>&1 || return $?
|
|
150
|
+
fi
|
|
151
|
+
AUTOSTART_BACKUP=$(mktemp /var/lib/docker/.unraid-autostart.ouro.XXXXXX) || return $?
|
|
152
|
+
AUTOSTART_NONBUTLER_BEFORE=$(mktemp /run/unraid-autostart.nonbutler-before.XXXXXX) || { rm -f -- "$AUTOSTART_BACKUP"; return 1; }
|
|
153
|
+
AUTOSTART_NONBUTLER_AFTER=$(mktemp /run/unraid-autostart.nonbutler-after.XXXXXX) || { rm -f -- "$AUTOSTART_BACKUP" "$AUTOSTART_NONBUTLER_BEFORE"; return 1; }
|
|
154
|
+
AUTOSTART_COMMITTED=no
|
|
155
|
+
AUTOSTART_BACKUP_READY=no
|
|
156
|
+
AUTOSTART_RESTORE_TMP=
|
|
157
|
+
autostart_cleanup() {
|
|
158
|
+
AUTOSTART_STATUS=$?
|
|
159
|
+
trap - EXIT HUP INT TERM
|
|
160
|
+
if test "$AUTOSTART_COMMITTED" = yes; then
|
|
161
|
+
rm -f -- "$AUTOSTART_BACKUP" || AUTOSTART_STATUS=1
|
|
162
|
+
elif test "$AUTOSTART_BACKUP_READY" = yes; then
|
|
163
|
+
AUTOSTART_RESTORE_TMP=$(mktemp /var/lib/docker/.unraid-autostart.restore.XXXXXX) || AUTOSTART_RESTORE_TMP=
|
|
164
|
+
if test -n "$AUTOSTART_RESTORE_TMP" \
|
|
165
|
+
&& cp -p -- "$AUTOSTART_BACKUP" "$AUTOSTART_RESTORE_TMP" \
|
|
166
|
+
&& sync -f "$AUTOSTART_RESTORE_TMP" \
|
|
167
|
+
&& mv -f -- "$AUTOSTART_RESTORE_TMP" "$AUTOSTART_FILE" \
|
|
168
|
+
&& sync -f "$AUTOSTART_FILE" \
|
|
169
|
+
&& sync -f /var/lib/docker; then
|
|
170
|
+
rm -f -- "$AUTOSTART_BACKUP" || AUTOSTART_STATUS=1
|
|
171
|
+
else
|
|
172
|
+
test -z "$AUTOSTART_RESTORE_TMP" || rm -f -- "$AUTOSTART_RESTORE_TMP"
|
|
173
|
+
printf 'CRITICAL: Butler autostart rollback failed; recovery copy preserved at %s\n' "$AUTOSTART_BACKUP" >&2
|
|
174
|
+
AUTOSTART_STATUS=1
|
|
175
|
+
fi
|
|
176
|
+
else
|
|
177
|
+
rm -f -- "$AUTOSTART_BACKUP" || AUTOSTART_STATUS=1
|
|
178
|
+
fi
|
|
179
|
+
rm -f -- "$AUTOSTART_NONBUTLER_BEFORE" "$AUTOSTART_NONBUTLER_AFTER" || AUTOSTART_STATUS=1
|
|
180
|
+
exit "$AUTOSTART_STATUS"
|
|
181
|
+
}
|
|
182
|
+
trap autostart_cleanup EXIT
|
|
183
|
+
trap 'exit 129' HUP
|
|
184
|
+
trap 'exit 130' INT
|
|
185
|
+
trap 'exit 143' TERM
|
|
186
|
+
cp -p -- "$AUTOSTART_FILE" "$AUTOSTART_BACKUP" || return $?
|
|
187
|
+
cmp -s -- "$AUTOSTART_FILE" "$AUTOSTART_BACKUP" || return 1
|
|
188
|
+
sync -f "$AUTOSTART_BACKUP" || return $?
|
|
189
|
+
sync -f /var/lib/docker || return $?
|
|
190
|
+
AUTOSTART_BACKUP_READY=yes
|
|
191
|
+
snapshot_nonbutler_autostart >"$AUTOSTART_NONBUTLER_BEFORE" || return $?
|
|
192
|
+
mutate_butler_autostart ouro-butler-staging false || return $?
|
|
193
|
+
mutate_butler_autostart ouro-butler-rollback false || return $?
|
|
194
|
+
mutate_butler_autostart ouro-butler-legacy-evidence false || return $?
|
|
195
|
+
if test "$AUTOSTART_PROFILE" = production; then
|
|
196
|
+
mutate_butler_autostart ouro-butler true || return $?
|
|
197
|
+
AUTOSTART_EXPECTED_COUNTS="1 0 0 0"
|
|
198
|
+
else
|
|
199
|
+
mutate_butler_autostart ouro-butler false || return $?
|
|
200
|
+
AUTOSTART_EXPECTED_COUNTS="0 0 0 0"
|
|
201
|
+
fi
|
|
202
|
+
verify_butler_autostart "$AUTOSTART_EXPECTED_COUNTS" || return $?
|
|
203
|
+
snapshot_nonbutler_autostart >"$AUTOSTART_NONBUTLER_AFTER" || return $?
|
|
204
|
+
cmp -s -- "$AUTOSTART_NONBUTLER_BEFORE" "$AUTOSTART_NONBUTLER_AFTER" || return 1
|
|
205
|
+
sync -f "$AUTOSTART_FILE" || return $?
|
|
206
|
+
sync -f /var/lib/docker || return $?
|
|
207
|
+
AUTOSTART_COMMITTED=yes
|
|
98
208
|
)
|
|
99
209
|
}
|
|
100
210
|
verify_butler_autostart() {
|
|
@@ -105,17 +215,11 @@ Effective-spec audit helper:
|
|
|
105
215
|
)
|
|
106
216
|
}
|
|
107
217
|
disable_butler_autostart() {
|
|
108
|
-
set_butler_autostart
|
|
109
|
-
set_butler_autostart ouro-butler-rollback false || return $?
|
|
110
|
-
set_butler_autostart ouro-butler-legacy-evidence false || return $?
|
|
111
|
-
set_butler_autostart ouro-butler false || return $?
|
|
218
|
+
set_butler_autostart disabled || return $?
|
|
112
219
|
verify_butler_autostart "0 0 0 0" || return $?
|
|
113
220
|
}
|
|
114
221
|
enable_butler_autostart() {
|
|
115
|
-
set_butler_autostart
|
|
116
|
-
set_butler_autostart ouro-butler-rollback false || return $?
|
|
117
|
-
set_butler_autostart ouro-butler-legacy-evidence false || return $?
|
|
118
|
-
set_butler_autostart ouro-butler true || return $?
|
|
222
|
+
set_butler_autostart production || return $?
|
|
119
223
|
verify_butler_autostart "1 0 0 0" || return $?
|
|
120
224
|
}
|
|
121
225
|
This bounded wait accepts only Docker's healthy state. The image healthcheck
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0"?>
|
|
2
2
|
<Container version="2">
|
|
3
3
|
<Name>Mendelow Cloud Butler</Name>
|
|
4
|
-
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.
|
|
4
|
+
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.749</Repository>
|
|
5
5
|
<Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
|
|
6
6
|
<Network>host</Network>
|
|
7
7
|
<Shell>sh</Shell>
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouro.bot/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.749",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@ouro.bot/cli",
|
|
9
|
-
"version": "0.1.0-alpha.
|
|
9
|
+
"version": "0.1.0-alpha.749",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|