Skip to content

fix(scripts): improve workspace setup/teardown reliability#333

Merged
saddlepaddle merged 1 commit into
mainfrom
clumsy-sparrow-3dd333
Dec 12, 2025
Merged

fix(scripts): improve workspace setup/teardown reliability#333
saddlepaddle merged 1 commit into
mainfrom
clumsy-sparrow-3dd333

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Dec 12, 2025

Summary

  • Source root .env at start of setup to get NEON_PROJECT_ID
  • Copy root .env to worktree and override DATABASE_URLs with branch-specific values
  • Create .envrc instead of symlinking to root
  • Make setup idempotent by checking for existing Neon branches
  • Make teardown idempotent by handling already-deleted branches gracefully

Test plan

  • Tested setup.sh on fresh worktree
  • Tested setup.sh re-run (idempotent - uses existing branch)
  • Tested teardown.sh
  • Tested teardown.sh re-run (idempotent - graceful warning)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Workspace setup now intelligently reuses existing database branches when available, eliminating unnecessary duplication.
    • Improved environment configuration handling with automatic population of database connection strings.
  • Bug Fixes

    • Enhanced teardown process with improved error handling and informative messaging when database branch removal fails.

✏️ Tip: You can customize this high-level summary in your review settings.

- Source root .env at start of setup to get NEON_PROJECT_ID
- Copy root .env to worktree and override DATABASE_URLs with branch-specific values
- Create .envrc instead of symlinking to root
- Make setup idempotent by checking for existing Neon branches
- Make teardown idempotent by handling already-deleted branches gracefully
- Source local .env at start of teardown to get required vars

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 12, 2025

Walkthrough

The changes modify Superset's workspace setup and teardown scripts to implement a branch-reuse strategy for Neon databases. Setup now checks for existing Neon branches matching the workspace name, reuses them if found, or creates new ones, then populates environment variables with pooled and unpooled connection strings. Teardown improves error handling when deleting branches, with explicit logging and failure-resilience messaging.

Changes

Cohort / File(s) Summary
Neon branch lifecycle management
\.superset/setup.sh`, `.superset/teardown.sh``
Modified setup script to load root .env, create .envrc wrapper if missing, implement branch-reuse or branch-creation logic based on existing Neon branch availability, and populate local environment with pooled/unpooled database URLs and NEON_BRANCH_ID. Enhanced teardown script to load local .env, add explicit logging for branch deletion, and implement error-handling flow with success/failure messaging.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Branch reuse logic verification: Confirm neonctl queries correctly detect existing branches and that the conditional flow (check → reuse or create) handles all edge cases.
  • Connection string handling: Verify pooled (DATABASE_URL) and unpooled (DATABASE_URL_UNPOOLED) URLs are correctly extracted and applied to local .env.
  • Environment variable precedence: Ensure root .env loading, copying, and local updates don't create conflicts or unintended overrides.
  • Error resilience in teardown: Validate that branch deletion failures (not found or already deleted) are handled gracefully with appropriate messaging.
  • direnv integration: Confirm .envrc creation is idempotent and that the minimal wrapper correctly sources .env.

Possibly related PRs

Poem

🐰 A branch blooms in Neon's glow,
We reuse what's there, or plant one new—
Connection strings flow, both pooled and true,
Then gently tear it down below.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main objective of improving workspace setup/teardown reliability through idempotency and better environment handling.
Description check ✅ Passed The description provides a clear summary of changes and testing performed, but lacks full alignment with the template including missing Type of Change checkbox, Related Issues section, and Screenshots/Additional Notes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch clumsy-sparrow-3dd333

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 12, 2025

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

Service Status
Database (Neon)

Thank you for your contribution! 🎉


Preview resources have been processed for cleanup

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
.superset/teardown.sh (1)

28-31: Potential edge case: Missing NEON_BRANCH_ID after .env load.

