Skip to content

Commit 109689d

Browse files
committed
ensure full schema dropping after test
1 parent b2a3e21 commit 109689d

File tree

3 files changed

+55
-22
lines changed

3 files changed

+55
-22
lines changed

.github/workflows/redshift.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,15 @@ jobs:
7373
run: |
7474
apt-get update
7575
apt-get -y install python3 python3-pip python3-venv
76-
- name: Run linter
76+
- name: Run linter, deploy and test
7777
run: |
78-
make lint cloud=redshift || echo "Lint warnings (non-blocking)"
79-
- name: Run tests
80-
run: |
81-
make test cloud=redshift || echo "Tests (non-blocking)"
82-
- name: Deploy and test
83-
run: |
84-
make deploy cloud=redshift
85-
echo "✓ Deployment successful"
78+
make lint cloud=redshift && \
79+
make deploy cloud=redshift diff="$GIT_DIFF" && \
80+
make test cloud=redshift diff="$GIT_DIFF"
8681
- name: Remove deployment
82+
if: always()
8783
run: |
88-
make remove cloud=redshift
84+
make remove cloud=redshift drop-schema=1
8985
9086
deploy-internal:
9187
if: github.ref_name == 'main'

gateway/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ deploy: venv
9797
$(if $(modules),--modules=$(modules),) \
9898
$(if $(functions),--functions=$(functions),) \
9999
$(if $(production),--production,) \
100+
$(if $(diff),--diff,) \
100101
$(if $(dry-run),--dry-run,) \
101102
$(EXTRA_CLI_ARGS)
102103

@@ -106,6 +107,7 @@ remove: venv
106107
$(if $(modules),--modules=$(modules),) \
107108
$(if $(functions),--functions=$(functions),) \
108109
$(if $(production),--production,) \
110+
$(if $(drop-schema),--drop-schema,) \
109111
$(if $(dry-run),--dry-run,) \
110112
$(EXTRA_CLI_ARGS)
111113

gateway/logic/clouds/redshift/cli.py

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,11 @@ def deploy_all(
983983
is_flag=True,
984984
help="Remove from production (use 'carto' schema instead of prefixed schema)",
985985
)
986+
@click.option(
987+
"--drop-schema",
988+
is_flag=True,
989+
help="Drop entire schema with CASCADE (faster, removes all objects in schema)",
990+
)
986991
@click.pass_context
987992
def remove_all(
988993
ctx,
@@ -994,11 +999,15 @@ def remove_all(
994999
functions: Optional[str],
9951000
dry_run: bool,
9961001
production: bool,
1002+
drop_schema: bool,
9971003
):
9981004
"""Remove Lambda functions and external functions from Redshift
9991005
10001006
NOTE: This command does NOT delete IAM roles. Roles can be reused across
10011007
deployments and should be managed separately.
1008+
1009+
Use --drop-schema for CI environments to drop the entire schema with CASCADE.
1010+
This is faster and cleaner than dropping individual functions.
10021011
"""
10031012
logger.info("Removing Analytics Toolbox from Redshift")
10041013

@@ -1079,16 +1088,20 @@ def remove_all(
10791088
lambda_name = f"{lambda_prefix}{func.name}"
10801089
logger.info(f" - {lambda_name}")
10811090

1082-
# Count external functions
1083-
external_count = sum(
1084-
1 for f in to_remove
1085-
if f.get_cloud_config(CloudType.REDSHIFT).external_function_template
1086-
)
1087-
logger.info(f"\nExternal functions in {rs_schema} ({external_count}):")
1088-
for func in to_remove:
1089-
cloud_config = func.get_cloud_config(CloudType.REDSHIFT)
1090-
if cloud_config.external_function_template:
1091-
logger.info(f" - {rs_schema}.{func.name.upper()}")
1091+
if drop_schema:
1092+
logger.info(f"\nSchema:")
1093+
logger.info(f" - DROP SCHEMA {rs_schema} CASCADE")
1094+
else:
1095+
# Count external functions
1096+
external_count = sum(
1097+
1 for f in to_remove
1098+
if f.get_cloud_config(CloudType.REDSHIFT).external_function_template
1099+
)
1100+
logger.info(f"\nExternal functions in {rs_schema} ({external_count}):")
1101+
for func in to_remove:
1102+
cloud_config = func.get_cloud_config(CloudType.REDSHIFT)
1103+
if cloud_config.external_function_template:
1104+
logger.info(f" - {rs_schema}.{func.name.upper()}")
10921105

10931106
logger.info("\nNOTE: IAM roles will NOT be deleted (they can be reused)")
10941107
return
@@ -1110,15 +1123,37 @@ def remove_all(
11101123

11111124
# Phase 1: Drop all functions from Redshift
11121125
if rs_host and rs_user and rs_password and rs_database:
1113-
logger.info("\n=== Phase 1: Dropping all functions from Redshift ===\n")
1126+
logger.info("\n=== Phase 1: Dropping from Redshift ===\n")
11141127

11151128
# Filter functions that have external function templates
11161129
functions_to_drop = [
11171130
f for f in to_remove
11181131
if f.get_cloud_config(CloudType.REDSHIFT).external_function_template
11191132
]
11201133

1121-
if functions_to_drop:
1134+
if drop_schema:
1135+
# Drop entire schema with CASCADE - faster and cleaner for CI
1136+
try:
1137+
logger.info(f"Dropping schema {rs_schema} with CASCADE...")
1138+
drop_schema_sql = f"DROP SCHEMA IF EXISTS {rs_schema} CASCADE"
1139+
1140+
with redshift_connector.connect(
1141+
host=rs_host,
1142+
database=rs_database,
1143+
user=rs_user,
1144+
password=rs_password,
1145+
timeout=300,
1146+
) as conn:
1147+
conn.autocommit = True
1148+
with conn.cursor() as cursor:
1149+
cursor.execute(drop_schema_sql)
1150+
1151+
logger.info(f"✓ Dropped schema {rs_schema} (all objects removed)\n")
1152+
external_success = len(functions_to_drop)
1153+
except Exception as e:
1154+
logger.error(f"✗ Failed to drop schema: {e}\n")
1155+
# Continue with Lambda deletion even if schema drop fails
1156+
elif functions_to_drop:
11221157
try:
11231158
# Drop ALL external functions (Lambda-backed) in the schema
11241159
# Gateway only deploys external functions, so this is safe

0 commit comments

Comments
 (0)