Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .ahoy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ commands:
docker compose build database
ahoy up

#;< MIGRATION
reload-db2:
usage: Reload the migration database container using local database image.
cmd: |
ahoy confirm "Running this command will replace your current database. Are you sure?" || exit 0
docker compose rm --force --stop --volumes database2
ahoy up -- --build database2
Comment on lines +166 to +168
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspect reload-db2 command in .ahoy.yml"
rg -n -C2 'reload-db2|--build database2|replace your current database' .ahoy.yml

echo
echo "Inspect database2 service definition in docker-compose.yml"
awk '
  /^database2:/ {in_block=1}
  in_block {print}
  in_block && /^  #;> MIGRATION/ {exit}
' docker-compose.yml

echo
echo "Expectation:"
echo "- database2 block contains image:"
echo "- database2 block does NOT contain build:"
echo "- then --build is a no-op for that service"

Repository: drevops/vortex

Length of output: 963


🏁 Script executed:

# Find and read the database2 service definition in docker-compose.yml
rg -A 20 "^database2:" docker-compose.yml

Repository: drevops/vortex

Length of output: 40


🏁 Script executed:

# First, check if docker-compose.yml exists and find database2 anywhere in it
echo "=== Checking for docker-compose.yml files ==="
find . -name "docker-compose*.yml" -o -name "docker-compose*.yaml" | head -20

echo
echo "=== Searching for database2 in docker-compose files ==="
rg "database2" -l docker-compose* 2>/dev/null || echo "No files matched"

echo
echo "=== Searching for database2 anywhere ==="
rg "database2" --type yaml 2>/dev/null | head -30

Repository: drevops/vortex

Length of output: 2770


🏁 Script executed:

# Read docker-compose.yml and extract the database2 service definition
rg -A 30 "^database2:" docker-compose.yml

Repository: drevops/vortex

Length of output: 40


🏁 Script executed:

# Read the docker-compose.yml file and extract database2 service
cat docker-compose.yml | grep -A 30 "database2:" | head -40

Repository: drevops/vortex

Length of output: 1209


The reload-db2 command has two issues that should be corrected.

Line 166 should explicitly mention the migration database in the confirmation prompt, and Line 168's --build flag is ineffective since database2 (which uses image: uselagoon/mysql-8.4:26.2.0) has no build: definition.

Suggested fix
-      ahoy confirm "Running this command will replace your current database. Are you sure?" || exit 0
+      ahoy confirm "Running this command will replace your current migration database. Are you sure?" || exit 0
       docker compose rm --force --stop --volumes database2
