Created
May 21, 2026 22:30
-
-
Save mattbloomfield/9da043594087b91eb1867d4cd7a71452 to your computer and use it in GitHub Desktop.
Requires our custom .helpers.sh file: https://gist.github.com/mattbloomfield/da096ba4b90e77d26a79cae0b5caad2f
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| ## Description: Sync database and/or files between two remote environments | |
| ## Usage: sync:remote | |
| ## Example: "ddev sync:remote production staging db files" | |
| source "$(dirname "$0")/.helpers.sh" | |
| ddev_setup_error_handling | |
| BUCKET_PREFIX="mysite-assets" | |
| ENTRIES_TO_ENABLE="3177012,3177117,4210469,4348080" # we have a few test entries that are disabled in prod but we enable everywhere else | |
| # ─── Help ───────────────────────────────────────────────────────────────────── | |
| if ddev_check_help "$@"; then | |
| ddev_print_help \ | |
| "Usage: ddev sync:remote [source] [destination] [db|-db] [files|assets|-files|-assets]" \ | |
| "" \ | |
| "Sync database and/or files between two remote environments." \ | |
| "" \ | |
| "Arguments:" \ | |
| " source Source environment: staging or production" \ | |
| " destination Destination environment: development or staging" \ | |
| " db Pull the database" \ | |
| " -db Skip the database" \ | |
| " files, assets Pull assets" \ | |
| " -files, -assets Skip assets" \ | |
| "" \ | |
| "Examples:" \ | |
| " ddev sync:remote # Interactive prompts" \ | |
| " ddev sync:remote production development db # Pull db from prod to dev" \ | |
| " ddev sync:remote production staging db files # Pull both to staging" | |
| fi | |
| # ─── Parse arguments ────────────────────────────────────────────────────────── | |
| SOURCE_ENV="" | |
| DESTINATION_ENV="" | |
| PULL_DB="" | |
| PULL_FILES="" | |
| # Parse positional environments and flags | |
| _SOURCE="" | |
| _DEST="" | |
| for arg in "$@"; do | |
| case $arg in | |
| development|staging|production) | |
| if [[ -z "$_SOURCE" ]]; then | |
| _SOURCE=$arg | |
| elif [[ -z "$_DEST" ]]; then | |
| _DEST=$arg | |
| fi | |
| ;; | |
| db) PULL_DB="y" ;; | |
| -db) PULL_DB="n" ;; | |
| files|assets) PULL_FILES="y" ;; | |
| -files|-assets) PULL_FILES="n" ;; | |
| esac | |
| done | |
| # Apply parsed positional environments | |
| if [[ -n "$_SOURCE" ]]; then | |
| SOURCE_ENV="$_SOURCE" | |
| fi | |
| if [[ -n "$_DEST" ]]; then | |
| DESTINATION_ENV="$_DEST" | |
| fi | |
| # ─── Prompt for missing choices ─────────────────────────────────────────────── | |
| if [[ -z "$SOURCE_ENV" ]]; then | |
| ddev_prompt_choice "Source environment" "production" "staging production" | |
| SOURCE_ENV="$REPLY" | |
| fi | |
| if [[ -z "$DESTINATION_ENV" ]]; then | |
| ddev_prompt_choice "Destination environment" "development" "development staging" | |
| DESTINATION_ENV="$REPLY" | |
| fi | |
| # Validate source != destination | |
| if [[ "$SOURCE_ENV" == "$DESTINATION_ENV" ]]; then | |
| ddev_error "Source and destination cannot be the same (${SOURCE_ENV})" | |
| exit 1 | |
| fi | |
| # Validate source can only be staging or production | |
| if [[ "$SOURCE_ENV" != "staging" && "$SOURCE_ENV" != "production" ]]; then | |
| ddev_error "Source must be 'staging' or 'production', got '${SOURCE_ENV}'" | |
| exit 1 | |
| fi | |
| # Validate destination can only be development or staging | |
| if [[ "$DESTINATION_ENV" != "development" && "$DESTINATION_ENV" != "staging" ]]; then | |
| ddev_error "Destination must be 'development' or 'staging', got '${DESTINATION_ENV}'" | |
| exit 1 | |
| fi | |
| if [[ -z "$PULL_DB" ]]; then | |
| ddev_prompt_yn "Pull database from ${YELLOW}${SOURCE_ENV}${RESET} to ${YELLOW}${DESTINATION_ENV}${RESET}?" "y" | |
| PULL_DB="$REPLY" | |
| fi | |
| if [[ -z "$PULL_FILES" ]]; then | |
| ddev_prompt_yn "Pull assets from ${YELLOW}${SOURCE_ENV}${RESET} to ${YELLOW}${DESTINATION_ENV}${RESET}?" "n" | |
| PULL_FILES="$REPLY" | |
| fi | |
| # ─── Summary + Confirm ─────────────────────────────────────────────────────── | |
| ddev_header "Remote Sync Summary" | |
| ddev_summary_line "Source" "$SOURCE_ENV" | |
| ddev_summary_line "Destination" "$DESTINATION_ENV" | |
| ddev_summary_line "Pull database" "$( [[ "$PULL_DB" == "y" ]] && echo "yes" || echo "no" )" | |
| ddev_summary_line "Pull assets" "$( [[ "$PULL_FILES" == "y" ]] && echo "yes" || echo "no" )" | |
| echo "" | |
| ddev_warn "This will modify the ${YELLOW}${DESTINATION_ENV}${RESET} environment" | |
| ddev_confirm_or_abort "Proceed with remote sync?" | |
| # ─── Sync database ─────────────────────────────────────────────────────────── | |
| if [[ "$PULL_DB" == "y" ]]; then | |
| ddev_step "Cloning database from ${YELLOW}${SOURCE_ENV}${RESET} to ${YELLOW}${DESTINATION_ENV}${RESET}" | |
| ( | |
| echo "$PULL_DB" | |
| echo "$PULL_FILES" | |
| echo "no" | |
| echo "no" | |
| ) | ./craft servd-asset-storage/clone --from="${SOURCE_ENV}" --to="${DESTINATION_ENV}" --wait | |
| ddev_step "Enabling entries on ${YELLOW}${DESTINATION_ENV}${RESET}" | |
| echo "yes" | ./craft servd-asset-storage/command "resave/entries --element-id $ENTRIES_TO_ENABLE --set enabled --to '=true'" --environment="${DESTINATION_ENV}" | |
| ddev_success "Database synced from ${SOURCE_ENV} to ${DESTINATION_ENV}" | |
| fi | |
| # ─── Sync files ────────────────────────────────────────────────────────────── | |
| if [[ "$PULL_FILES" == "y" ]]; then | |
| get_bucket() { | |
| local env=$1 | |
| case $env in | |
| development|master) echo "s3://${BUCKET_PREFIX}-development/" ;; | |
| staging) echo "s3://${BUCKET_PREFIX}-staging/" ;; | |
| production) echo "s3://${BUCKET_PREFIX}/" ;; | |
| esac | |
| } | |
| SOURCE_BUCKET=$(get_bucket "$SOURCE_ENV") | |
| DESTINATION_BUCKET=$(get_bucket "$DESTINATION_ENV") | |
| ddev_step "Syncing assets from ${YELLOW}${SOURCE_ENV}${RESET} to ${YELLOW}${DESTINATION_ENV}${RESET}" | |
| aws s3 sync --acl public-read "${SOURCE_BUCKET}" "${DESTINATION_BUCKET}" | |
| ddev_success "Assets synced from ${SOURCE_ENV} to ${DESTINATION_ENV}" | |
| fi | |
| ddev_success "Remote sync complete" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment