Skip to content

Commit 258215c

Browse files
DB: Added tool to dump DB schema and Hasura metadata for version control
1 parent 4025287 commit 258215c

5 files changed

Lines changed: 864 additions & 1 deletion

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
node_modules
22
dist
33
.ds_store
4-
.vscode
4+
.vscode
5+
.env
6+
.env.*

db/dump.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Export DB schema and Hasura metadata
5+
# Usage: ./dump.sh staging or ./dump.sh production
6+
7+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8+
ENV="${1:-staging}"
9+
10+
# Load environment-specific .env file
11+
ENV_FILE="$SCRIPT_DIR/.env.$ENV"
12+
if [ -f "$ENV_FILE" ]; then
13+
set -a
14+
source "$ENV_FILE"
15+
set +a
16+
else
17+
echo "Error: $ENV_FILE not found"
18+
echo "Usage: ./dump.sh [staging|production]"
19+
exit 1
20+
fi
21+
22+
# Validate required env vars
23+
for var in DB_HOST DB_USER DB_NAME DB_PASSWORD; do
24+
if [ -z "${!var}" ]; then
25+
echo "Error: $var is not set in $ENV_FILE"
26+
exit 1
27+
fi
28+
done
29+
30+
# Determine Hasura endpoint
31+
if [ "$ENV" = "staging" ]; then
32+
HASURA_ENDPOINT="https://graphql-staging.equalifyapp.com"
33+
else
34+
HASURA_ENDPOINT="https://graphql.equalifyapp.com"
35+
fi
36+
37+
# Add Homebrew PostgreSQL to PATH if needed
38+
if ! command -v pg_dump &> /dev/null; then
39+
PG_PATH=$(find /opt/homebrew/Cellar/postgresql* -name "pg_dump" 2>/dev/null | head -1)
40+
if [ -n "$PG_PATH" ]; then
41+
export PATH="$(dirname "$PG_PATH"):$PATH"
42+
else
43+
echo "Error: pg_dump not found. Install with: brew install postgresql"
44+
exit 1
45+
fi
46+
fi
47+
48+
OUT_DIR="$SCRIPT_DIR/$ENV"
49+
mkdir -p "$OUT_DIR"
50+
51+
echo "Dumping $ENV..."
52+
53+
# Export DB schema (no data)
54+
echo "Dumping database schema..."
55+
PGPASSWORD="$DB_PASSWORD" pg_dump \
56+
--schema-only \
57+
--no-owner \
58+
--no-privileges \
59+
-h "$DB_HOST" \
60+
-U "$DB_USER" \
61+
"$DB_NAME" > "$OUT_DIR/schema.sql"
62+
echo " -> db/$ENV/schema.sql"
63+
64+
# Export Hasura metadata
65+
echo "Exporting Hasura metadata..."
66+
curl -s -X POST "$HASURA_ENDPOINT/v1/metadata" \
67+
-H "X-Hasura-Admin-Secret: $DB_PASSWORD" \
68+
-H "Content-Type: application/json" \
69+
-d '{"type":"export_metadata","version":2,"args":{}}' > "$OUT_DIR/hasura-metadata.json"
70+
echo " -> db/$ENV/hasura-metadata.json"
71+
72+
echo "Done!"

