changemaker.lite/scripts/update-env.sh

86 lines
2.0 KiB
Bash
Executable File

#!/bin/bash
# Safe .env updater with atomic writes
# Usage: ./scripts/update-env.sh KEY1=value1 KEY2=value2 ...
set -euo pipefail
# Configuration
ENV_FILE="${ENV_FILE:-.env}"
BACKUP_DIR="${BACKUP_DIR:-.}"
# Validate arguments
if [ $# -eq 0 ]; then
echo "Usage: $0 KEY=value [KEY2=value2 ...]"
echo "Example: $0 PANGOLIN_SITE_ID=abc123 PANGOLIN_NEWT_ID=xyz789"
exit 1
fi
# Validate .env file exists
if [ ! -f "$ENV_FILE" ]; then
echo "Error: $ENV_FILE not found"
exit 1
fi
# Create backup with timestamp
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/.env.backup.${TIMESTAMP}"
cp "$ENV_FILE" "$BACKUP_FILE"
echo "Backup created: $BACKUP_FILE"
# Create temporary file
TMP_FILE="${ENV_FILE}.tmp"
cp "$ENV_FILE" "$TMP_FILE"
# Process each KEY=value argument
for arg in "$@"; do
# Validate format
if [[ ! "$arg" =~ ^[A-Z_][A-Z0-9_]*=.*$ ]]; then
echo "Error: Invalid format '$arg'. Expected KEY=value"
rm "$TMP_FILE"
exit 1
fi
KEY="${arg%%=*}"
VALUE="${arg#*=}"
echo "Updating $KEY"
# Check if key exists
if grep -q "^${KEY}=" "$TMP_FILE"; then
# Update existing key (handles multi-line values via sed)
# Use | as delimiter to avoid conflicts with / in values
sed -i "s|^${KEY}=.*|${KEY}=${VALUE}|" "$TMP_FILE"
else
# Append new key
echo "" >> "$TMP_FILE"
echo "${KEY}=${VALUE}" >> "$TMP_FILE"
fi
done
# Validate updated file (basic format check)
if ! grep -qE '^[A-Z_][A-Z0-9_]*=' "$TMP_FILE"; then
echo "Error: Updated file has invalid format"
rm "$TMP_FILE"
exit 1
fi
# Atomic move (overwrites original)
mv "$TMP_FILE" "$ENV_FILE"
echo "$ENV_FILE updated successfully"
echo "Backup available at: $BACKUP_FILE"
# Show updated values
echo ""
echo "Updated environment variables:"
for arg in "$@"; do
KEY="${arg%%=*}"
VALUE="${arg#*=}"
# Mask secrets (show first 8 chars only)
if [[ "$KEY" == *"SECRET"* ]] || [[ "$KEY" == *"PASSWORD"* ]] || [[ "$KEY" == *"TOKEN"* ]]; then
MASKED="${VALUE:0:8}..."
echo " $KEY=$MASKED"
else
echo " $KEY=$VALUE"
fi
done