The script correctly validates that NEON_BRANCH_ID exists, but if .env loading fails silently (e.g., file permission issues), the error message may not be clear. Consider logging the source attempt:

 # Load local .env
 if [ -f ".env" ]; then
+  echo "📋 Loading workspace configuration..."
   set -a
   source .env
   set +a
 fi

This provides clearer diagnostics if branch deletion fails due to missing configuration.

.superset/setup.sh (1)

47-69: Branch reuse/create logic is sound, but missing validation for jq output.

The logic correctly checks for an existing branch and reuses it, or creates a new one. However, line 51 assumes jq returns exactly one result or empty. If multiple branches have the same name (due to past failures or race conditions), the filter selects the first match. Consider validating the jq output:

 EXISTING_BRANCH=$(neonctl branches list --project-id "$NEON_PROJECT_ID" --output json | jq -r ".[] | select(.name == \"$WORKSPACE_NAME\") | .id")
+if [ $(echo "$NEON_OUTPUT" | jq '. | length') -gt 1 ]; then
+  error "Multiple Neon branches found with name '$WORKSPACE_NAME'. Manual cleanup required."
+fi

However, this adds complexity. A simpler fix: use first to ensure deterministic behavior:

-EXISTING_BRANCH=$(neonctl branches list --project-id "$NEON_PROJECT_ID" --output json | jq -r ".[] | select(.name == \"$WORKSPACE_NAME\") | .id")
+EXISTING_BRANCH=$(neonctl branches list --project-id "$NEON_PROJECT_ID" --output json | jq -r "first((.[] | select(.name == \"$WORKSPACE_NAME\")) | .id)")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ea6dce and a4185fa.