-      ahoy up -- --build database2
+      ahoy up -- database2
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.ahoy.yml around lines 166 - 168, Update the reload-db2 command so the
confirmation prompt explicitly references the migration database and remove the
ineffective --build flag when bringing up the database2 service: change the ahoy
confirm message to mention "migration database" (e.g., ahoy confirm "Running
this command will replace your migration database. Are you sure?") and replace
the ahoy up invocation that currently uses "-- --build database2" with a simple
ahoy up -- database2 (or equivalent without --build) to avoid passing a no-op
build flag for the image-backed service.

#;> MIGRATION

provision:
usage: Provision a site from the database dump or profile.
cmd: |
Expand Down
6 changes: 6 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ VORTEX_DOWNLOAD_DB2_FILE=db2.sql
# Second database download source.
VORTEX_DOWNLOAD_DB2_SOURCE=url

#;< MIGRATION_DB_DOWNLOAD_SOURCE_CONTAINER_REGISTRY
# Name of the pre-built migration database container image.
# @see https://github.com/drevops/mariadb-drupal-data to seed your DB image.
# VORTEX_DB2_IMAGE=your_org/your_site-migration:latest
#;> MIGRATION_DB_DOWNLOAD_SOURCE_CONTAINER_REGISTRY

#;< MIGRATION_DB_DOWNLOAD_SOURCE_URL
# Second database dump file sourced from a URL.
#
Expand Down
432 changes: 217 additions & 215 deletions .vortex/docs/static/img/installer.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .vortex/docs/static/img/installer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class MigrationDownloadSource extends AbstractHandler {

const LAGOON = 'lagoon';

const CONTAINER_REGISTRY = 'container_registry';

const S3 = 's3';

/**
Expand All @@ -42,6 +44,7 @@ public function options(array $responses): ?array {
self::FTP => 'FTP download',
self::ACQUIA => 'Acquia backup',
self::LAGOON => 'Lagoon environment',
self::CONTAINER_REGISTRY => 'Container registry',
self::S3 => 'S3 bucket',
];

Expand Down Expand Up @@ -112,6 +115,7 @@ public function process(): void {
MigrationDownloadSource::FTP,
MigrationDownloadSource::ACQUIA,
MigrationDownloadSource::LAGOON,
MigrationDownloadSource::CONTAINER_REGISTRY,
MigrationDownloadSource::S3,
];

Expand Down
109 changes: 109 additions & 0 deletions .vortex/installer/src/Prompts/Handlers/MigrationImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

declare(strict_types=1);

namespace DrevOps\VortexInstaller\Prompts\Handlers;

use DrevOps\VortexInstaller\Utils\Converter;
use DrevOps\VortexInstaller\Utils\Env;
use DrevOps\VortexInstaller\Utils\Validator;

class MigrationImage extends AbstractHandler {

/**
* {@inheritdoc}
*/
public function label(): string {
return 'What is your migration database container image name and a tag?';
}

/**
* {@inheritdoc}
*/
public function hint(array $responses): ?string {
return 'Use "latest" tag for the latest version. CI will be building this image overnight.';
}

/**
* {@inheritdoc}
*/
public function placeholder(array $responses): ?string {
if (isset($responses[OrgMachineName::id()]) && isset($responses[MachineName::id()])
&& !empty($responses[OrgMachineName::id()]) && !empty($responses[MachineName::id()])) {
return sprintf('E.g. %s/%s-data-migration:latest',
strtolower(Converter::phpNamespace($responses[OrgMachineName::id()])),
strtolower(Converter::phpNamespace($responses[MachineName::id()]))
);
}
Comment on lines +30 to +37
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Extract shared migration-image template generation.

The placeholder and default paths duplicate the same formatting logic; consolidate into one helper to prevent drift.

Refactor sketch
 class MigrationImage extends AbstractHandler {
+  private function buildMigrationImage(array $responses): ?string {
+    if (
+      isset($responses[OrgMachineName::id()], $responses[MachineName::id()]) &&
+      !empty($responses[OrgMachineName::id()]) &&
+      !empty($responses[MachineName::id()])
+    ) {
+      return sprintf(
+        '%s/%s-data-migration:latest',
+        strtolower(Converter::phpNamespace($responses[OrgMachineName::id()])),
+        strtolower(Converter::phpNamespace($responses[MachineName::id()]))
+      );
+    }
+    return NULL;
+  }
+
   public function placeholder(array $responses): ?string {
-    if (isset($responses[OrgMachineName::id()]) && isset($responses[MachineName::id()])
-      && !empty($responses[OrgMachineName::id()]) && !empty($responses[MachineName::id()])) {
-      return sprintf('E.g. %s/%s-data-migration:latest',
-        strtolower(Converter::phpNamespace($responses[OrgMachineName::id()])),
-        strtolower(Converter::phpNamespace($responses[MachineName::id()]))
-      );
-    }
+    $image = $this->buildMigrationImage($responses);
+    if ($image !== NULL) {
+      return sprintf('E.g. %s', $image);
+    }
 
     return parent::placeholder($responses);
   }
 
   public function default(array $responses): null|string|bool|array {
-    if (
-      isset($responses[OrgMachineName::id()]) &&
-      isset($responses[MachineName::id()]) &&
-      !empty($responses[OrgMachineName::id()]) &&
-      !empty($responses[MachineName::id()])
-    ) {
-      return sprintf(
-        '%s/%s-data-migration:latest',
-        strtolower(Converter::phpNamespace($responses[OrgMachineName::id()])),
-        strtolower(Converter::phpNamespace($responses[MachineName::id()]))
-      );
-    }
-
-    return NULL;
+    return $this->buildMigrationImage($responses);
   }

Also applies to: 60-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vortex/installer/src/Prompts/Handlers/MigrationImage.php around lines 30 -
37, Extract the duplicated migration-image formatting into a single helper
(e.g., a private static method like buildMigrationImageTemplate or
migrationImageTemplate) and update both placeholder(array $responses) and the
default-generating method (the one around lines 60-70) to call this helper; the
helper should accept the two inputs pulled from $responses using
OrgMachineName::id() and MachineName::id(), apply Converter::phpNamespace and
strtolower, and return the sprintf string ('E.g. %s/%s-data-migration:latest' or
the corresponding default value) so the formatting logic exists in one place and
both methods delegate to it.


return parent::placeholder($responses);
}

/**
* {@inheritdoc}
*/
public function dependsOn(): ?array {
return [MigrationDownloadSource::id() => [MigrationDownloadSource::CONTAINER_REGISTRY]];
}

/**
* {@inheritdoc}
*/
public function shouldRun(array $responses): bool {
return isset($responses[MigrationDownloadSource::id()]) && $responses[MigrationDownloadSource::id()] === MigrationDownloadSource::CONTAINER_REGISTRY;
}

/**
* {@inheritdoc}
*/
public function default(array $responses): null|string|bool|array {
if (
isset($responses[OrgMachineName::id()]) &&
isset($responses[MachineName::id()]) &&
!empty($responses[OrgMachineName::id()]) &&
!empty($responses[MachineName::id()])
) {
return sprintf(
'%s/%s-data-migration:latest',
strtolower(Converter::phpNamespace($responses[OrgMachineName::id()])),
strtolower(Converter::phpNamespace($responses[MachineName::id()]))
);
}

return NULL;
}

/**
* {@inheritdoc}
*/
public function discover(): null|string|bool|array {
return Env::getFromDotenv('VORTEX_DB2_IMAGE', $this->dstDir);
}

/**
* {@inheritdoc}
*/
public function validate(): ?callable {
return fn($v): ?string => Validator::containerImage($v) ? NULL : 'Please enter a valid container image name with an optional tag.';
}

/**
* {@inheritdoc}
*/
public function transform(): ?callable {
return fn($v): string => trim((string) $v);
}

/**
* {@inheritdoc}
*/
public function process(): void {
if (!empty($this->response)) {
$v = $this->getResponseAsString();
$t = $this->tmpDir;

Env::writeValueDotenv('VORTEX_DB2_IMAGE', $v, $t . '/.env');
}
}

}
11 changes: 11 additions & 0 deletions .vortex/installer/src/Prompts/PromptManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use DrevOps\VortexInstaller\Prompts\Handlers\MachineName;
use DrevOps\VortexInstaller\Prompts\Handlers\Migration;
use DrevOps\VortexInstaller\Prompts\Handlers\MigrationDownloadSource;
use DrevOps\VortexInstaller\Prompts\Handlers\MigrationImage;
use DrevOps\VortexInstaller\Prompts\Handlers\ModulePrefix;
use DrevOps\VortexInstaller\Prompts\Handlers\Modules;
use DrevOps\VortexInstaller\Prompts\Handlers\Name;
Expand Down Expand Up @@ -195,6 +196,11 @@ public function runPrompts(): void {
fn(array $r, $pr, $n): mixed => $this->prompt(MigrationDownloadSource::class, $r),
MigrationDownloadSource::id()
)
->addIf(
fn(array $r): bool => $this->handlers[MigrationImage::id()]->shouldRun($r),
fn(array $r, $pr, $n): mixed => $this->prompt(MigrationImage::class, $r),
MigrationImage::id()
)

->intro('Notifications')
->add(fn($r, $pr, $n): mixed => $this->prompt(NotificationChannels::class), NotificationChannels::id())
Expand Down Expand Up @@ -286,6 +292,7 @@ public function runProcessors(): void {
AssignAuthorPr::id(),
DependencyUpdatesProvider::id(),
CiProvider::id(),
MigrationImage::id(),
MigrationDownloadSource::id(),
Migration::id(),
DatabaseImage::id(),
Expand Down Expand Up @@ -467,6 +474,10 @@ public function getResponsesSummary(): array {
$values['Migration database'] = Converter::bool($responses[Migration::id()]);
if ($responses[Migration::id()] === TRUE && isset($responses[MigrationDownloadSource::id()])) {
$values['Migration database source'] = $responses[MigrationDownloadSource::id()];

if ($responses[MigrationDownloadSource::id()] == MigrationDownloadSource::CONTAINER_REGISTRY && isset($responses[MigrationImage::id()])) {
$values['Migration database container image'] = $responses[MigrationImage::id()];
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,31 @@
# ----------------------------------------------------------------------------
# Container commands.
# ----------------------------------------------------------------------------
@@ -117,6 +126,13 @@
cmd: |
@@ -118,6 +127,13 @@
case " $* " in *" --fresh "*) export VORTEX_DOWNLOAD_DB_FRESH=1;; esac
./scripts/vortex/download-db.sh
+
+ download-db2:
+ usage: Download second database (migration). Run with "--fresh" to force.
+ aliases: [fetch-db2]
+ cmd: |
+ case " $* " in *" --fresh "*) export VORTEX_DOWNLOAD_DB_FORCE=1;; esac
+ VORTEX_DB_INDEX=2 ./scripts/vortex/download-db.sh
+
reload-db:
usage: Reload the database container using local database image.
cmd: |
@@ -125,6 +141,13 @@
docker compose rm --force --stop --volumes database
docker compose build database
ahoy up
+
+ reload-db2:
+ usage: Reload the migration database container using local database image.
+ cmd: |
+ ahoy confirm "Running this command will replace your current database. Are you sure?" || exit 0
+ docker compose rm --force --stop --volumes database2
+ ahoy up -- --build database2

provision:
usage: Provision a site from the database dump or profile.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- '3306' # Database port in a container. Find port on host with `ahoy info` or `docker compose port database 3306`.

+ database2:
+ image: uselagoon/mysql-8.4:__VERSION__
+ image: "${VORTEX_DB2_IMAGE:-uselagoon/mysql-8.4:__VERSION__}" # Use custom database image (if defined) or fallback to standard database image.
+ environment:
+ <<: *default-environment
+ MYSQL_DATABASE: drupal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
@@ -30,6 +30,7 @@
cmd: |
export COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-${PWD##*/}}
export VORTEX_HOST_DB_PORT=$(docker compose port database 3306 2>/dev/null | cut -d : -f 2)
+ export VORTEX_HOST_DB2_PORT=$(docker compose port database2 3306 2>/dev/null | cut -d : -f 2)
export VORTEX_HOST_SOLR_PORT=$(docker compose port solr 8983 2>/dev/null | cut -d : -f 2)
export VORTEX_HOST_SELENIUM_VNC_PORT=$(docker compose port chrome 7900 2>/dev/null | cut -d : -f 2)
export VORTEX_HOST_HAS_SEQUELACE=$(uname -a | grep -i -q darwin && mdfind -name 'Sequel Ace' 2>/dev/null | grep -q "Ace" && echo 1 || true)
@@ -43,6 +44,14 @@
open "mysql://${DATABASE_USERNAME:-drupal}:${DATABASE_PASSWORD:-drupal}@127.0.0.1:${VORTEX_HOST_DB_PORT}/drupal" -a "Sequel Ace" \
|| echo "Not a supported OS or Sequel Ace is not installed."

+ db2:
+ usage: Open DB2 in Sequel Ace.
+ cmd: |
+ uname -a | grep -i -q darwin && test -d "${VORTEX_HOST_SEQUELACE_PATH:-/Applications/Sequel Ace.app}" && \
+ VORTEX_HOST_DB2_PORT=$(docker compose port database2 3306 2>/dev/null | cut -d : -f 2) && \
+ open "mysql://${DATABASE2_USERNAME:-drupal}:${DATABASE2_PASSWORD:-drupal}@127.0.0.1:${VORTEX_HOST_DB2_PORT}/drupal" -a "Sequel Ace" \
+ || echo "Not a supported OS or Sequel Ace is not installed."
+
# ----------------------------------------------------------------------------
# Container commands.
# ----------------------------------------------------------------------------
@@ -118,6 +127,13 @@
case " $* " in *" --fresh "*) export VORTEX_DOWNLOAD_DB_FRESH=1;; esac
./scripts/vortex/download-db.sh

+ download-db2:
+ usage: Download second database (migration). Run with "--fresh" to force.
+ aliases: [fetch-db2]
+ cmd: |
+ case " $* " in *" --fresh "*) export VORTEX_DOWNLOAD_DB_FORCE=1;; esac
+ VORTEX_DB_INDEX=2 ./scripts/vortex/download-db.sh
+
reload-db:
usage: Reload the database container using local database image.
cmd: |
@@ -125,6 +141,13 @@
docker compose rm --force --stop --volumes database
docker compose build database
ahoy up
+
+ reload-db2:
+ usage: Reload the migration database container using local database image.
+ cmd: |
+ ahoy confirm "Running this command will replace your current database. Are you sure?" || exit 0
+ docker compose rm --force --stop --volumes database2
+ ahoy up -- --build database2

provision:
usage: Provision a site from the database dump or profile.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@@ -170,6 +170,28 @@
VORTEX_DOWNLOAD_DB_ENVIRONMENT=prod

################################################################################
+# SECOND DATABASE (MIGRATION) #
+################################################################################
+
+# Second database for migrations.
+# See settings.migration.php for database credentials.
+
+# Second database dump file name.
+VORTEX_DOWNLOAD_DB2_FILE=db2.sql
+
+# Second database download source.
+VORTEX_DOWNLOAD_DB2_SOURCE=container_registry
+
+# Name of the pre-built migration database container image.
+# @see https://github.com/drevops/mariadb-drupal-data to seed your DB image.
+VORTEX_DB2_IMAGE=the_empire/star_wars-migration:latest
+
+# Environment to download the second database from.
+#
+# Applies to hosting environments.
+VORTEX_DOWNLOAD_DB2_ENVIRONMENT=prod
+
+################################################################################
# RELEASE VERSIONING #
################################################################################

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@@ -250,6 +250,9 @@
echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV"
timeout-minutes: 30

+ - name: Download migration DB
+ run: VORTEX_DB_INDEX=2 ./scripts/vortex/download-db.sh
+
- name: Export DB
run: |
if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi
@@ -373,6 +376,10 @@
if [ -f .data/db.sql ]; then
docker compose exec cli mkdir -p .data
docker compose cp -L .data/db.sql cli:/app/.data/db.sql
+ fi
+ if [ -f ".data/${VORTEX_DOWNLOAD_DB2_FILE:-db2.sql}" ]; then
+ docker compose exec -T cli mkdir -p .data
+ docker compose cp -L ".data/${VORTEX_DOWNLOAD_DB2_FILE:-db2.sql}" cli:"/app/.data/${VORTEX_DOWNLOAD_DB2_FILE:-db2.sql}"
fi
docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli ./scripts/vortex/provision.sh
timeout-minutes: 30
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@@ -21,6 +21,7 @@
web/sites/default/*
!web/sites/default/settings.php
!web/sites/default/services.yml
+!web/sites/default/settings.migration.php
!web/sites/default/example.settings.local.php
!web/sites/default/example.services.local.yml
!web/sites/default/default.settings.local.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@@ -17,6 +17,8 @@
"drupal/drupal_helpers": "__VERSION__",
"drupal/environment_indicator": "__VERSION__",
"drupal/generated_content": "__VERSION__",
+ "drupal/migrate_plus": "__VERSION__",
+ "drupal/migrate_tools": "__VERSION__",
"drupal/pathauto": "__VERSION__",
"drupal/redirect": "__VERSION__",
"drupal/redis": "__VERSION__",
Loading
Loading