db/hasura-metadata.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"resource_version":175,"metadata":{"version":3,"sources":[{"name":"default","kind":"postgres","tables":[{"table":{"name":"audits","schema":"public"},"object_relationships":[{"name":"user","using":{"manual_configuration":{"column_mapping":{"user_id":"id"},"insertion_order":null,"remote_table":{"name":"users","schema":"public"}}}}],"array_relationships":[{"name":"ignored_blockers","using":{"manual_configuration":{"column_mapping":{"id":"audit_id"},"insertion_order":null,"remote_table":{"name":"ignored_blockers","schema":"public"}}}},{"name":"scans","using":{"manual_configuration":{"column_mapping":{"id":"audit_id"},"insertion_order":null,"remote_table":{"name":"scans","schema":"public"}}}},{"name":"urls","using":{"manual_configuration":{"column_mapping":{"id":"audit_id"},"insertion_order":null,"remote_table":{"name":"urls","schema":"public"}}}}],"select_permissions":[{"role":"anonymous","permission":{"columns":["created_at","email_notifications","id","interval","name","payload","processed_at","remote_csv_error","remote_csv_url","response","scheduled_at","status","updated_at","user_id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["created_at","email_notifications","id","interval","name","payload","processed_at","remote_csv_error","remote_csv_url","response","scheduled_at","status","updated_at","user_id"],"filter":{},"allow_aggregations":true},"comment":""}],"update_permissions":[{"role":"user","permission":{"columns":["email_notifications","interval","remote_csv_error","remote_csv_url"],"filter":{},"check":null},"comment":""}]},{"table":{"name":"blocker_messages","schema":"public"},"object_relationships":[{"name":"blocker","using":{"manual_configuration":{"column_mapping":{"blocker_id":"id"},"insertion_order":null,"remote_table":{"name":"blockers","schema":"public"}}}},{"name":"message","using":{"manual_configuration":{"column_mapping":{"message_id":"id"},"insertion_order":null,"remote_table":{"name":"messages","schema":"public"}}}}],"select_permissions":[{"role":"anonymous","permission":{"columns":["created_at","updated_at","blocker_id","id","message_id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["created_at","updated_at","blocker_id","message_id","id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"blockers","schema":"public"},"object_relationships":[{"name":"ignored_blocker","using":{"manual_configuration":{"column_mapping":{"id":"blocker_id"},"insertion_order":null,"remote_table":{"name":"ignored_blockers","schema":"public"}}}},{"name":"url","using":{"manual_configuration":{"column_mapping":{"url_id":"id"},"insertion_order":null,"remote_table":{"name":"urls","schema":"public"}}}}],"array_relationships":[{"name":"blocker_messages","using":{"manual_configuration":{"column_mapping":{"id":"blocker_id"},"insertion_order":null,"remote_table":{"name":"blocker_messages","schema":"public"}}}}],"select_permissions":[{"role":"user","permission":{"columns":["audit_id","content","content_hash_id","content_normalized","created_at","equalified","id","scan_id","short_id","targets","updated_at","url_id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"ignored_blockers","schema":"public"},"object_relationships":[{"name":"blocker","using":{"manual_configuration":{"column_mapping":{"blocker_id":"id"},"insertion_order":null,"remote_table":{"name":"blockers","schema":"public"}}}}],"insert_permissions":[{"role":"user","permission":{"check":{},"columns":["created_at","updated_at","audit_id","blocker_id","id"]},"comment":""}],"select_permissions":[{"role":"anonymous","permission":{"columns":["created_at","updated_at","audit_id","blocker_id","id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["created_at","updated_at","audit_id","blocker_id","id"],"filter":{},"allow_aggregations":true},"comment":""}],"delete_permissions":[{"role":"user","permission":{"filter":{}},"comment":""}]},{"table":{"name":"invites","schema":"public"},"insert_permissions":[{"role":"user","permission":{"check":{},"set":{"user_id":"x-hasura-user-id"},"columns":["email","name","type","created_at","expires_on","updated_at","id","user_id"]},"comment":""}],"select_permissions":[{"role":"user","permission":{"columns":["email","name","type","created_at","expires_on","updated_at","id","user_id"],"filter":{},"allow_aggregations":true},"comment":""}],"delete_permissions":[{"role":"user","permission":{"filter":{}},"comment":""}]},{"table":{"name":"logs","schema":"public"},"object_relationships":[{"name":"LogToAudit","using":{"manual_configuration":{"column_mapping":{"audit_id":"id"},"insertion_order":null,"remote_table":{"name":"audits","schema":"public"}}}},{"name":"LogToUser","using":{"manual_configuration":{"column_mapping":{"user_id":"id"},"insertion_order":null,"remote_table":{"name":"users","schema":"public"}}}}],"insert_permissions":[{"role":"user","permission":{"check":{"user_id":{"_eq":"X-Hasura-User-Id"}},"set":{"user_id":"x-hasura-user-id"},"columns":["data","message","created_at","updated_at","audit_id","id","user_id"]},"comment":""}],"select_permissions":[{"role":"user","permission":{"columns":["data","message","created_at","updated_at","audit_id","id","user_id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"message_tags","schema":"public"},"object_relationships":[{"name":"tag","using":{"manual_configuration":{"column_mapping":{"tag_id":"id"},"insertion_order":null,"remote_table":{"name":"tags","schema":"public"}}}}],"select_permissions":[{"role":"anonymous","permission":{"columns":["created_at","updated_at","id","message_id","tag_id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["created_at","updated_at","tag_id","message_id","id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"messages","schema":"public"},"array_relationships":[{"name":"message_tags","using":{"manual_configuration":{"column_mapping":{"id":"message_id"},"insertion_order":null,"remote_table":{"name":"message_tags","schema":"public"}}}}],"select_permissions":[{"role":"anonymous","permission":{"columns":["category","content","id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["content","category","id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"scans","schema":"public"},"array_relationships":[{"name":"blockers","using":{"manual_configuration":{"column_mapping":{"id":"scan_id"},"insertion_order":null,"remote_table":{"name":"blockers","schema":"public"}}}}],"select_permissions":[{"role":"anonymous","permission":{"columns":["errors","pages","processed_pages","percentage","status","created_at","updated_at","audit_id","id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["errors","pages","processed_pages","percentage","status","created_at","updated_at","audit_id","id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"tags","schema":"public"},"select_permissions":[{"role":"anonymous","permission":{"columns":["content","id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["content","id"],"filter":{},"allow_aggregations":true},"comment":""}]},{"table":{"name":"urls","schema":"public"},"insert_permissions":[{"role":"user","permission":{"check":{"user_id":{"_eq":"X-Hasura-User-Id"}},"set":{"user_id":"x-hasura-user-id"},"columns":["audit_ids","type","url","created_at","updated_at","audit_id","id","user_id"]},"comment":""}],"select_permissions":[{"role":"anonymous","permission":{"columns":["audit_ids","type","url","created_at","updated_at","audit_id","id","user_id"],"filter":{},"allow_aggregations":true},"comment":""},{"role":"user","permission":{"columns":["audit_ids","type","url","created_at","updated_at","audit_id","id","user_id"],"filter":{},"allow_aggregations":true},"comment":""}],"update_permissions":[{"role":"user","permission":{"columns":["type"],"filter":{},"check":null},"comment":""}],"delete_permissions":[{"role":"user","permission":{"filter":{}},"comment":""}]},{"table":{"name":"users","schema":"public"},"select_permissions":[{"role":"user","permission":{"columns":["analytics","email","name","type","created_at","updated_at","apikey","id"],"filter":{},"allow_aggregations":true},"comment":""}],"update_permissions":[{"role":"user","permission":{"columns":["analytics","email","name","type","created_at","updated_at","apikey","id"],"filter":{},"check":{}},"comment":""}],"delete_permissions":[{"role":"user","permission":{"filter":{}},"comment":""}]}],"configuration":{"connection_info":{"database_url":{"from_env":"HASURA_GRAPHQL_DATABASE_URL"},"isolation_level":"read-committed","pool_settings":{"connection_lifetime":600,"idle_timeout":180,"max_connections":50,"retries":1},"use_prepared_statements":true}}}]}}

db/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "equalify-db",
3+
"private": true,
4+
"scripts": {
5+
"dump:staging": "./dump.sh staging",
6+
"dump:production": "./dump.sh production"
7+
}
8+
}

0 commit comments

Comments
 (0)