#!/usr/bin/env sh # Update SOPS keys for every encrypted file in the project. # Discovers files by matching path_regex rules from .sops.yaml — # no directories are hardcoded. # # Usage: script/update-sops-keys [--dry-run] set -eu REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" DRY_RUN=0 for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=1 ;; *) printf 'unknown argument: %s\n' "$arg" >&2; exit 9 ;; esac done SOPS_CONFIG="$REPO_ROOT/.sops.yaml" if [ ! -f "$SOPS_CONFIG" ]; then printf 'error: .sops.yaml not found at %s\n' "$SOPS_CONFIG" >&2 exit 1 fi # Extract every path_regex value from .sops.yaml. # Lines look like: - path_regex: some/pattern$ regexes="$(grep '^\s*-\s*path_regex:' "$SOPS_CONFIG" | sed 's/.*path_regex:[[:space:]]*//')" if [ -z "$regexes" ]; then printf 'no path_regex rules found in .sops.yaml\n' >&2 exit 0 fi # Collect all repo files (committed + untracked, excluding .gitignore). # Write matches to a temp file to avoid subshell variable scoping issues. tmp="$(mktemp)" trap 'rm -f "$tmp"' EXIT git -C "$REPO_ROOT" ls-files --cached --others --exclude-standard | while read -r rel; do for regex in $regexes; do if printf '%s\n' "$rel" | grep -qE "$regex"; then printf '%s\n' "$rel" >> "$tmp" break fi done done if [ ! -s "$tmp" ]; then printf 'no matching sops files found\n' exit 0 fi while read -r rel; do abs="$REPO_ROOT/$rel" [ -f "$abs" ] || continue if [ "$DRY_RUN" -eq 1 ]; then printf '[dry-run] would updatekeys: %s\n' "$rel" else printf 'updating keys: %s\n' "$rel" sops updatekeys --yes "$abs" fi done < "$tmp"