📒 Files selected for processing (2)
  • .superset/setup.sh (2 hunks)
  • .superset/teardown.sh (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
.superset/teardown.sh (1)
.superset/setup.sh (1)
  • error (8-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Deploy API
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy Web
  • GitHub Check: Deploy Marketing
  • GitHub Check: Build
🔇 Additional comments (3)
.superset/teardown.sh (2)

13-19: Environment loading pattern is safe and consistent.

Using set -a/set +a to source .env is correct and aligns with setup.sh. The conditional check for .env existence prevents errors if the file is missing.


36-41: Graceful error handling for idempotent teardown is well-implemented.

The script handles the case where the branch is already deleted by catching the neonctl error and displaying a non-fatal warning. This supports the idempotency requirement stated in the PR objectives.

.superset/setup.sh (1)

34-45: No action needed. The dotenv .env syntax in the .envrc file is valid according to direnv's official documentation. Both dotenv .env and dotenv_if_exists .env are supported; the former is a standard form and does not require modification.

Comment thread .superset/setup.sh
Comment on lines +13 to +18
# Load root .env for this script (provides NEON_PROJECT_ID, etc.)
if [ -n "$SUPERSET_ROOT_PATH" ] && [ -f "$SUPERSET_ROOT_PATH/.env" ]; then
set -a
source "$SUPERSET_ROOT_PATH/.env"
set +a
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Root .env loading requires validation of SUPERSET_ROOT_PATH.

The script attempts to source $SUPERSET_ROOT_PATH/.env but does not validate that the path is absolute or that the file exists with correct permissions. If SUPERSET_ROOT_PATH is unset or malformed, the load silently skips, yet the script later assumes variables like NEON_PROJECT_ID are available. Consider adding explicit validation:

 # Load root .env for this script (provides NEON_PROJECT_ID, etc.)
-if [ -n "$SUPERSET_ROOT_PATH" ] && [ -f "$SUPERSET_ROOT_PATH/.env" ]; then
+if [ -z "$SUPERSET_ROOT_PATH" ]; then
+  error "SUPERSET_ROOT_PATH environment variable is required"
+fi
+
+if [ ! -f "$SUPERSET_ROOT_PATH/.env" ]; then
+  error "Root .env file not found at $SUPERSET_ROOT_PATH/.env"
+fi
+
+if true; then
   set -a
   source "$SUPERSET_ROOT_PATH/.env"
   set +a
 fi

This ensures the root .env is always available and fails fast with a clear error message.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In .superset/setup.sh around lines 13 to 18, the script sources
$SUPERSET_ROOT_PATH/.env without validating SUPERSET_ROOT_PATH or the .env file,
which can lead to missing required env vars later; update the script to first
check that SUPERSET_ROOT_PATH is set, that it is an absolute path, that the file
"$SUPERSET_ROOT_PATH/.env" exists and is readable, and if any check fails print
a clear error to stderr and exit non‑zero; only then enable export (set -a),
source the file, and disable export (set +a) so the script fails fast with a
clear message when the root .env is missing or inaccessible.

Comment thread .superset/setup.sh
Comment on lines +71 to +75
# Copy root .env and override with branch-specific values
cp "$SUPERSET_ROOT_PATH/.env" .env
sed -i '' "s|^DATABASE_URL=.*|DATABASE_URL=$POOLED_URL|" .env
sed -i '' "s|^DATABASE_URL_UNPOOLED=.*|DATABASE_URL_UNPOOLED=$DIRECT_URL|" .env
echo "NEON_BRANCH_ID=$BRANCH_ID" >> .env
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: sed -i '' is not portable; environment variable values may break sed patterns.

Two issues here:

  1. Portability: sed -i '' (macOS syntax with empty backup suffix) fails on GNU sed (Linux). Use sed -i alone with conditional logic:

    -sed -i '' "s|^DATABASE_URL=.*|DATABASE_URL=$POOLED_URL|" .env
    -sed -i '' "s|^DATABASE_URL_UNPOOLED=.*|DATABASE_URL_UNPOOLED=$DIRECT_URL|" .env
    +if sed -i.bak "s|^DATABASE_URL=.*|DATABASE_URL=$POOLED_URL|" .env && rm -f .env.bak; then :; else
    +  error "Failed to update DATABASE_URL in .env"
    +fi
    +if sed -i.bak "s|^DATABASE_URL_UNPOOLED=.*|DATABASE_URL_UNPOOLED=$DIRECT_URL|" .env && rm -f .env.bak; then :; else
    +  error "Failed to update DATABASE_URL_UNPOOLED in .env"
    +fi
  2. Path Injection: If $POOLED_URL or $DIRECT_URL contain sed delimiters (e.g., | or &), the sed command will break. Escape or use a different delimiter:

    +# Escape special characters in connection strings for sed
    +POOLED_URL_ESCAPED=$(echo "$POOLED_URL" | sed -e 's/[\/&]/\\&/g')
    +DIRECT_URL_ESCAPED=$(echo "$DIRECT_URL" | sed -e 's/[\/&]/\\&/g')

    Or, use a safer alternative with awk:

    -sed -i '' "s|^DATABASE_URL=.*|DATABASE_URL=$POOLED_URL|" .env
    -sed -i '' "s|^DATABASE_URL_UNPOOLED=.*|DATABASE_URL_UNPOOLED=$DIRECT_URL|" .env
    +awk -v pooled="$POOLED_URL" -v direct="$DIRECT_URL" '
    +  /^DATABASE_URL=/ { print "DATABASE_URL=" pooled; next }
    +  /^DATABASE_URL_UNPOOLED=/ { print "DATABASE_URL_UNPOOLED=" direct; next }
    +  { print }
    +' "$SUPERSET_ROOT_PATH/.env" > .env.tmp && mv .env.tmp .env
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Copy root .env and override with branch-specific values
cp "$SUPERSET_ROOT_PATH/.env" .env
sed -i '' "s|^DATABASE_URL=.*|DATABASE_URL=$POOLED_URL|" .env
sed -i '' "s|^DATABASE_URL_UNPOOLED=.*|DATABASE_URL_UNPOOLED=$DIRECT_URL|" .env
echo "NEON_BRANCH_ID=$BRANCH_ID" >> .env
# Copy root .env and override with branch-specific values
cp "$SUPERSET_ROOT_PATH/.env" .env
awk -v pooled="$POOLED_URL" -v direct="$DIRECT_URL" '
/^DATABASE_URL=/ { print "DATABASE_URL=" pooled; next }
/^DATABASE_URL_UNPOOLED=/ { print "DATABASE_URL_UNPOOLED=" direct; next }
{ print }
' "$SUPERSET_ROOT_PATH/.env" > .env.tmp && mv .env.tmp .env
echo "NEON_BRANCH_ID=$BRANCH_ID" >> .env
🤖 Prompt for AI Agents
In .superset/setup.sh around lines 71 to 75, the current use of sed -i '' is
non‑portable and substituting DATABASE_URL/DATABASE_URL_UNPOOLED directly with
unescaped environment variables can break when those variables contain sed
delimiters or special chars; change the script to use a portable approach
(detect platform and use sed -i '' on macOS vs sed -i on Linux) or avoid
in‑place sed entirely by writing to a temp file and moving it over, and perform
safe variable insertion by escaping the replacement values (or using a different
delimiter that is unlikely to occur) or use a robust tool like awk/perl/envsubst
to replace the DATABASE_URL lines so values with |, /, &, etc. are handled
correctly before appending NEON_BRANCH_ID.

Comment thread .superset/setup.sh
fi

# Copy root .env and override with branch-specific values
cp "$SUPERSET_ROOT_PATH/.env" .env
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing validation and error handling for root .env copy.

Line 72 copies the root .env without checking if the source file exists or if the copy succeeds. If SUPERSET_ROOT_PATH is unset or the file doesn't exist, cp will fail silently (partially, due to set -e), but the error message will not be informative. Add explicit checks:

+[ -f "$SUPERSET_ROOT_PATH/.env" ] || error "Source .env not found at $SUPERSET_ROOT_PATH/.env"
 cp "$SUPERSET_ROOT_PATH/.env" .env
+[ -f .env ] || error "Failed to copy .env to workspace"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cp "$SUPERSET_ROOT_PATH/.env" .env
[ -f "$SUPERSET_ROOT_PATH/.env" ] || error "Source .env not found at $SUPERSET_ROOT_PATH/.env"
cp "$SUPERSET_ROOT_PATH/.env" .env
[ -f .env ] || error "Failed to copy .env to workspace"
🤖 Prompt for AI Agents
In .superset/setup.sh around line 72, the script blindly runs cp
"$SUPERSET_ROOT_PATH/.env" .env without validating SUPERSET_ROOT_PATH or the
source file and without explicit error messages; update the script to (1) verify
SUPERSET_ROOT_PATH is set and non-empty, (2) check that
"$SUPERSET_ROOT_PATH/.env" exists and is a regular readable file, (3) perform
the copy and check its exit status, and (4) print clear, actionable error
messages and exit with a non-zero status if any check or the copy fails so
failures are explicit and debuggable.

Comment thread .superset/setup.sh
sed -i '' "s|^DATABASE_URL_UNPOOLED=.*|DATABASE_URL_UNPOOLED=$DIRECT_URL|" .env
echo "NEON_BRANCH_ID=$BRANCH_ID" >> .env

success "Neon branch created: $WORKSPACE_NAME"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent success message for branch reuse vs. creation.

Line 77 always prints "Neon branch created: $WORKSPACE_NAME" even when an existing branch is reused (line 54). This is misleading. Update the message to reflect the actual action:

+if [ "$EXISTING_BRANCH" != "" ]; then
+  success "Neon branch reused: $WORKSPACE_NAME"
+else
   success "Neon branch created: $WORKSPACE_NAME"
+fi

Or move the success message into each branch of the if/else block.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
success "Neon branch created: $WORKSPACE_NAME"
if [ "$EXISTING_BRANCH" != "" ]; then
success "Neon branch reused: $WORKSPACE_NAME"
else
success "Neon branch created: $WORKSPACE_NAME"
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant