fix: migrate copy-forward is manifest-free, no dead-end on legacy projects (EGB-710)
This commit is contained in:
parent
679ddbc1b7
commit
c121982dcd
2 changed files with 37 additions and 27 deletions
41
secrets
41
secrets
|
|
@ -2138,47 +2138,40 @@ _migrate_project() {
|
|||
info "Store is already format v2 — nothing to migrate."
|
||||
return 0
|
||||
fi
|
||||
local manifest="$PWD/$SECRETS_JSON_NAME"
|
||||
if [ ! -e "$manifest" ]; then
|
||||
die "No $SECRETS_JSON_NAME in $PWD.
|
||||
'secrets migrate' copy-forwards a project's v1 blobs to their v2 names and
|
||||
reads the project manifest to do so. cd into a project that has a manifest,
|
||||
then run 'secrets migrate'. (Store-wide 'secrets migrate --finalize' comes
|
||||
after every project is migrated.)"
|
||||
fi
|
||||
_check_manifest_file "$manifest"
|
||||
local project; project=$(derive_project_name "")
|
||||
local pdir="$SECRETS_DIR/$project"
|
||||
|
||||
local moved=0 already=0 would=0 etype epath slug old new
|
||||
while IFS=$'\t' read -r etype epath _; do
|
||||
[ -n "$etype" ] || continue
|
||||
# Only `properties` blobs change name in v2; dotenv and `file` are already
|
||||
# in their v2 shape and never move.
|
||||
[ "$etype" = "gradle-properties" ] || continue
|
||||
slug=$(_secrets_files_slug "$epath")
|
||||
old="$pdir/external/$slug.gradle-properties.age"
|
||||
new="$pdir/external/$slug.properties.age"
|
||||
[ -f "$old" ] || continue # nothing pushed yet (or already dropped)
|
||||
if [ -f "$new" ]; then # idempotent: twin already exists
|
||||
# Source of truth for the copy-forward is the STORE, not a project manifest.
|
||||
# Every v1 properties blob is a `*.gradle-properties.age` file whose v2 twin
|
||||
# is the same name with the `.properties.age` suffix (the only on-disk change
|
||||
# v2 makes). Enumerating the store — exactly as `_migrate_finalize` does —
|
||||
# means migrate twins precisely the blobs finalize will demand twins for, with
|
||||
# no manifest dependency. This is why a legacy `.secrets-files`-only project
|
||||
# (no `.secrets.json` yet) migrates cleanly instead of dead-ending, and why a
|
||||
# store blob the manifest no longer declares still gets a twin.
|
||||
local moved=0 already=0 would=0 f new
|
||||
while IFS= read -r f; do
|
||||
[ -f "$f" ] || continue
|
||||
new="${f%.gradle-properties.age}.properties.age"
|
||||
if [ -f "$new" ]; then
|
||||
already=$((already + 1))
|
||||
continue
|
||||
fi
|
||||
if [ "$dry_run" = true ]; then
|
||||
echo "would migrate: $project/external/$slug.gradle-properties.age -> $slug.properties.age"
|
||||
echo "would migrate: ${f#"$SECRETS_DIR"/} -> $(basename "$new")"
|
||||
would=$((would + 1))
|
||||
else
|
||||
cp "$old" "$new"
|
||||
cp "$f" "$new"
|
||||
moved=$((moved + 1))
|
||||
fi
|
||||
done < <(_json_external_entries "$manifest")
|
||||
done < <(find "$pdir/external" -type f -name '*.gradle-properties.age' 2>/dev/null)
|
||||
|
||||
if [ "$dry_run" = true ]; then
|
||||
echo "migrate --dry-run: $would blob(s) would be copy-forwarded for '$project' (writes nothing); $already already present. v1 blobs are kept until 'secrets migrate --finalize'."
|
||||
return 0
|
||||
fi
|
||||
if [ "$moved" -eq 0 ] && [ "$already" -eq 0 ]; then
|
||||
info "Nothing to migrate for '$project' (no v1 properties blobs)."
|
||||
info "Nothing to migrate for '$project' — no v1 properties blobs in the store (already v2-shaped). If you expected one, run 'secrets push' first, then re-run 'secrets migrate'."
|
||||
return 0
|
||||
fi
|
||||
ensure_store_protections
|
||||
|
|
|
|||
|
|
@ -123,12 +123,29 @@ m_file_src() { mkdir -p "$HOME/keystores"; printf 'KS\x00\x01\x02\xffDATA\n' >
|
|||
[ "$output" = "1" ]
|
||||
}
|
||||
|
||||
@test "migrate with no manifest in cwd dies with a directed message" {
|
||||
@test "migrate copy-forwards a v1 properties blob with no .secrets.json (manifest-free)" {
|
||||
# The EGB-710 repro: a legacy project has a v1 properties blob in the store
|
||||
# but no .secrets.json (it predates the manifest). migrate must NOT dead-end.
|
||||
make_v1_store
|
||||
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
||||
create_project_dir nomanifestblob
|
||||
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
||||
"$SECRETS_BIN" push nomanifestblob >/dev/null 2>&1
|
||||
rm -f .secrets.json # simulate a pre-manifest project
|
||||
run "$SECRETS_BIN" migrate
|
||||
[ "$status" -eq 0 ]
|
||||
run bash -c "ls $SECRETS_DIR/nomanifestblob/external/*.properties.age"
|
||||
[ "$status" -eq 0 ] # v2 twin written despite no manifest
|
||||
run bash -c "ls $SECRETS_DIR/nomanifestblob/external/*.gradle-properties.age"
|
||||
[ "$status" -eq 0 ] # v1 kept (non-destructive)
|
||||
}
|
||||
|
||||
@test "migrate in a project with no manifest and no store blobs is a clean no-op" {
|
||||
make_v1_store
|
||||
local dir="$WORK_DIR/nomanifest"; mkdir -p "$dir"; cd "$dir"
|
||||
run "$SECRETS_BIN" migrate
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *".secrets.json"* ]] || false
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"no v1 properties blobs"* ]] || false
|
||||
}
|
||||
|
||||
@test "migrate on an already-v2 store is a no-op" {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue