457 lines
18 KiB
Bash
457 lines
18 KiB
Bash
#!/usr/bin/env bats
|
|
# EGB-703 store-format-v2: marker, format-aware suffix, migrate (dry-run /
|
|
# copy-forward / finalize). bash 3.2: every standalone [[ ]] ends with || false.
|
|
|
|
load test_helper
|
|
|
|
# A v1 (legacy) store: born-v2 init, then strip the marker so it reads as v1
|
|
# and pushes write the legacy .gradle-properties.age suffix.
|
|
make_v1_store() {
|
|
init_with_remote
|
|
rm -f "$SECRETS_DIR/.secrets-format"
|
|
}
|
|
# Simulate an old (v1) client's properties blob: copy the pushed v2
|
|
# .properties.age to its v1 .gradle-properties.age twin (KEEPS both present).
|
|
m_fake_v1_twin() {
|
|
local proj="$1" v2
|
|
v2=$(ls "$SECRETS_DIR/$proj/external/"*.properties.age)
|
|
cp "$v2" "${v2%.properties.age}.gradle-properties.age"
|
|
}
|
|
# Like m_fake_v1_twin but RENAMES (leaves ONLY the v1 blob) — for copy-forward fixtures.
|
|
m_make_v1_only() {
|
|
local proj="$1" v2
|
|
v2=$(ls "$SECRETS_DIR/$proj/external/"*.properties.age)
|
|
mv "$v2" "${v2%.properties.age}.gradle-properties.age"
|
|
}
|
|
m_gradle_src() { mkdir -p "$HOME/.gradle"; printf '%s' "$1" > "$HOME/.gradle/gradle.properties"; }
|
|
m_file_src() { mkdir -p "$HOME/keystores"; printf 'KS\x00\x01\x02\xffDATA\n' > "$HOME/keystores/upload.keystore"; }
|
|
|
|
# ─── Format marker + format-aware suffix (increment 1) ────────────────
|
|
|
|
@test "init stamps the store format marker as v2 (born-v2)" {
|
|
init_with_remote
|
|
[ -f "$SECRETS_DIR/.secrets-format" ]
|
|
[ "$(cat "$SECRETS_DIR/.secrets-format")" = "2" ]
|
|
}
|
|
|
|
@test "which prints format v2 for a born-v2 store" {
|
|
init_with_remote
|
|
create_project_dir whichv2
|
|
run "$SECRETS_BIN" which
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"format: v2"* ]] || false
|
|
}
|
|
|
|
@test "which prints format v1 for a markerless (legacy) store" {
|
|
make_v1_store
|
|
create_project_dir whichv1
|
|
run "$SECRETS_BIN" which
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"format: v1"* ]] || false
|
|
}
|
|
|
|
@test "push on a born-v2 store writes the properties blob as .properties.age" {
|
|
init_with_remote
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir v2push
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push v2push >/dev/null 2>&1
|
|
run bash -c "ls $SECRETS_DIR/v2push/external/*.properties.age"
|
|
[ "$status" -eq 0 ]
|
|
run bash -c "ls $SECRETS_DIR/v2push/external/*.gradle-properties.age 2>/dev/null"
|
|
[ "$status" -ne 0 ]
|
|
}
|
|
|
|
@test "push on a v1 store writes the v2 suffix for a fresh external (additive v2)" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir v1push
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push v1push >/dev/null 2>&1
|
|
run bash -c "ls $SECRETS_DIR/v1push/external/*.properties.age"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "push writes the v2 suffix for a fresh external even on a v1 store" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir freshv1
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push freshv1 >/dev/null 2>&1
|
|
run bash -c "ls $SECRETS_DIR/freshv1/external/*.properties.age"
|
|
[ "$status" -eq 0 ]
|
|
run bash -c "ls $SECRETS_DIR/freshv1/external/*.gradle-properties.age 2>/dev/null"
|
|
[ "$status" -ne 0 ]
|
|
}
|
|
|
|
@test "push dual-writes the v1 twin so old clients stay fresh" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_old\n'
|
|
create_project_dir dualwrite
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push dualwrite >/dev/null 2>&1
|
|
m_fake_v1_twin dualwrite
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_new\n'
|
|
"$SECRETS_BIN" push dualwrite >/dev/null 2>&1
|
|
rm -f "$SECRETS_DIR/dualwrite/external/"*.properties.age
|
|
rm -f "$HOME/.gradle/gradle.properties"
|
|
"$SECRETS_BIN" pull dualwrite >/dev/null 2>&1
|
|
run grep -q 'beaconClerkPkTest=pk_test_new' "$HOME/.gradle/gradle.properties"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "the format marker is committed, not gitignored" {
|
|
init_with_remote
|
|
create_project_dir markercommit
|
|
"$SECRETS_BIN" push markercommit >/dev/null 2>&1
|
|
run bash -c "git -C $SECRETS_DIR ls-files | grep -qx .secrets-format"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "pull reads a v1-suffix properties blob on a v2 store (read-fallback)" {
|
|
init_with_remote # born-v2 store (marker=2)
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_v1\n'
|
|
create_project_dir rffallback
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push rffallback >/dev/null 2>&1 # writes .properties.age on a v2 store
|
|
# Simulate an external that exists only in the v1 suffix (an old client wrote it):
|
|
local v2blob; v2blob=$(ls "$SECRETS_DIR/rffallback/external/"*.properties.age)
|
|
mv "$v2blob" "${v2blob%.properties.age}.gradle-properties.age"
|
|
rm -f "$HOME/.gradle/gradle.properties"
|
|
"$SECRETS_BIN" pull rffallback >/dev/null 2>&1
|
|
run grep -q 'beaconClerkPkTest=pk_test_v1' "$HOME/.gradle/gradle.properties"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
# ─── migrate --dry-run / copy-forward (increment 2) ───────────────────
|
|
|
|
@test "migrate --dry-run reports the rename and writes nothing" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir dryproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push dryproj >/dev/null 2>&1
|
|
m_make_v1_only dryproj
|
|
run "$SECRETS_BIN" migrate --dry-run
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"would migrate"* ]] || false
|
|
# nothing written
|
|
run bash -c "ls $SECRETS_DIR/dryproj/external/*.properties.age 2>/dev/null"
|
|
[ "$status" -ne 0 ]
|
|
# marker still absent (store still v1)
|
|
[ ! -f "$SECRETS_DIR/.secrets-format" ]
|
|
}
|
|
|
|
@test "migrate --dry-run on a dotenv-only project reports nothing to migrate" {
|
|
make_v1_store
|
|
create_project_dir dotenvonly
|
|
"$SECRETS_BIN" push dotenvonly >/dev/null 2>&1
|
|
run "$SECRETS_BIN" migrate --dry-run
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"0 blob(s) would be copy-forwarded"* ]] || false
|
|
}
|
|
|
|
@test "migrate copy-forward creates the v2 twin and keeps the v1 blob (byte-identical)" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir cfproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push cfproj >/dev/null 2>&1
|
|
m_make_v1_only cfproj
|
|
local old; old=$(ls "$SECRETS_DIR/cfproj/external/"*.gradle-properties.age)
|
|
run "$SECRETS_BIN" migrate
|
|
[ "$status" -eq 0 ]
|
|
local new; new=$(ls "$SECRETS_DIR/cfproj/external/"*.properties.age)
|
|
[ -f "$old" ] # v1 kept (non-destructive)
|
|
[ -f "$new" ] # v2 twin written
|
|
cmp -s "$old" "$new" # byte-identical ciphertext copy
|
|
}
|
|
|
|
@test "migrate copy-forward is idempotent" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir idemproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push idemproj >/dev/null 2>&1
|
|
m_make_v1_only idemproj
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
run "$SECRETS_BIN" migrate
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"1 already present"* ]] || false
|
|
run bash -c "ls $SECRETS_DIR/idemproj/external/*.properties.age | wc -l | tr -d ' '"
|
|
[ "$output" = "1" ]
|
|
}
|
|
|
|
@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
|
|
m_make_v1_only nomanifestblob
|
|
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 twins a store blob even when the manifest no longer declares it" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir staleblob
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push staleblob >/dev/null 2>&1
|
|
m_make_v1_only staleblob
|
|
# The blob is now in the store. Drop the external from the project's manifest
|
|
# entirely (and remove the legacy file) so NO manifest declares it.
|
|
printf '{"version":2,"dotenv":[".env",".env.staging"]}\n' > .secrets.json
|
|
rm -f .secrets-files
|
|
run bash -c "ls $SECRETS_DIR/staleblob/external/*.gradle-properties.age"
|
|
[ "$status" -eq 0 ] # precondition: the v1 blob exists in the store
|
|
run "$SECRETS_BIN" migrate
|
|
[ "$status" -eq 0 ]
|
|
run bash -c "ls $SECRETS_DIR/staleblob/external/*.properties.age"
|
|
[ "$status" -eq 0 ] # twinned despite not being declared anywhere
|
|
}
|
|
|
|
@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 0 ]
|
|
[[ "$output" == *"no v1 properties blobs"* ]] || false
|
|
}
|
|
|
|
@test "migrate on an already-v2 store is a no-op" {
|
|
init_with_remote
|
|
create_project_dir alreadyv2
|
|
run "$SECRETS_BIN" migrate
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"already format v2"* ]] || false
|
|
}
|
|
|
|
@test "migrate unknown flag dies with usage" {
|
|
init_with_remote
|
|
create_project_dir mgflag
|
|
run "$SECRETS_BIN" migrate --bogus
|
|
[ "$status" -eq 1 ]
|
|
[[ "$output" == *"Unknown migrate flag"* ]] || false
|
|
}
|
|
|
|
@test "migrate leaves dotenv and file blobs untouched" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
m_file_src
|
|
create_project_dir mixproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\nfile ~/keystores/upload.keystore\n' > .secrets-files
|
|
"$SECRETS_BIN" push mixproj >/dev/null 2>&1
|
|
local envblob; envblob=$(ls "$SECRETS_DIR/mixproj/".env.age)
|
|
local fileblob; fileblob=$(ls "$SECRETS_DIR/mixproj/external/"*.file.age)
|
|
local envsum; envsum=$(cksum "$envblob")
|
|
local filesum; filesum=$(cksum "$fileblob")
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
[ "$(cksum "$envblob")" = "$envsum" ] # dotenv blob unchanged
|
|
[ "$(cksum "$fileblob")" = "$filesum" ] # file blob unchanged
|
|
}
|
|
|
|
# ─── migrate --finalize (increment 3) ─────────────────────────────────
|
|
|
|
@test "finalize refuses when verify --all is not green" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir failverify
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push failverify >/dev/null 2>&1
|
|
m_make_v1_only failverify
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
# corrupt the v2 twin so verify --all fails
|
|
printf 'garbage' > "$SECRETS_DIR/failverify/external/"*.properties.age
|
|
run "$SECRETS_BIN" migrate --finalize --yes
|
|
[ "$status" -eq 1 ]
|
|
[[ "$output" == *"not green"* ]] || false
|
|
# marker not stamped; v1 blob still present
|
|
[ ! -f "$SECRETS_DIR/.secrets-format" ]
|
|
run bash -c "ls $SECRETS_DIR/failverify/external/*.gradle-properties.age"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "finalize refuses an un-twinned v1 blob (project not migrated)" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir untwinned
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push untwinned >/dev/null 2>&1
|
|
m_make_v1_only untwinned
|
|
# do NOT migrate — leave the v1 blob with no twin
|
|
run "$SECRETS_BIN" migrate --finalize --yes
|
|
[ "$status" -eq 1 ]
|
|
[[ "$output" == *"no v2 twin"* ]] || false
|
|
run bash -c "ls $SECRETS_DIR/untwinned/external/*.gradle-properties.age"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "finalize green path drops v1, keeps v2, stamps the marker" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir finproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push finproj >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
run "$SECRETS_BIN" migrate --finalize --yes
|
|
[ "$status" -eq 0 ]
|
|
[ "$(cat "$SECRETS_DIR/.secrets-format")" = "2" ]
|
|
run bash -c "ls $SECRETS_DIR/finproj/external/*.properties.age"
|
|
[ "$status" -eq 0 ]
|
|
run bash -c "ls $SECRETS_DIR/finproj/external/*.gradle-properties.age 2>/dev/null"
|
|
[ "$status" -ne 0 ]
|
|
}
|
|
|
|
@test "finalize cuts a recovery tag before deleting v1 blobs" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir tagproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push tagproj >/dev/null 2>&1
|
|
m_make_v1_only tagproj
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate --finalize --yes >/dev/null 2>&1
|
|
local tag; tag=$(git -C "$SECRETS_DIR" tag | grep '^pre-v2-migrate-')
|
|
[ -n "$tag" ]
|
|
# the tagged commit still contains the v1 blob (tag cut before delete)
|
|
run bash -c "git -C $SECRETS_DIR ls-tree -r --name-only $tag | grep -q gradle-properties.age"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "finalize without --yes aborts when not confirmed" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir confproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push confproj >/dev/null 2>&1
|
|
m_make_v1_only confproj
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
run bash -c "echo '' | $SECRETS_BIN migrate --finalize"
|
|
[ "$status" -eq 1 ]
|
|
[[ "$output" == *"aborted"* ]] || false
|
|
[ ! -f "$SECRETS_DIR/.secrets-format" ]
|
|
}
|
|
|
|
@test "verify is green during the migration window (v2 twin is not a spurious orphan)" {
|
|
# Regression: after copy-forward the store is still v1, so verify computed the
|
|
# external blob path as .gradle-properties.age and flagged the .properties.age
|
|
# twin as an orphan, failing verify mid-migration. The orphan set now accounts
|
|
# for both suffix forms.
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir windowverify
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push windowverify >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
run "$SECRETS_BIN" verify windowverify
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "v1 client still reads during the migration window (after copy-forward, before finalize)" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir windowproj
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push windowproj >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
# store is still v1 (markerless); pull uses the .gradle-properties.age blob
|
|
rm "$HOME/.gradle/gradle.properties"
|
|
run "$SECRETS_BIN" pull windowproj
|
|
[ "$status" -eq 0 ]
|
|
grep -q '^beaconClerkPkTest=pk_test_abc$' "$HOME/.gradle/gradle.properties"
|
|
}
|
|
|
|
@test "post-finalize pull reads the v2 blob" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir postfin
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push postfin >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate --finalize --yes >/dev/null 2>&1
|
|
rm "$HOME/.gradle/gradle.properties"
|
|
run "$SECRETS_BIN" pull postfin
|
|
[ "$status" -eq 0 ]
|
|
grep -q '^beaconClerkPkTest=pk_test_abc$' "$HOME/.gradle/gradle.properties"
|
|
}
|
|
|
|
@test "finalize on a v1 dotenv-only store stamps the marker (no v1 blobs to drop)" {
|
|
make_v1_store
|
|
create_project_dir dotenvfin
|
|
"$SECRETS_BIN" push dotenvfin >/dev/null 2>&1
|
|
# no gradle-properties externals → v1count==0 path; no confirmation needed
|
|
run "$SECRETS_BIN" migrate --finalize
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"no v1 blobs"* ]] || false
|
|
[ "$(cat "$SECRETS_DIR/.secrets-format")" = "2" ]
|
|
}
|
|
|
|
@test "migrate with a positional argument dies" {
|
|
init_with_remote
|
|
create_project_dir mgpos
|
|
run "$SECRETS_BIN" migrate someproject
|
|
[ "$status" -eq 1 ]
|
|
[[ "$output" == *"no project argument"* ]] || false
|
|
}
|
|
|
|
@test "finalize on an already-v2 store is a no-op" {
|
|
init_with_remote
|
|
create_project_dir finv2
|
|
run "$SECRETS_BIN" migrate --finalize --yes
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"already format v2"* ]] || false
|
|
}
|
|
|
|
@test "migrate --status flags a project that needs migrating" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir needsmig
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push needsmig >/dev/null 2>&1 # v1 blob, no twin yet
|
|
m_make_v1_only needsmig
|
|
run "$SECRETS_BIN" migrate --status
|
|
[ "$status" -ne 0 ] # not finalize-ready
|
|
[[ "$output" == *"needsmig"* ]] || false
|
|
[[ "$output" == *"NEEDS MIGRATE"* ]] || false
|
|
[[ "$output" == *"Not finalize-ready"* ]] || false
|
|
}
|
|
|
|
@test "migrate --status reports finalize-ready once every blob is twinned" {
|
|
make_v1_store
|
|
m_gradle_src $'beaconClerkPkTest=pk_test_abc\n'
|
|
create_project_dir readymig
|
|
printf 'gradle-properties ~/.gradle/gradle.properties beaconClerkPkTest\n' > .secrets-files
|
|
"$SECRETS_BIN" push readymig >/dev/null 2>&1
|
|
"$SECRETS_BIN" migrate >/dev/null 2>&1 # create the twin
|
|
run "$SECRETS_BIN" migrate --status
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Finalize-ready"* ]] || false
|
|
}
|
|
|
|
@test "migrate --status on an already-v2 store says nothing to do" {
|
|
init_with_remote
|
|
create_project_dir v2status
|
|
run "$SECRETS_BIN" migrate --status
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"v2"* ]] || false
|
|
[[ "$output" == *"nothing to migrate"* ]] || false
|
|
}
|
|
|
|
@test "_store_format reads a garbage marker as v1 (strict parse)" {
|
|
make_v1_store
|
|
create_project_dir garbagemarker
|
|
# a non-"2" marker (e.g. a truncated/garbled value) must read as v1, not v2
|
|
printf 'v2-ish-garbage\n' > "$SECRETS_DIR/.secrets-format"
|
|
run "$SECRETS_BIN" which
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"format: v1"* ]] || false
|
|
}
|