Fix CI migration step: extract Python to scripts/run_migrations.py
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m36s
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m36s
go-yaml (Gitea's parser) mishandles << inside block scalars, treating the bash heredoc delimiter as a YAML merge key. Move the migration logic to a standalone script called via python3 scripts/run_migrations.py.
This commit is contained in:
@@ -85,61 +85,7 @@ jobs:
|
||||
# Applies any pending migrations in migrations/*.sql to the Supabase DB.
|
||||
# Runs unconditionally (asset-only or full build) so the schema is always
|
||||
# current before the new code is deployed.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 - << 'PYEOF'
|
||||
import json, glob, subprocess, sys, os
|
||||
|
||||
def gcloud_secret(name):
|
||||
return subprocess.check_output([
|
||||
'gcloud', 'secrets', 'versions', 'access', 'latest',
|
||||
f'--secret={name}', '--project=neuron-785695'
|
||||
], text=True).strip()
|
||||
|
||||
access_token = gcloud_secret('supabase-access-token')
|
||||
project_id = 'ocojsghaonltunidkzpw'
|
||||
api_url = f'https://api.supabase.com/v1/projects/{project_id}/database/query'
|
||||
|
||||
def query(sql):
|
||||
r = subprocess.run([
|
||||
'curl', '-sf', '-X', 'POST', api_url,
|
||||
'-H', f'Authorization: Bearer {access_token}',
|
||||
'-H', 'Content-Type: application/json',
|
||||
'-d', json.dumps({'query': sql})
|
||||
], capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
raise RuntimeError(f'curl failed: {r.stderr}')
|
||||
resp = json.loads(r.stdout)
|
||||
if isinstance(resp, dict) and resp.get('message') and not isinstance(resp.get('message'), list):
|
||||
raise RuntimeError(f'DB error: {resp}')
|
||||
return resp
|
||||
|
||||
query("""
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
id text PRIMARY KEY,
|
||||
applied_at timestamptz DEFAULT now()
|
||||
)
|
||||
""")
|
||||
|
||||
applied = {row['id'] for row in query('SELECT id FROM schema_migrations')}
|
||||
print(f'Already applied: {sorted(applied)}')
|
||||
|
||||
pending = [p for p in sorted(glob.glob('migrations/*.sql'))
|
||||
if os.path.basename(p) not in applied]
|
||||
|
||||
if not pending:
|
||||
print('No pending migrations.')
|
||||
sys.exit(0)
|
||||
|
||||
for path in pending:
|
||||
name = os.path.basename(path)
|
||||
print(f'Applying {name}...')
|
||||
query(open(path).read())
|
||||
query(f"INSERT INTO schema_migrations (id) VALUES ('{name}')")
|
||||
print(f'Applied {name}')
|
||||
|
||||
print(f'Done. Applied {len(pending)} migration(s).')
|
||||
PYEOF
|
||||
run: python3 scripts/run_migrations.py
|
||||
|
||||
- name: Configure docker auth for Artifact Registry
|
||||
run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
|
||||
|
||||
@@ -102,61 +102,7 @@ jobs:
|
||||
# Applies any pending migrations in migrations/*.sql to the Supabase DB.
|
||||
# Runs unconditionally (asset-only or full build) so the schema is always
|
||||
# current before the new code is deployed.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 - << 'PYEOF'
|
||||
import json, glob, subprocess, sys, os
|
||||
|
||||
def gcloud_secret(name):
|
||||
return subprocess.check_output([
|
||||
'gcloud', 'secrets', 'versions', 'access', 'latest',
|
||||
f'--secret={name}', '--project=neuron-785695'
|
||||
], text=True).strip()
|
||||
|
||||
access_token = gcloud_secret('supabase-access-token')
|
||||
project_id = 'ocojsghaonltunidkzpw'
|
||||
api_url = f'https://api.supabase.com/v1/projects/{project_id}/database/query'
|
||||
|
||||
def query(sql):
|
||||
r = subprocess.run([
|
||||
'curl', '-sf', '-X', 'POST', api_url,
|
||||
'-H', f'Authorization: Bearer {access_token}',
|
||||
'-H', 'Content-Type: application/json',
|
||||
'-d', json.dumps({'query': sql})
|
||||
], capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
raise RuntimeError(f'curl failed: {r.stderr}')
|
||||
resp = json.loads(r.stdout)
|
||||
if isinstance(resp, dict) and resp.get('message') and not isinstance(resp.get('message'), list):
|
||||
raise RuntimeError(f'DB error: {resp}')
|
||||
return resp
|
||||
|
||||
query("""
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
id text PRIMARY KEY,
|
||||
applied_at timestamptz DEFAULT now()
|
||||
)
|
||||
""")
|
||||
|
||||
applied = {row['id'] for row in query('SELECT id FROM schema_migrations')}
|
||||
print(f'Already applied: {sorted(applied)}')
|
||||
|
||||
pending = [p for p in sorted(glob.glob('migrations/*.sql'))
|
||||
if os.path.basename(p) not in applied]
|
||||
|
||||
if not pending:
|
||||
print('No pending migrations.')
|
||||
sys.exit(0)
|
||||
|
||||
for path in pending:
|
||||
name = os.path.basename(path)
|
||||
print(f'Applying {name}...')
|
||||
query(open(path).read())
|
||||
query(f"INSERT INTO schema_migrations (id) VALUES ('{name}')")
|
||||
print(f'Applied {name}')
|
||||
|
||||
print(f'Done. Applied {len(pending)} migration(s).')
|
||||
PYEOF
|
||||
run: python3 scripts/run_migrations.py
|
||||
|
||||
- name: Configure docker auth for Artifact Registry
|
||||
run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
|
||||
|
||||
Reference in New Issue
Block a user