@humanu/orchestra 0.5.22 → 0.5.23
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/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
###############################################################################
|
|
4
|
+
# copy_env.sh – Shared helpers for copying .env/config files into worktrees
|
|
5
|
+
# ---------------------------------------------------------------------------
|
|
6
|
+
# Provides reusable functions consumed by commands.sh, gw-bridge.sh, and any
|
|
7
|
+
# other shell entry point. Adds structured logging so we can troubleshoot which
|
|
8
|
+
# files were selected and whether individual copy operations succeeded.
|
|
9
|
+
###############################################################################
|
|
10
|
+
|
|
11
|
+
# Global variables populated by copy_env_files
|
|
12
|
+
COPY_ENV_LAST_COPIED=0
|
|
13
|
+
COPY_ENV_LAST_TARGET=""
|
|
14
|
+
COPY_ENV_LOG_FILE=""
|
|
15
|
+
|
|
16
|
+
# Internal: write a log line (timestamped). Respects COPY_ENV_VERBOSE: if set to
|
|
17
|
+
# 1, the message is also echoed to stderr for real-time debugging.
|
|
18
|
+
copy_env_log() {
|
|
19
|
+
local level="$1"
|
|
20
|
+
shift
|
|
21
|
+
local message="$*"
|
|
22
|
+
local timestamp
|
|
23
|
+
timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
24
|
+
if [[ -n "$COPY_ENV_LOG_FILE" ]]; then
|
|
25
|
+
if ! printf '%s [%s] %s\n' "$timestamp" "$level" "$message" >>"$COPY_ENV_LOG_FILE" 2>/dev/null; then
|
|
26
|
+
# If we cannot write to the configured log file, drop logging to disk
|
|
27
|
+
COPY_ENV_LOG_FILE=""
|
|
28
|
+
fi
|
|
29
|
+
fi
|
|
30
|
+
if [[ ${COPY_ENV_VERBOSE:-0} -eq 1 ]]; then
|
|
31
|
+
printf '[copy-env][%s] %s\n' "$level" "$message" >&2
|
|
32
|
+
fi
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Determine which locations to copy by reading <repo>/.orchestra/options.json.
|
|
36
|
+
copy_env_load_locations() {
|
|
37
|
+
local repo_root="$1"
|
|
38
|
+
local config_file="$repo_root/.orchestra/options.json"
|
|
39
|
+
|
|
40
|
+
if [[ -f "$config_file" ]]; then
|
|
41
|
+
if command -v jq >/dev/null 2>&1; then
|
|
42
|
+
jq -r '(.copy_locations // ["/"])[]' "$config_file" 2>/dev/null || printf '/\n'
|
|
43
|
+
return
|
|
44
|
+
elif command -v python3 >/dev/null 2>&1; then
|
|
45
|
+
python3 - "$config_file" <<'PY'
|
|
46
|
+
import json
|
|
47
|
+
import sys
|
|
48
|
+
from pathlib import Path
|
|
49
|
+
|
|
50
|
+
config_path = Path(sys.argv[1])
|
|
51
|
+
try:
|
|
52
|
+
data = json.loads(config_path.read_text())
|
|
53
|
+
except Exception:
|
|
54
|
+
data = {}
|
|
55
|
+
locations = data.get("copy_locations")
|
|
56
|
+
if isinstance(locations, list) and locations:
|
|
57
|
+
for entry in locations:
|
|
58
|
+
if isinstance(entry, str):
|
|
59
|
+
print(entry)
|
|
60
|
+
else:
|
|
61
|
+
print("/")
|
|
62
|
+
PY
|
|
63
|
+
return
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
# Fallback: default to repo root
|
|
67
|
+
printf '/\n'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Copy .env files from the source worktree into the target worktree.
|
|
71
|
+
# Arguments:
|
|
72
|
+
# $1 - source root (worktree we are copying from)
|
|
73
|
+
# $2 - target root (new or existing worktree)
|
|
74
|
+
# $3 - repository shared root (defaults to source root)
|
|
75
|
+
# $4 - quiet flag (1 suppresses user-facing echo output)
|
|
76
|
+
copy_env_files() {
|
|
77
|
+
local source_root="$1"
|
|
78
|
+
local target_root="$2"
|
|
79
|
+
local repo_root="${3:-$source_root}"
|
|
80
|
+
local quiet="${4:-0}"
|
|
81
|
+
|
|
82
|
+
COPY_ENV_LAST_COPIED=0
|
|
83
|
+
COPY_ENV_LAST_TARGET="$target_root"
|
|
84
|
+
|
|
85
|
+
local enable_logs=${COPY_ENV_ENABLE_LOG:-0}
|
|
86
|
+
local log_file="${COPY_ENV_LOG_FILE:-}"
|
|
87
|
+
local log_dir="${COPY_ENV_LOG_DIR:-}"
|
|
88
|
+
|
|
89
|
+
if [[ -n "$log_file" ]]; then
|
|
90
|
+
mkdir -p "$(dirname "$log_file")" 2>/dev/null || true
|
|
91
|
+
COPY_ENV_LOG_FILE="$log_file"
|
|
92
|
+
elif [[ $enable_logs -eq 1 || -n "$log_dir" ]]; then
|
|
93
|
+
log_dir="${log_dir:-$repo_root/.orchestra/logs}"
|
|
94
|
+
mkdir -p "$log_dir" 2>/dev/null || true
|
|
95
|
+
COPY_ENV_LOG_FILE="$log_dir/copy-env.log"
|
|
96
|
+
else
|
|
97
|
+
COPY_ENV_LOG_FILE=""
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
copy_env_log "INFO" "Starting copy (source=$source_root, target=$target_root, repo=$repo_root)"
|
|
101
|
+
|
|
102
|
+
local override_locations="${COPY_ENV_OVERRIDE_LOCATIONS:-}"
|
|
103
|
+
unset COPY_ENV_OVERRIDE_LOCATIONS
|
|
104
|
+
local locations=()
|
|
105
|
+
if [[ -n "$override_locations" ]]; then
|
|
106
|
+
while IFS= read -r line; do
|
|
107
|
+
[[ -z "$line" ]] && continue
|
|
108
|
+
locations+=("$line")
|
|
109
|
+
done <<<"$override_locations"
|
|
110
|
+
else
|
|
111
|
+
while IFS= read -r line; do
|
|
112
|
+
[[ -z "$line" ]] && continue
|
|
113
|
+
locations+=("$line")
|
|
114
|
+
done < <(copy_env_load_locations "$repo_root")
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
if [[ ${#locations[@]} -eq 0 ]]; then
|
|
118
|
+
locations=("/")
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
local bases=("$source_root")
|
|
122
|
+
if [[ -n "$repo_root" && "$repo_root" != "$source_root" ]]; then
|
|
123
|
+
bases+=("$repo_root")
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
local overall_copied=0
|
|
127
|
+
local overall_failed=0
|
|
128
|
+
|
|
129
|
+
(( quiet != 1 )) && echo "🔧 Copying .env files to worktree..."
|
|
130
|
+
|
|
131
|
+
for raw_location in "${locations[@]}"; do
|
|
132
|
+
local trimmed
|
|
133
|
+
trimmed="$(printf '%s' "$raw_location" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
134
|
+
[[ -z "$trimmed" ]] && continue
|
|
135
|
+
|
|
136
|
+
local rel="${trimmed#/}"
|
|
137
|
+
rel="${rel#./}"
|
|
138
|
+
|
|
139
|
+
local location_copied=0
|
|
140
|
+
local location_failed=0
|
|
141
|
+
|
|
142
|
+
for base in "${bases[@]}"; do
|
|
143
|
+
[[ -z "$base" ]] && continue
|
|
144
|
+
|
|
145
|
+
copy_env_log "DEBUG" "Checking location '$trimmed' in base '$base'"
|
|
146
|
+
|
|
147
|
+
if [[ "$trimmed" == "/" ]]; then
|
|
148
|
+
local found_root=0
|
|
149
|
+
for env_file in "$base"/.env*; do
|
|
150
|
+
[[ -f "$env_file" ]] || continue
|
|
151
|
+
mkdir -p "$target_root"
|
|
152
|
+
local err_msg
|
|
153
|
+
err_msg="$(cp "$env_file" "$target_root/$(basename "$env_file")" 2>&1)"
|
|
154
|
+
if [[ $? -eq 0 ]]; then
|
|
155
|
+
(( overall_copied++ ))
|
|
156
|
+
location_copied=1
|
|
157
|
+
found_root=1
|
|
158
|
+
(( quiet != 1 )) && echo " ✅ Copied $(basename "$env_file") from $base/"
|
|
159
|
+
copy_env_log "INFO" "Copied $(basename "$env_file") from $base/"
|
|
160
|
+
else
|
|
161
|
+
(( overall_failed++ ))
|
|
162
|
+
(( location_failed++ ))
|
|
163
|
+
(( quiet != 1 )) && echo " ❌ Failed to copy $(basename "$env_file") from $base/"
|
|
164
|
+
copy_env_log "ERROR" "Failed to copy $(basename "$env_file") from $base/: ${err_msg:-unknown error}"
|
|
165
|
+
fi
|
|
166
|
+
done
|
|
167
|
+
if [[ $found_root -eq 1 ]]; then
|
|
168
|
+
break
|
|
169
|
+
fi
|
|
170
|
+
else
|
|
171
|
+
local source_path="$base/$rel"
|
|
172
|
+
if [[ -d "$source_path" ]]; then
|
|
173
|
+
local dest_dir="$target_root/$rel"
|
|
174
|
+
mkdir -p "$dest_dir"
|
|
175
|
+
local found_any=0
|
|
176
|
+
for env_file in "$source_path"/.env*; do
|
|
177
|
+
[[ -f "$env_file" ]] || continue
|
|
178
|
+
local err_msg
|
|
179
|
+
err_msg="$(cp "$env_file" "$dest_dir/$(basename "$env_file")" 2>&1)"
|
|
180
|
+
if [[ $? -eq 0 ]]; then
|
|
181
|
+
(( overall_copied++ ))
|
|
182
|
+
location_copied=1
|
|
183
|
+
found_any=1
|
|
184
|
+
(( quiet != 1 )) && echo " ✅ Copied $(basename "$env_file") from $rel/"
|
|
185
|
+
copy_env_log "INFO" "Copied $(basename "$env_file") from $rel/"
|
|
186
|
+
else
|
|
187
|
+
(( overall_failed++ ))
|
|
188
|
+
(( location_failed++ ))
|
|
189
|
+
(( quiet != 1 )) && echo " ❌ Failed to copy $(basename "$env_file") from $rel/"
|
|
190
|
+
copy_env_log "ERROR" "Failed to copy $(basename "$env_file") from $rel/: ${err_msg:-unknown error}"
|
|
191
|
+
fi
|
|
192
|
+
done
|
|
193
|
+
if [[ $found_any -eq 1 ]]; then
|
|
194
|
+
break
|
|
195
|
+
fi
|
|
196
|
+
elif [[ -f "$source_path" ]]; then
|
|
197
|
+
local dest_dir
|
|
198
|
+
dest_dir="$(dirname "$rel")"
|
|
199
|
+
if [[ "$dest_dir" != "." ]]; then
|
|
200
|
+
mkdir -p "$target_root/$dest_dir"
|
|
201
|
+
else
|
|
202
|
+
mkdir -p "$target_root"
|
|
203
|
+
fi
|
|
204
|
+
local err_msg
|
|
205
|
+
err_msg="$(cp "$source_path" "$target_root/$rel" 2>&1)"
|
|
206
|
+
if [[ $? -eq 0 ]]; then
|
|
207
|
+
(( overall_copied++ ))
|
|
208
|
+
location_copied=1
|
|
209
|
+
(( quiet != 1 )) && echo " ✅ Copied $rel"
|
|
210
|
+
copy_env_log "INFO" "Copied file $rel"
|
|
211
|
+
else
|
|
212
|
+
(( overall_failed++ ))
|
|
213
|
+
(( location_failed++ ))
|
|
214
|
+
(( quiet != 1 )) && echo " ❌ Failed to copy $rel"
|
|
215
|
+
copy_env_log "ERROR" "Failed to copy file $rel: ${err_msg:-unknown error}"
|
|
216
|
+
fi
|
|
217
|
+
break
|
|
218
|
+
fi
|
|
219
|
+
fi
|
|
220
|
+
done
|
|
221
|
+
|
|
222
|
+
if [[ $location_copied -eq 0 ]]; then
|
|
223
|
+
if [[ "$trimmed" == "/" ]]; then
|
|
224
|
+
(( quiet != 1 )) && echo " ⚠️ No .env files found in any root"
|
|
225
|
+
copy_env_log "WARN" "No .env files discovered for '/'"
|
|
226
|
+
else
|
|
227
|
+
(( quiet != 1 )) && echo " ⚠️ No .env files found for $trimmed"
|
|
228
|
+
copy_env_log "WARN" "No .env files found for '$trimmed'"
|
|
229
|
+
fi
|
|
230
|
+
fi
|
|
231
|
+
done
|
|
232
|
+
|
|
233
|
+
COPY_ENV_LAST_COPIED=$overall_copied
|
|
234
|
+
|
|
235
|
+
if [[ $overall_copied -eq 0 ]]; then
|
|
236
|
+
copy_env_log "WARN" "Completed with no files copied"
|
|
237
|
+
(( quiet != 1 )) && echo " ⚠️ No environment files copied."
|
|
238
|
+
else
|
|
239
|
+
copy_env_log "INFO" "Completed: $overall_copied file(s) copied, failures=$overall_failed"
|
|
240
|
+
(( quiet != 1 )) && echo " ✅ Environment files copied ($overall_copied)."
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
return 0
|
|
244
|
+
}
|