Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 24 additions & 29 deletions stackctl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1044,34 +1044,28 @@ _secrets_decrypt() {
log "Decrypt complete: $decrypted decrypted, $skipped skipped"
}

# Resolve which stack owns a service directory by grepping its .env reference
# in committed stack files. Uses linear scan (3 stacks × ~10 dirs) to stay
# POSIX-safe; avoids Bash 4+ associative arrays that break on macOS.
_dir_to_stack() {
local rel_path="$1"
for stack in "${STACK_FILES[@]}"; do
local stack_file
if stack_file="$(find_stack_file "$stack")"; then
if grep -F "./${rel_path}/.env" "$stack_file" >/dev/null 2>&1; then
printf '%s' "$stack"
return 0
fi
fi
done
return 1
}

_secrets_deploy() {
local -a dirs=("$@")
local deployed=0
local skipped=0

# Determine which stacks to deploy based on service dirs
# Map repo-relative path → stack name
local -A dir_to_stack=()
for dir in "${dirs[@]}"; do
local rel_path="${dir#$SCRIPT_DIR/}"
# Match precise env_file reference in stack content: ./REL_PATH/.env
# Avoids false positives from loose basename-only grep matches
local found_stack=false
for stack in "${STACK_FILES[@]}"; do
local stack_file
if stack_file="$(find_stack_file "$stack")"; then
if grep -F "./${rel_path}/.env" "$stack_file" >/dev/null 2>&1; then
dir_to_stack["$rel_path"]="$stack"
found_stack=true
break
fi
fi
done
if [[ "$found_stack" = false ]]; then
log "NOTE: $rel_path not found in any stack file — will decrypt but not deploy"
fi
done

# Decrypt all target services first (temp file + umask 077 + atomic move)
local -a decrypted_dirs=()
for dir in "${dirs[@]}"; do
Expand Down Expand Up @@ -1099,29 +1093,30 @@ _secrets_deploy() {
fi
done

# Deploy the relevant stacks
# Determine which stacks to deploy (deduped, one lookup per dir)
local -a stacks_to_deploy=()

for dir in "${dirs[@]}"; do
local rel_path="${dir#$SCRIPT_DIR/}"
if [[ -n "${dir_to_stack[$rel_path]:-}" ]]; then
local stack="${dir_to_stack[$rel_path]}"
# Deduplicate stacks
local stack
if stack="$(_dir_to_stack "$rel_path")"; then
# Deduplicate — same stack may be referenced by multiple services
local already=false
for s in "${stacks_to_deploy[@]}"; do
[[ "$s" == "$stack" ]] && already=true
done
if [[ "$already" = false ]]; then
stacks_to_deploy+=("$stack")
fi
else
log "NOTE: $rel_path not found in any stack file — will decrypt but not deploy"
fi
done

if [[ ${#stacks_to_deploy[@]} -gt 0 ]]; then
# Regenerate stacks if needed (reuse up logic)
if command -v python3 >/dev/null 2>&1; then
log "Regenerating stacks before deploy..."
python3 "$SCRIPT_DIR/tools/generate_stacks.py" 2>/dev/null || log "Warning: stack generation failed"
python3 "$SCRIPT_DIR/tools/generate_stacks.py" || log "Warning: stack generation failed"
fi

for stack in "${stacks_to_deploy[@]}"; do
Expand Down
Loading