Skip to content

Commit 276db43

Browse files
committed
Add support for source and target schemas in migration commands, enhance CLI options for better flexibility
1 parent 7079301 commit 276db43

File tree

2 files changed

+154
-18
lines changed

2 files changed

+154
-18
lines changed

README.md

Lines changed: 130 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,140 @@
1-
# ================================
2-
# README.md
31
# CloudSQL to Supabase Migration Tool
42

5-
A CLI tool to migrate PostgreSQL databases from Google Cloud SQL to Supabase.
3+
A robust CLI tool to safely migrate PostgreSQL databases from Google Cloud SQL to Supabase.
4+
5+
6+
## Installation
7+
8+
### 1. Clone the repository (or create the project structure)
9+
10+
```bash
11+
git clone https://github.com/Domains18/migrate-cloud-supabase.git
12+
cd cloudsql-to-supabase
13+
```
14+
15+
### 2. Set up a virtual environment (recommended)
16+
17+
```bash
18+
python -m venv venv
19+
source venv/bin/activate # On Windows: venv\Scripts\activate
20+
```
21+
22+
### 3. Install the package
23+
24+
```bash
25+
pip install -e .
26+
```
27+
28+
### 4. Configure your environment
29+
30+
Copy the example `.env` file and edit it with your database details:
31+
32+
```bash
33+
cp .env.example .env
34+
```
35+
36+
Edit the `.env` file with your database credentials:
37+
38+
```env
39+
# CloudSQL Configuration
40+
CLOUDSQL_USER=your_cloudsql_user
41+
CLOUDSQL_HOST=your_cloudsql_host
42+
CLOUDSQL_DB=your_database_name
43+
CLOUDSQL_PORT=5432
44+
CLOUDSQL_SSL_MODE=prefer
45+
CLOUDSQL_SCHEMA=public # Source schema to export from
46+
47+
# Supabase Configuration
48+
SUPABASE_USER=postgres
49+
SUPABASE_HOST=your_supabase_host.supabase.co
50+
SUPABASE_DB=postgres
51+
SUPABASE_PASSWORD=your_supabase_password
52+
SUPABASE_PORT=5432
53+
SUPABASE_SSL_MODE=require
54+
SUPABASE_SCHEMA=public # Target schema to import into
55+
56+
# Output Configuration
57+
OUTPUT_DIR=./outputs
58+
OUTPUT_DUMP=backup.sql
59+
CLEANED_DUMP=cleaned_backup.sql
60+
```
661

762
## Usage
63+
64+
### Validate Your Configuration
65+
66+
Before running any migration, check that your configuration is valid:
67+
68+
```bash
69+
python main.py validate
70+
```
71+
72+
### Full Migration
73+
74+
Run a complete migration from CloudSQL to Supabase in one command:
75+
876
```bash
977
python main.py migrate
10-
python main.py backup
1178
```
1279

