feat: add inventory metadata updates
This commit is contained in:
1 parent
51aec1b404
commit
a87ab2709f
11 files changed
+1048
-12
No files matched your search
Executable
+219
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
project_name="${MINEROPS_ASSET_HISTORY_TEST_PROJECT:-minerops-asset-history-$$}"
|
||||
empty_database="minerops_asset_history_empty"
|
||||
compose=(
|
||||
docker compose
|
||||
--project-name "${project_name}"
|
||||
--env-file .env.dev
|
||||
-f compose.dev.yaml
|
||||
)
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
if (( status != 0 )); then
|
||||
echo
|
||||
echo "Asset ID history migration test failed. Recent PostgreSQL logs:"
|
||||
"${compose[@]}" logs --no-color --tail 120 postgres || true
|
||||
fi
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
exit "${status}"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
if [[ ! -f .env.dev ]]; then
|
||||
echo "Missing .env.dev. Run ./scripts/dev-env-init.sh first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_alembic() {
|
||||
"${compose[@]}" run --rm --no-deps backend alembic "$@"
|
||||
}
|
||||
|
||||
echo "Starting disposable PostgreSQL..."
|
||||
"${compose[@]}" up --detach postgres
|
||||
for attempt in $(seq 1 60); do
|
||||
if "${compose[@]}" exec -T postgres sh -ec \
|
||||
'pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
|
||||
>/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
if (( attempt == 60 )); then
|
||||
echo "PostgreSQL did not become ready." >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Building migration image..."
|
||||
"${compose[@]}" build backend
|
||||
|
||||
echo "Upgrading the current head to Asset ID history..."
|
||||
run_alembic upgrade 0008_manual_miner_inventory
|
||||
run_alembic upgrade head
|
||||
|
||||
current_revision="$(run_alembic current 2>/dev/null)"
|
||||
[[ "${current_revision}" == *"0009_inventory_asset_id_history"* ]]
|
||||
|
||||
echo "Checking history schema, constraints, foreign keys, and indexes..."
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
|
||||
<<'SQL'
|
||||
DO $$
|
||||
DECLARE
|
||||
v_role_id UUID;
|
||||
BEGIN
|
||||
IF to_regclass('public.miner_asset_id_history') IS NULL THEN
|
||||
RAISE EXCEPTION 'Asset ID history table was not created';
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'miner_asset_id_history'
|
||||
AND column_name = 'old_asset_id'
|
||||
AND is_nullable = 'YES'
|
||||
) OR EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'miner_asset_id_history'
|
||||
AND column_name IN ('miner_id', 'new_asset_id', 'changed_at', 'changed_by')
|
||||
AND is_nullable <> 'NO'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Asset ID history nullability is incorrect';
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = 'public'
|
||||
AND tablename = 'miner_asset_id_history'
|
||||
AND indexname = 'idx_miner_asset_id_history_miner_changed_at'
|
||||
AND indexdef LIKE '%(miner_id, changed_at, id)%'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Chronological miner history index is missing';
|
||||
END IF;
|
||||
|
||||
SELECT id INTO v_role_id FROM roles WHERE name = 'Admin';
|
||||
INSERT INTO users (
|
||||
id, username, display_name, password_hash, role_id
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000901',
|
||||
'asset-history-test',
|
||||
'Asset History Test',
|
||||
'not-used',
|
||||
v_role_id
|
||||
);
|
||||
INSERT INTO miners (id, asset_tag, status)
|
||||
VALUES (
|
||||
'00000000-0000-0000-0000-000000000902',
|
||||
'ASSET-OLD',
|
||||
'manual'
|
||||
);
|
||||
INSERT INTO miner_asset_id_history (
|
||||
miner_id, old_asset_id, new_asset_id, changed_at, changed_by
|
||||
) VALUES
|
||||
(
|
||||
'00000000-0000-0000-0000-000000000902',
|
||||
'ASSET-OLD',
|
||||
'ASSET-NEW',
|
||||
'2026-01-01 00:00:00+00',
|
||||
'00000000-0000-0000-0000-000000000901'
|
||||
),
|
||||
(
|
||||
'00000000-0000-0000-0000-000000000902',
|
||||
'ASSET-NEW',
|
||||
'ASSET-LATEST',
|
||||
'2026-01-02 00:00:00+00',
|
||||
'00000000-0000-0000-0000-000000000901'
|
||||
);
|
||||
|
||||
BEGIN
|
||||
INSERT INTO miner_asset_id_history (
|
||||
miner_id, old_asset_id, new_asset_id, changed_by
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000902',
|
||||
' ASSET-OLD ',
|
||||
'ASSET-BAD',
|
||||
'00000000-0000-0000-0000-000000000901'
|
||||
);
|
||||
RAISE EXCEPTION 'Unnormalized old Asset ID was accepted';
|
||||
EXCEPTION WHEN check_violation THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
INSERT INTO miner_asset_id_history (
|
||||
miner_id, old_asset_id, new_asset_id, changed_by
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000999',
|
||||
NULL,
|
||||
'ASSET-NEW',
|
||||
'00000000-0000-0000-0000-000000000901'
|
||||
);
|
||||
RAISE EXCEPTION 'Unknown miner history was accepted';
|
||||
EXCEPTION WHEN foreign_key_violation THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
INSERT INTO miner_asset_id_history (
|
||||
miner_id, old_asset_id, new_asset_id, changed_by
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000902',
|
||||
'ASSET-OLD',
|
||||
'ASSET-NEW',
|
||||
NULL
|
||||
);
|
||||
RAISE EXCEPTION 'History without an actor was accepted';
|
||||
EXCEPTION WHEN not_null_violation THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
DELETE FROM miners
|
||||
WHERE id = '00000000-0000-0000-0000-000000000902';
|
||||
RAISE EXCEPTION 'Miner with permanent Asset ID history was deleted';
|
||||
EXCEPTION WHEN foreign_key_violation THEN
|
||||
NULL;
|
||||
END;
|
||||
END
|
||||
$$;
|
||||
SQL
|
||||
|
||||
echo "Downgrading and re-upgrading Asset ID history..."
|
||||
run_alembic downgrade 0008_manual_miner_inventory
|
||||
table_after_downgrade="$(
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" -At' <<'SQL'
|
||||
SELECT to_regclass('public.miner_asset_id_history');
|
||||
SQL
|
||||
)"
|
||||
if [[ -n "${table_after_downgrade}" ]]; then
|
||||
echo "Asset ID history table remained after downgrade." >&2
|
||||
exit 1
|
||||
fi
|
||||
run_alembic upgrade head
|
||||
|
||||
echo "Migrating an empty database from base through head..."
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d postgres \
|
||||
-c "CREATE DATABASE minerops_asset_history_empty"' >/dev/null
|
||||
"${compose[@]}" run --rm --no-deps \
|
||||
-e "POSTGRES_DB=${empty_database}" \
|
||||
backend alembic upgrade head
|
||||
|
||||
empty_revision="$(
|
||||
"${compose[@]}" run --rm --no-deps \
|
||||
-e "POSTGRES_DB=${empty_database}" \
|
||||
backend alembic current 2>/dev/null
|
||||
)"
|
||||
[[ "${empty_revision}" == *"0009_inventory_asset_id_history"* ]]
|
||||
|
||||
echo "Asset ID history migration test passed."
|
||||
@@ -88,7 +88,7 @@ health_json="$(cat "${health_file}")"
|
||||
|
||||
echo "Checking migrations and required schema..."
|
||||
current_revision="$("${compose[@]}" exec -T backend alembic current 2>/dev/null)"
|
||||
[[ "${current_revision}" == *"0008_manual_miner_inventory"* ]]
|
||||
[[ "${current_revision}" == *"0009_inventory_asset_id_history"* ]]
|
||||
|
||||
missing_tables="$(
|
||||
"${compose[@]}" exec -T postgres sh -c \
|
||||
|
||||
Reference in new issue
Block a user