13-
## Setup
80+
You'll be prompted for your CloudSQL password during the process.
81+
82+
### Full Migration with Custom Schema
83+
84+
To migrate data from a specific CloudSQL schema to a custom Supabase schema:
85+
86+
```bash
87+
python main.py migrate --source-schema=my_source_schema --target-schema=my_target_schema
88+
```
89+
90+
### Using with a Manually Downloaded Dump File
91+
92+
If you've already downloaded a PostgreSQL dump from CloudSQL:
93+
1494
```bash
15-
pip install -r requirements.txt
16-
cp .env.example .env
95+
# First clean the dump for Supabase compatibility
96+
python main.py clean-dump --input-file your_dump.sql --target-schema=my_schema
97+
98+
# Then import the cleaned dump to Supabase
99+
python main.py import-db --input-file cleaned_backup.sql --schema=my_schema
17100
```
101+
102+
### Step-by-Step Migration
103+
104+
You can also run each step of the migration separately:
105+
106+
1. Export from CloudSQL:
107+
```bash
108+
python main.py backup
109+
110+
## Requirements
111+
112+
- Python 3.8+
113+
- PostgreSQL client tools (psql, pg_dump)
114+
- Access to both CloudSQL and Supabase databases
115+
116+
## Troubleshooting
117+
118+
### Common Issues
119+
120+
1. **"Command not found" errors**
121+
- Ensure that PostgreSQL client tools are installed and in your PATH
122+
- On Ubuntu/Debian: `sudo apt-get install postgresql-client`
123+
- On macOS with Homebrew: `brew install libpq` and `brew link --force libpq`
124+
125+
2. **Connection errors**
126+
- Verify your database credentials in the `.env` file
127+
- Check that your IP is allowed in both CloudSQL and Supabase network settings
128+
- Test connection manually: `psql -h your_host -U your_user -d your_db`
129+
130+
3. **Import errors**
131+
- Common Supabase import issues are fixed by the cleaning step
132+
- For specific table errors, you may need to customize the `clean.py` replacement rules
133+
134+
### Getting Help
135+
136+
For more detailed logs, use the `--verbose` flag with any command:
137+
138+
```bash
139+
python main.py migrate --verbose
140+
```

cloudsql_to_supabase/cli.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,26 @@ def cli(verbose):
1818
@click.option('--schema-only', is_flag=True, help="Only export database schema, not data")
1919
@click.option('--skip-export', is_flag=True, help="Skip the export step (use existing dump)")
2020
@click.option('--skip-clean', is_flag=True, help="Skip the cleaning step")
21-
def migrate(cloudsql_password, schema_only, skip_export, skip_clean):
21+
@click.option('--source-schema', help="Source schema in CloudSQL to export")
22+
@click.option('--target-schema', help="Target schema in Supabase to import into")
23+
def migrate(cloudsql_password, schema_only, skip_export, skip_clean, source_schema, target_schema):
2224
"""Run full migration from CloudSQL to Supabase"""
2325
try:
2426
if not skip_export:
25-
export.export_cloudsql(password=cloudsql_password, schema_only=schema_only)
27+
export.export_cloudsql(
28+
password=cloudsql_password,
29+
schema_only=schema_only,
30+
schema=source_schema
31+
)
2632
else:
2733
logger.info("Skipping export step")
2834

2935
if not skip_clean:
30-
clean.clean_dump_file()
36+
clean.clean_dump_file(target_schema=target_schema)
3137
else:
3238
logger.info("Skipping clean step")
3339

34-
import_.import_to_supabase()
40+
import_.import_to_supabase(schema=target_schema)
3541
click.echo("Migration completed successfully!")
3642

3743
except Exception as e:
@@ -42,10 +48,15 @@ def migrate(cloudsql_password, schema_only, skip_export, skip_clean):
4248
@cli.command()
4349
@click.option('--cloudsql-password', help="CloudSQL password (if not provided, will prompt)")
4450
@click.option('--schema-only', is_flag=True, help="Only export database schema, not data")
45-
def backup(cloudsql_password, schema_only):
51+
@click.option('--schema', help="Specific schema to export (default: public)")
52+
def backup(cloudsql_password, schema_only, schema):
4653
"""Only export CloudSQL to a dump file"""
4754
try:
48-
dump_file = export.export_cloudsql(password=cloudsql_password, schema_only=schema_only)
55+
dump_file = export.export_cloudsql(
56+
password=cloudsql_password,
57+
schema_only=schema_only,
58+
schema=schema
59+
)
4960
click.echo(f"Backup completed successfully! File saved to: {dump_file}")
5061
except Exception as e:
5162
logger.error(f"Backup failed: {str(e)}")
@@ -55,13 +66,14 @@ def backup(cloudsql_password, schema_only):
5566
@cli.command()
5667
@click.option('--input-file', '-i', type=click.Path(exists=True), help="Input SQL dump file")
5768
@click.option('--output-file', '-o', type=click.Path(), help="Output cleaned SQL file")
58-
def clean_dump(input_file, output_file):
69+
@click.option('--target-schema', help="Target schema in Supabase to import into")
70+
def clean_dump(input_file, output_file, target_schema):
5971
"""Clean a SQL dump file for Supabase compatibility"""
6072
try:
6173
input_path = Path(input_file) if input_file else None
6274
output_path = Path(output_file) if output_file else None
6375

64-
result_file = clean.clean_dump_file(input_path, output_path)
76+
result_file = clean.clean_dump_file(input_path, output_path, target_schema)
6577
click.echo(f"Cleaning completed successfully! File saved to: {result_file}")
6678
except Exception as e:
6779
logger.error(f"Cleaning failed: {str(e)}")
@@ -70,11 +82,12 @@ def clean_dump(input_file, output_file):
7082

7183
@cli.command()
7284
@click.option('--input-file', '-i', type=click.Path(exists=True), help="Input SQL dump file to import")
73-
def import_db(input_file):
85+
@click.option('--schema', help="Target schema in Supabase to import into")
86+
def import_db(input_file, schema):
7487
"""Import a cleaned SQL dump file into Supabase"""
7588
try:
7689
input_path = Path(input_file) if input_file else None
77-
import_.import_to_supabase(input_path)
90+
import_.import_to_supabase(input_path, schema=schema)
7891
click.echo("Import completed successfully!")
7992
except Exception as e:
8093
logger.error(f"Import failed: {str(e)}")
@@ -98,4 +111,4 @@ def validate():
98111

99112
except Exception as e:
100113
click.echo(f"Configuration error: {str(e)}", err=True)
101-
exit(1)
114+
exit(1)

0 commit comments

Comments
 (0)