From f6c1107aa648e1caf7b71bd9d4dd594dcadac93c Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sun, 10 May 2026 10:49:46 -0600 Subject: [PATCH 1/5] feat(drupal-core): switch to amateescu/ddev-drupal-dev scaffolding Replace joachim-n/drupal-core-development-project (composer create-project) with a direct git clone of drupal/drupal + the amateescu/ddev-drupal-dev DDEV add-on. This eliminates ~440 lines of bash: the inline-alias JSON fixups, json-schema pin, vendor symlink restoration, and branch-aware composer update -W are no longer needed because the add-on's composer.local.json overlay keeps core's composer.json untouched. - Drupal version is now set by git branch (main/11.x/10.x), not by Composer constraints - Issue forks still work: git remote add issue + fetch + checkout - Old joachim-n workspaces are detected and kept as-is with a note to recreate; docroot auto-detects old vs new scaffolding - cache_path is now optional (default = ""); cache seed is used as a git --reference hint with fallback to direct clone - drush added via ddev composer require into composer.local.json - Welcome message and ddev launch now document ddev add-module, ddev phpunit, and link to https://github.com/amateescu/ddev-drupal-dev Closes #142 Co-Authored-By: Claude Sonnet 4.6 --- drupal-core/template.tf | 663 ++++++++++++++-------------------------- 1 file changed, 221 insertions(+), 442 deletions(-) diff --git a/drupal-core/template.tf b/drupal-core/template.tf index 137435c..9602c0f 100644 --- a/drupal-core/template.tf +++ b/drupal-core/template.tf @@ -67,6 +67,7 @@ variable "docker_registry_mirror" { variable "cache_path" { description = "Host path to the drupal-core seed cache directory (mounted read-only into workspaces)" type = string + default = "" } # Per-workspace user parameters (shown in workspace creation UI, pre-fillable via ?param.name=value URL) @@ -558,12 +559,109 @@ STATUS_HEADER # Ensure we're starting from home directory cd /home/coder || exit 1 - # Step 1: Create project directory and configure DDEV - if [ ! -d "$DRUPAL_DIR" ]; then - log_setup "Creating project directory: $DRUPAL_DIR" - mkdir -p "$DRUPAL_DIR" + # Issue fork / install profile parameters (evaluated at template build time) + ISSUE_FORK="${data.coder_parameter.issue_fork.value}" + ISSUE_FORK="$${ISSUE_FORK#drupal-}" + ISSUE_BRANCH="${data.coder_parameter.issue_branch.value}" + INSTALL_PROFILE="${data.coder_parameter.install_profile.value}" + + # Fetch issue title from drupal.org API (best-effort) + ISSUE_TITLE="" + if [ -n "$ISSUE_FORK" ]; then + ISSUE_TITLE=$(curl -sf "https://www.drupal.org/api-d7/node/$${ISSUE_FORK}.json" 2>/dev/null | jq -r '.title // ""' 2>/dev/null || echo "") fi - + + USING_ISSUE_FORK=false + SETUP_FAILED=false + if [ -n "$ISSUE_FORK" ] || [ -n "$ISSUE_BRANCH" ]; then + USING_ISSUE_FORK=true + log_setup "Issue fork mode: ISSUE_FORK=$ISSUE_FORK ISSUE_BRANCH=$ISSUE_BRANCH INSTALL_PROFILE=$INSTALL_PROFILE" + fi + + if [ -n "$ISSUE_FORK" ]; then + log_setup "๐Ÿ”— Issue: https://www.drupal.org/project/drupal/issues/$ISSUE_FORK" + if [ -n "$ISSUE_TITLE" ]; then log_setup " Title: $ISSUE_TITLE"; fi + fi + + # Step 1: Clone Drupal core (first run) or verify existing checkout + CACHE_SEED="/home/coder-cache-seed" + SETUP_START=$SECONDS + DRUPAL_SETUP_NEEDED=false + + if [ -d "$DRUPAL_DIR/repos/drupal/.git" ]; then + # Old joachim-n scaffolding detected โ€” existing workspace, skip clone. + # Drupal continues to work with the existing setup; recreate the workspace to + # switch to the new amateescu/ddev-drupal-dev scaffolding. + log_setup "โš  Old scaffolding (repos/drupal/) detected โ€” keeping existing setup" + log_setup " Recreate this workspace to migrate to the new scaffolding." + update_status "โœ“ Setup: Existing old-scaffolding workspace" + elif [ ! -d "$DRUPAL_DIR/.git" ]; then + DRUPAL_SETUP_NEEDED=true + update_status "โณ Git clone: In progress..." + _t=$SECONDS + if [ -d "$CACHE_SEED/repos/drupal/.git" ]; then + log_setup "Cloning Drupal core (with reference from cache seed)..." + git clone --reference "$CACHE_SEED/repos/drupal" https://git.drupalcode.org/project/drupal.git "$DRUPAL_DIR" >> "$SETUP_LOG" 2>&1 || \ + git clone https://git.drupalcode.org/project/drupal.git "$DRUPAL_DIR" >> "$SETUP_LOG" 2>&1 + else + log_setup "Cloning Drupal core..." + git clone https://git.drupalcode.org/project/drupal.git "$DRUPAL_DIR" >> "$SETUP_LOG" 2>&1 + fi + if [ -d "$DRUPAL_DIR/.git" ]; then + log_setup "โœ“ Drupal core cloned ($((SECONDS - _t))s)" + update_status "โœ“ Git clone: Success" + else + log_setup "โœ— Failed to clone Drupal core" + update_status "โœ— Git clone: Failed" + SETUP_FAILED=true + fi + + # Branch or fork checkout + if [ "$SETUP_FAILED" != "true" ] && [ "$USING_ISSUE_FORK" = "true" ] && [ -n "$ISSUE_FORK" ]; then + log_setup "Adding issue fork remote and fetching: $ISSUE_FORK" + git -C "$DRUPAL_DIR" remote add issue "https://git.drupalcode.org/issue/drupal-$${ISSUE_FORK}.git" + if git -C "$DRUPAL_DIR" fetch issue >> "$SETUP_LOG" 2>&1; then + log_setup " โœ“ Fetched from issue remote" + if [ -n "$ISSUE_BRANCH" ]; then + if git -C "$DRUPAL_DIR" checkout -b "$ISSUE_BRANCH" "issue/$ISSUE_BRANCH" >> "$SETUP_LOG" 2>&1 || \ + git -C "$DRUPAL_DIR" checkout "$ISSUE_BRANCH" >> "$SETUP_LOG" 2>&1; then + log_setup " โœ“ Checked out branch: $ISSUE_BRANCH" + else + log_setup "โœ— Failed to check out branch $ISSUE_BRANCH" + SETUP_FAILED=true + fi + fi + else + log_setup "โœ— Failed to fetch from issue remote $ISSUE_FORK" + SETUP_FAILED=true + fi + elif [ "$SETUP_FAILED" != "true" ] && [ "$DRUPAL_BRANCH" != "main" ]; then + if [ "$DRUPAL_BRANCH" = "10.x" ]; then + _r=$(git -C "$DRUPAL_DIR" branch -r 2>/dev/null | grep -oE "10\.[0-9]+\.x" | sort -V | tail -1 || echo "") + [ -n "$_r" ] && { DRUPAL_BRANCH="$_r"; log_setup " Resolved Drupal 10 branch โ†’ $DRUPAL_BRANCH"; } + fi + if git -C "$DRUPAL_DIR" checkout "$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1; then + log_setup "โœ“ Checked out branch: $DRUPAL_BRANCH" + else + log_setup "โœ— Failed to check out $DRUPAL_BRANCH" + SETUP_FAILED=true + fi + fi + else + log_setup "โœ“ Drupal core already cloned โ€” skipping git clone" + update_status "โœ“ Setup: Already present" + if [ "$USING_ISSUE_FORK" = "false" ]; then + _t=$SECONDS + if [ "$DRUPAL_BRANCH" = "10.x" ]; then + _r=$(git -C "$DRUPAL_DIR" branch -r 2>/dev/null | grep -oE "10\.[0-9]+\.x" | sort -V | tail -1 || echo "") + [ -n "$_r" ] && DRUPAL_BRANCH="$_r" + fi + git -C "$DRUPAL_DIR" fetch --all --prune >> "$SETUP_LOG" 2>&1 || true + git -C "$DRUPAL_DIR" merge --ff-only "origin/$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || true + log_setup " git fetch+merge $DRUPAL_BRANCH complete ($((SECONDS - _t))s)" + fi + fi + cd "$DRUPAL_DIR" || exit 1 # Step 2: Configure DDEV (must be done before composer create) @@ -589,6 +687,13 @@ STATUS_HEADER log_setup "Configuring DDEV for Drupal $DRUPAL_VERSION ($DDEV_PROJECT_TYPE)..." update_status "โณ DDEV config: In progress..." + # Detect docroot: old joachim-n scaffolding uses web/ symlink; direct git clone has index.php at root. + DDEV_DOCROOT_ARG="" + if [ -d "repos/drupal/.git" ] || [ -L "web" ]; then + DDEV_DOCROOT_ARG="--docroot=web" + log_setup " Detected old scaffolding โ€” using --docroot=web" + fi + # Compute Coder domain for use in DDEV configuration CODER_DOMAIN="" if [ -n "$CODER_WORKSPACE_OWNER_NAME" ] && ([ -n "$VSCODE_PROXY_URI" ] || [ -n "$CODER_AGENT_URL" ]); then @@ -619,8 +724,8 @@ hooks: CODER_YAML_EOF log_setup "โœ“ .ddev/config.coder.yaml written" - if ddev config --project-type="$DDEV_PROJECT_TYPE" --docroot=web --project-name="$${CODER_WORKSPACE_NAME}--$${CODER_WORKSPACE_OWNER_NAME}" >> "$SETUP_LOG" 2>&1; then - log_setup "โœ“ DDEV configured (project-type=$DDEV_PROJECT_TYPE docroot=web)" + if ddev config --project-type="$DDEV_PROJECT_TYPE" $DDEV_DOCROOT_ARG --project-name="$${CODER_WORKSPACE_NAME}--$${CODER_WORKSPACE_OWNER_NAME}" >> "$SETUP_LOG" 2>&1; then + log_setup "โœ“ DDEV configured (project-type=$DDEV_PROJECT_TYPE)" update_status "โœ“ DDEV config: Success" else log_setup "โœ— Failed to configure DDEV" @@ -629,7 +734,7 @@ CODER_YAML_EOF update_status "" update_status "Manual recovery:" update_status " cd $DRUPAL_DIR" - update_status " ddev config --project-type=$DDEV_PROJECT_TYPE --docroot=web" + update_status " ddev config --project-type=$DDEV_PROJECT_TYPE $DDEV_DOCROOT_ARG" fi # Configure DDEV global settings (omit router) @@ -690,64 +795,7 @@ COMPOSE_EOF update_status " Check: docker ps, docker logs" fi - CACHE_SEED="/home/coder-cache-seed" - DRUPAL_SETUP_NEEDED=false - ISSUE_FORK_CHECKOUT_DONE=false - SETUP_START=$SECONDS - - # Diagnostic: report what the cache mount contains - log_setup "Cache mount check: $CACHE_SEED" - if [ -f "$CACHE_SEED/composer.json" ]; then - log_setup " composer.json: present" - else - log_setup " composer.json: MISSING (cache not seeded or bind mount empty)" - fi - if [ -d "$CACHE_SEED/repos/drupal/.git" ]; then - log_setup " repos/drupal/.git: present" - else - log_setup " repos/drupal/.git: MISSING" - fi - if [ -f "$CACHE_SEED/.tarballs/db.sql.gz" ]; then - log_setup " .tarballs/db.sql.gz: present ($(du -sh $CACHE_SEED/.tarballs/db.sql.gz 2>/dev/null | cut -f1))" - else - log_setup " .tarballs/db.sql.gz: MISSING" - fi - - # Issue fork / install profile parameters (baked in at template evaluation) - ISSUE_FORK="${data.coder_parameter.issue_fork.value}" - ISSUE_FORK="$${ISSUE_FORK#drupal-}" # strip leading "drupal-" if user provided it - ISSUE_BRANCH="${data.coder_parameter.issue_branch.value}" - INSTALL_PROFILE="${data.coder_parameter.install_profile.value}" - - # Fetch issue title from drupal.org API at runtime (best-effort; empty string on failure) - ISSUE_TITLE="" - if [ -n "$ISSUE_FORK" ]; then - ISSUE_TITLE=$(curl -sf "https://www.drupal.org/api-d7/node/$${ISSUE_FORK}.json" 2>/dev/null | jq -r '.title // ""' 2>/dev/null || echo "") - fi - USING_ISSUE_FORK=false - SETUP_FAILED=false - if [ -n "$ISSUE_FORK" ] || [ -n "$ISSUE_BRANCH" ]; then - USING_ISSUE_FORK=true - log_setup "Issue fork mode: ISSUE_FORK=$ISSUE_FORK ISSUE_BRANCH=$ISSUE_BRANCH INSTALL_PROFILE=$INSTALL_PROFILE" - fi - - # Non-main versions (10.x, 11.x) without an issue fork also need branch checkout + - # composer.json fixes + composer update โ€” cannot use the main-branch cached DB. - NEEDS_NONMAIN_CHECKOUT=false - if [ "$DRUPAL_BRANCH" != "main" ] && [ "$USING_ISSUE_FORK" = "false" ]; then - NEEDS_NONMAIN_CHECKOUT=true - log_setup "Non-main version mode: DRUPAL_VERSION=$DRUPAL_VERSION DRUPAL_BRANCH=$DRUPAL_BRANCH INSTALL_PROFILE=$INSTALL_PROFILE" - fi - - # Log issue link early so it's visible at the top of the agent logs - if [ -n "$ISSUE_FORK" ]; then - log_setup "๐Ÿ”— Issue: https://www.drupal.org/project/drupal/issues/$ISSUE_FORK" - if [ -n "$ISSUE_TITLE" ]; then - log_setup " Title: $ISSUE_TITLE" - fi - fi - - # Create Drupal-specific welcome message (first run only, now that issue info is available) + # Create Drupal-specific welcome message (ISSUE_FORK and ISSUE_TITLE already set above) { cat << 'WELCOME_STATIC' Drupal Core Development Workspace @@ -761,7 +809,11 @@ Commands: ddev logs # View container logs ddev ssh # SSH into web container -Docs: https://docs.ddev.com/ + ddev add-module # Clone a contrib module for development + ddev phpunit [--db=sqlite|mysql|pgsql] # Run PHPUnit tests + +Add-on docs: https://github.com/amateescu/ddev-drupal-dev +DDEV docs: https://docs.ddev.com/ WELCOME_STATIC if [ -n "$ISSUE_FORK" ]; then @@ -772,399 +824,122 @@ WELCOME_STATIC } > ~/WELCOME.txt chown coder:coder ~/WELCOME.txt 2>/dev/null || true - # Step 4: Set up Drupal core project โ€” use seed cache for main branch only (fast path) - # Issue forks and non-main plain versions (10.x, 11.x) skip the cache: the seed - # composer.json has "drupal/core: dev-main" and vendor is resolved for PHP 8.5/drupal12, - # both incompatible with non-main branches. The else branch handles those with a fresh - # composer create-project (and supplements git objects from the seed for speed). - if [ -f "composer.json" ] && [ -d "repos/drupal/.git" ]; then - log_setup "โœ“ Drupal core project already present โ€” skipping setup" - update_status "โœ“ Setup: Already present" - # For non-issue-fork workspaces, keep the drupal repo current on every start - if [ "$USING_ISSUE_FORK" = "false" ]; then - _t=$SECONDS - git -C "$DRUPAL_DIR/repos/drupal" fetch --all --prune >> "$SETUP_LOG" 2>&1 || true - # Resolve 10.x placeholder to actual latest remote minor (e.g. 10.6.x) - if [ "$DRUPAL_BRANCH" = "10.x" ]; then - _r=$(git -C "$DRUPAL_DIR/repos/drupal" branch -r 2>/dev/null | grep -oE "10\.[0-9]+\.x" | sort -V | tail -1 || echo "") - [ -n "$_r" ] && { DRUPAL_BRANCH="$_r"; log_setup " Resolved Drupal 10 branch โ†’ $DRUPAL_BRANCH"; } - fi - CURRENT_BRANCH=$(git -C "$DRUPAL_DIR/repos/drupal" branch --show-current 2>/dev/null || echo "") - if [ "$CURRENT_BRANCH" = "$DRUPAL_BRANCH" ]; then - git -C "$DRUPAL_DIR/repos/drupal" merge --ff-only "origin/$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || true - log_setup " git fetch+merge $DRUPAL_BRANCH complete ($((SECONDS - _t))s)" - else - log_setup " โš  Branch mismatch: repo is on '$CURRENT_BRANCH', need '$DRUPAL_BRANCH' โ€” switching..." - git -C "$DRUPAL_DIR/repos/drupal" checkout "$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || \ - git -C "$DRUPAL_DIR/repos/drupal" checkout -b "$DRUPAL_BRANCH" "origin/$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || true - log_setup " git checkout $DRUPAL_BRANCH complete ($((SECONDS - _t))s)" - # vendor is from the old branch โ€” trigger composer.json fixes + update below - [ "$DRUPAL_BRANCH" != "main" ] && DRUPAL_SETUP_NEEDED=true - fi - fi - # If non-main branch: check vendor stamp to catch cases where vendor is stale - # (e.g. recycled host directory where branch was switched but composer update never ran) - if [ "$DRUPAL_BRANCH" != "main" ] && [ "$USING_ISSUE_FORK" = "false" ] && [ "$DRUPAL_SETUP_NEEDED" = "false" ]; then - _vendor_branch=$(cat "$DRUPAL_DIR/.vendor-branch" 2>/dev/null || echo "") - if [ "$_vendor_branch" != "$DRUPAL_BRANCH" ]; then - log_setup " Vendor stamp is '$_vendor_branch', need '$DRUPAL_BRANCH' โ€” triggering composer update..." - DRUPAL_SETUP_NEEDED=true - fi - fi - elif [ "$USING_ISSUE_FORK" = "false" ] && [ "$DRUPAL_BRANCH" = "main" ] && [ -f "$CACHE_SEED/composer.json" ] && [ -d "$CACHE_SEED/repos/drupal/.git" ]; then + # Step 4: Install ddev-drupal-dev add-on, composer install, and drush (first run only) + if [ "$DRUPAL_SETUP_NEEDED" = "true" ] && [ "$SETUP_FAILED" != "true" ]; then + log_setup "Installing amateescu/ddev-drupal-dev add-on..." + update_status "โณ DDEV add-on install: In progress..." _t=$SECONDS - log_setup "Cache hit: seeding project from host cache (fast path)..." - update_status "โณ DDEV setup: Seeding from cache..." - # Copy everything except .ddev/ โ€” workspace generates its own DDEV config - if rsync -a --exclude='.ddev/' --exclude='.tarballs/' "$CACHE_SEED/" "$DRUPAL_DIR/" >> "$SETUP_LOG" 2>&1; then - log_setup " rsync complete ($((SECONDS - _t))s)" - # Bring git checkout up to date (fast โ€” objects already present locally) - _t=$SECONDS - git -C "$DRUPAL_DIR/repos/drupal" fetch --all --prune >> "$SETUP_LOG" 2>&1 || true - log_setup " git fetch complete ($((SECONDS - _t))s)" - # Resolve 10.x placeholder to actual latest remote minor (e.g. 10.6.x) - if [ "$DRUPAL_BRANCH" = "10.x" ]; then - _r=$(git -C "$DRUPAL_DIR/repos/drupal" branch -r 2>/dev/null | grep -oE "10\.[0-9]+\.x" | sort -V | tail -1 || echo "") - [ -n "$_r" ] && { DRUPAL_BRANCH="$_r"; log_setup " Resolved Drupal 10 branch โ†’ $DRUPAL_BRANCH"; } - fi - if [ "$DRUPAL_BRANCH" = "main" ]; then - # Sync vendor with the (unchanged main-branch) lock file - _t=$SECONDS - ddev composer install >> "$SETUP_LOG" 2>&1 - log_setup " composer install complete ($((SECONDS - _t))s)" - else - # Non-main: checkout target branch now; composer.json fixes + update run below - git -C "$DRUPAL_DIR/repos/drupal" checkout -b "$DRUPAL_BRANCH" "origin/$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || \ - git -C "$DRUPAL_DIR/repos/drupal" checkout "$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || true - log_setup " git checkout $DRUPAL_BRANCH complete" - fi - log_setup "โœ“ Cache seed complete ($((SECONDS - SETUP_START))s total so far)" - update_status "โœ“ DDEV composer create: Seeded from cache" - DRUPAL_SETUP_NEEDED=true + if ddev add-on get amateescu/ddev-drupal-dev >> "$SETUP_LOG" 2>&1; then + log_setup "โœ“ Add-on installed ($((SECONDS - _t))s)" + update_status "โœ“ DDEV add-on install: Success" else - log_setup "โœ— Failed to seed from cache ($((SECONDS - _t))s), falling back to full setup..." - update_status "โš  Cache seed failed, running full setup..." - ddev composer create-project --no-interaction joachim-n/drupal-core-development-project . >> "$SETUP_LOG" 2>&1 - DRUPAL_SETUP_NEEDED=true + log_setup "โœ— Failed to install add-on ($((SECONDS - _t))s)" + update_status "โœ— DDEV add-on install: Failed" + SETUP_FAILED=true fi - else - _t=$SECONDS - if [ "$USING_ISSUE_FORK" = "true" ]; then - # Issue fork: create project structure WITHOUT installing dependencies. - # We must checkout the issue branch before composer install so that vendor - # is resolved for the correct branch, not for main/drupal12. - log_setup "Issue fork: creating project structure (dependencies installed after branch checkout)..." - update_status "โณ DDEV composer create-project: In progress..." - - if ddev composer create-project --no-install --no-interaction "joachim-n/drupal-core-development-project" . >> "$SETUP_LOG" 2>&1; then - log_setup "โœ“ Project structure created ($((SECONDS - _t))s)" - update_status "โœ“ DDEV composer create-project: Success" - DRUPAL_SETUP_NEEDED=true - # Supplement git objects from seed cache so issue-branch fetch only downloads the delta - if [ -d "$CACHE_SEED/repos/drupal/.git/objects" ]; then - log_setup "Supplementing git objects from seed cache..." - rsync -a "$CACHE_SEED/repos/drupal/.git/objects/" "$DRUPAL_DIR/repos/drupal/.git/objects/" >> "$SETUP_LOG" 2>&1 || true - log_setup " git objects supplement complete" - fi - else - log_setup "โœ— Failed to create project structure ($((SECONDS - _t))s)" - log_setup "Check $SETUP_LOG for details" - update_status "โœ— DDEV composer create-project: Failed" - update_status "" - update_status "Manual recovery:" - update_status " cd $DRUPAL_DIR && ddev composer create-project --no-install \"joachim-n/drupal-core-development-project\" ." - fi - elif [ "$NEEDS_NONMAIN_CHECKOUT" = "true" ]; then - # Non-main version (10.x/11.x) without cache: create project structure then checkout branch. - # Must use --no-install (like issue fork) so vendor is resolved for the correct branch. - log_setup "Creating project structure for Drupal $DRUPAL_VERSION ($DRUPAL_BRANCH), no cache available..." - update_status "โณ DDEV composer create-project: In progress..." - if ddev composer create-project --no-install --no-interaction "joachim-n/drupal-core-development-project" . >> "$SETUP_LOG" 2>&1; then - log_setup "โœ“ Project structure created ($((SECONDS - _t))s)" - update_status "โœ“ DDEV composer create-project: Success" - DRUPAL_SETUP_NEEDED=true - # Supplement git objects from seed cache so branch fetch only downloads the delta - if [ -d "$CACHE_SEED/repos/drupal/.git/objects" ]; then - log_setup "Supplementing git objects from seed cache..." - rsync -a "$CACHE_SEED/repos/drupal/.git/objects/" "$DRUPAL_DIR/repos/drupal/.git/objects/" >> "$SETUP_LOG" 2>&1 || true - log_setup " git objects supplement complete" - fi - else - log_setup "โœ— Failed to create project structure ($((SECONDS - _t))s)" - log_setup "Check $SETUP_LOG for details" - update_status "โœ— DDEV composer create-project: Failed" - update_status "" - update_status "Manual recovery:" - update_status " cd $DRUPAL_DIR && ddev composer create-project --no-install \"joachim-n/drupal-core-development-project\" ." - fi - else - log_setup "No cache available, running full composer create..." - update_status "โณ DDEV composer create: In progress..." - if ddev composer create-project --no-interaction joachim-n/drupal-core-development-project . >> "$SETUP_LOG" 2>&1; then - log_setup "โœ“ Drupal core development project created ($((SECONDS - _t))s)" - update_status "โœ“ DDEV composer create-project: Success" - DRUPAL_SETUP_NEEDED=true - else - log_setup "โœ— Failed to create Drupal core development project ($((SECONDS - _t))s)" - log_setup "Check $SETUP_LOG for details" - update_status "โœ— DDEV composer create-project: Failed" - update_status "" - update_status "Manual recovery:" - update_status " cd $DRUPAL_DIR && ddev composer create-project joachim-n/drupal-core-development-project ." - fi - fi - fi + if [ "$SETUP_FAILED" != "true" ]; then + log_setup "Restarting DDEV to activate add-on..." + ddev restart >> "$SETUP_LOG" 2>&1 || true - # Steps 5-7: run whenever project files are present โ€” inner checks handle idempotency - if [ -f "composer.json" ] && [ -d "repos/drupal" ]; then - # Step 4.5: Branch checkout, composer.json fixes, and composer update. - # Applies to: (a) issue forks, and (b) non-main versions (10.x/11.x) without an issue fork. - # In both cases the project was created with --no-install so no vendor exists yet. - # The branch must be checked out BEFORE composer install so that vendor is - # resolved for the correct Drupal version, not for main/drupal12. - if ([ "$USING_ISSUE_FORK" = "true" ] || ([ "$NEEDS_NONMAIN_CHECKOUT" = "true" ] && [ "$DRUPAL_SETUP_NEEDED" = "true" ])) && [ "$ISSUE_FORK_CHECKOUT_DONE" = "false" ]; then - REPOS_DIR="$DRUPAL_DIR/repos/drupal" - if [ -d "$REPOS_DIR/.git" ]; then - if [ "$USING_ISSUE_FORK" = "true" ]; then - # Issue fork: add the fork remote and checkout the issue branch - CURRENT_BRANCH=$(git -C "$REPOS_DIR" branch --show-current 2>/dev/null || echo "") - if [ -n "$ISSUE_BRANCH" ] && [ "$CURRENT_BRANCH" = "$ISSUE_BRANCH" ]; then - log_setup "โœ“ Already on issue branch: $ISSUE_BRANCH" - else - if [ -n "$ISSUE_FORK" ]; then - log_setup "Adding issue fork remote and fetching: $ISSUE_FORK" - git -C "$REPOS_DIR" remote remove issue 2>/dev/null || true - git -C "$REPOS_DIR" remote add issue "https://git.drupalcode.org/issue/drupal-$ISSUE_FORK.git" - if git -C "$REPOS_DIR" fetch issue >> "$SETUP_LOG" 2>&1; then - log_setup " โœ“ Fetched from issue remote" - else - log_setup "โœ— Failed to fetch from issue remote $ISSUE_FORK โ€” aborting setup" - SETUP_FAILED=true - fi - fi - if [ "$SETUP_FAILED" != "true" ] && [ -n "$ISSUE_BRANCH" ]; then - log_setup "Checking out issue branch: $ISSUE_BRANCH" - if git -C "$REPOS_DIR" checkout -b "$ISSUE_BRANCH" "issue/$ISSUE_BRANCH" >> "$SETUP_LOG" 2>&1 || \ - git -C "$REPOS_DIR" checkout "$ISSUE_BRANCH" >> "$SETUP_LOG" 2>&1; then - log_setup " โœ“ Checked out branch: $ISSUE_BRANCH" - else - log_setup "โœ— Failed to check out branch $ISSUE_BRANCH โ€” aborting setup" - SETUP_FAILED=true - fi - fi - fi - else - # Non-main version without issue fork: fetch + checkout branch from origin - git -C "$REPOS_DIR" fetch --all --prune >> "$SETUP_LOG" 2>&1 || true - # Resolve 10.x placeholder to actual latest remote minor (e.g. 10.6.x) - if [ "$DRUPAL_BRANCH" = "10.x" ]; then - _r=$(git -C "$REPOS_DIR" branch -r 2>/dev/null | grep -oE "10\.[0-9]+\.x" | sort -V | tail -1 || echo "") - [ -n "$_r" ] && { DRUPAL_BRANCH="$_r"; log_setup " Resolved Drupal 10 branch โ†’ $DRUPAL_BRANCH"; } - fi - CURRENT_BRANCH=$(git -C "$REPOS_DIR" branch --show-current 2>/dev/null || echo "") - if [ "$CURRENT_BRANCH" = "$DRUPAL_BRANCH" ]; then - log_setup "โœ“ Already on $DRUPAL_BRANCH" - else - log_setup "Checking out $DRUPAL_BRANCH from origin..." - if git -C "$REPOS_DIR" checkout -b "$DRUPAL_BRANCH" "origin/$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1 || \ - git -C "$REPOS_DIR" checkout "$DRUPAL_BRANCH" >> "$SETUP_LOG" 2>&1; then - log_setup " โœ“ Checked out $DRUPAL_BRANCH" - else - log_setup "โœ— Failed to check out $DRUPAL_BRANCH โ€” aborting setup" - SETUP_FAILED=true - fi - fi - fi - - # Apply composer.json fixes so ddev composer update resolves correctly. - # joachim-n/drupal-core-development-project uses "*" for all drupal/* - # root constraints and includes repos/drupal/composer/Plugin/* as a glob path repo - # (so RecipeUnpack is covered). However, transitive constraints BETWEEN path repo - # issue fork branches need Fix 1+2: e.g. drupal/core-recommended requires drupal/core - # 11.x-dev but an issue fork presents as dev-ISSUEBRANCH, requiring an inline alias. - # Named release branches (10.6.x, 11.x) present at 10.6.x-dev naturally and need no - # fix. For 12.x the 12.x-dev alias = dev-main on Packagist โ€” also no fix needed. - if [ "$SETUP_FAILED" = "true" ]; then - log_setup "โœ— Skipping composer.json fixes due to branch checkout failure" - else - # Detect actual Drupal major version from CoreRecommended's constraint on disk - # (e.g. "10.5.x-dev" โ†’ "10", "11.x-dev" โ†’ "11") rather than trusting the - # user-selected DRUPAL_VERSION โ€” users sometimes select the wrong version. - CHECKED_OUT_BRANCH=$(git -C "$REPOS_DIR" branch --show-current 2>/dev/null || echo "") - TARGET_ALIAS=$(jq -r '.require["drupal/core"]' \ - "$REPOS_DIR/composer/Metapackage/CoreRecommended/composer.json" 2>/dev/null || echo "") - ACTUAL_DRUPAL_MAJOR=$(echo "$TARGET_ALIAS" | grep -oE '^[0-9]+' || echo "$DRUPAL_VERSION") - if [ -n "$TARGET_ALIAS" ] && [ -n "$CHECKED_OUT_BRANCH" ]; then - log_setup " Detected Drupal $ACTUAL_DRUPAL_MAJOR.x (CoreRecommended requires $TARGET_ALIAS)" - if [ "$ACTUAL_DRUPAL_MAJOR" != "$DRUPAL_VERSION" ]; then - log_setup " โš  Drupal version mismatch: user selected $DRUPAL_VERSION but branch is actually $ACTUAL_DRUPAL_MAJOR.x" - fi - else - log_setup " โš  Could not detect Drupal version (CHECKED_OUT_BRANCH='$CHECKED_OUT_BRANCH' TARGET_ALIAS='$TARGET_ALIAS')" - ACTUAL_DRUPAL_MAJOR="$DRUPAL_VERSION" - fi - - # Fix 1+2 (issue forks on 10.x/11.x only): inline alias so path repo packages - # satisfy each other's N.x-dev constraints. Issue fork branches present as - # dev-ISSUEBRANCH which doesn't satisfy drupal/core-recommended's N.x-dev - # requirement โ€” the inline alias bridges this gap. - # Named release branches (10.6.x, 11.x) already present at 10.6.x-dev / 11.x-dev - # matching what core-recommended requires, so the original "*" constraints work fine. - # 12.x also needs no fix (12.x-dev = dev-main on Packagist). - if [ "$ACTUAL_DRUPAL_MAJOR" != "12" ] && [ "$USING_ISSUE_FORK" = "true" ]; then - jq --arg val "dev-$CHECKED_OUT_BRANCH as $TARGET_ALIAS" \ - '.require |= with_entries(if (.key | startswith("drupal/")) and .key != "drupal/drupal" then .value = $val else . end)' \ - composer.json > composer.json.tmp && mv composer.json.tmp composer.json - log_setup " Set inline alias for all drupal/* packages: dev-$CHECKED_OUT_BRANCH as $TARGET_ALIAS" - jq --arg branch "dev-$CHECKED_OUT_BRANCH" \ - '.require["drupal/drupal"] = $branch' \ - composer.json > composer.json.tmp && mv composer.json.tmp composer.json - log_setup " Pinned drupal/drupal to path repo: dev-$CHECKED_OUT_BRANCH" - fi - - # Fix 3: drupal/core-dev on some branches (10.x, 11.2.x, ...) requires - # justinrainbow/json-schema ^5.2, but composer 2.9.x requires ^6.5.1 โ€” conflict. - # Detect from the actual path repo rather than assuming by major version. - # See https://www.drupal.org/project/drupal/issues/3557585 - _core_dev_json_schema=$(jq -r '.require["justinrainbow/json-schema"] // ""' \ - "$REPOS_DIR/composer/Metapackage/DevDependencies/composer.json" 2>/dev/null || echo "") - if echo "$_core_dev_json_schema" | grep -q '^\^5'; then - jq '.require["composer/composer"] = "~2.8.1" | .config.audit["block-insecure"] = false' \ - composer.json > composer.json.tmp && mv composer.json.tmp composer.json - log_setup " Applied composer/composer pin to ~2.8.1 (json-schema conflict detected)" - fi - - # Allow all Composer plugins โ€” issue fork packages (e.g. symfony/runtime) may - # introduce plugins not listed in the project's allow-plugins config. - ddev composer config allow-plugins true >> "$SETUP_LOG" 2>&1 - - # Now resolve dependencies for the checked-out issue branch. - # Use 'update -W' (not 'install') so composer re-solves the full dependency graph - # with the new composer.json constraints rather than trying to honour a stale lock file. - log_setup "Running composer update -W for issue branch..." - update_status "โณ Composer update for issue branch: In progress..." - _t=$SECONDS - ddev composer update -W 2>&1 | tee -a "$SETUP_LOG" - _composer_exit=$${PIPESTATUS[0]} - if [ "$_composer_exit" = "0" ]; then - log_setup "โœ“ Composer update complete ($((SECONDS - _t))s)" - update_status "โœ“ Composer update for issue branch: Success" - # Write stamp so "already present" restarts know vendor is valid for this branch - echo "$DRUPAL_BRANCH" > "$DRUPAL_DIR/.vendor-branch" - else - log_setup "โœ— Composer update failed (exit $_composer_exit, $((SECONDS - _t))s) โ€” skipping remaining setup" - update_status "โœ— Composer update for issue branch: Failed" - update_status "" - update_status "Manual recovery:" - update_status " cd $DRUPAL_DIR && ddev composer update -W" - SETUP_FAILED=true - fi - fi # end SETUP_FAILED (branch checkout) guard + log_setup "Running composer install..." + update_status "โณ Composer install: In progress..." + _t=$SECONDS + ddev composer install 2>&1 | tee -a "$SETUP_LOG" + _composer_exit=$${PIPESTATUS[0]} + if [ "$_composer_exit" = "0" ]; then + log_setup "โœ“ Composer install complete ($((SECONDS - _t))s)" + update_status "โœ“ Composer install: Success" + else + log_setup "โœ— Composer install failed (exit $_composer_exit, $((SECONDS - _t))s)" + update_status "โœ— Composer install: Failed" + SETUP_FAILED=true fi fi - # Step 4.9: Restore repos/drupal/vendor symlink if missing. - # This symlink (repos/drupal/vendor -> ../../vendor) is created by joachim-n's - # post-install scripts. It can be absent when a previous workspace attempt failed - # before composer install completed. - if [ -d "repos/drupal/.git" ] && [ ! -e "repos/drupal/vendor" ] && [ ! -L "repos/drupal/vendor" ]; then - log_setup "Restoring missing repos/drupal/vendor symlink..." - ln -s ../../vendor repos/drupal/vendor && log_setup " symlink restored" || log_setup " symlink restore failed (non-critical)" - elif [ -d "repos/drupal/.git" ] && [ -L "repos/drupal/vendor" ] && [ ! -e "repos/drupal/vendor" ]; then - log_setup "Fixing broken repos/drupal/vendor symlink..." - ln -sf ../../vendor repos/drupal/vendor && log_setup " symlink fixed" || log_setup " symlink fix failed (non-critical)" - fi - - # Steps 5 and 6 are skipped if an earlier step (e.g. composer update) failed. - if [ "$SETUP_FAILED" = "true" ]; then - log_setup "โš  Skipping Drush and Drupal install due to earlier failure" - update_status "โš  Setup incomplete โ€” see drupal-setup.log for details" - else - - # Step 5: Ensure Drush is available - if [ -f "vendor/bin/drush" ]; then - log_setup "โœ“ Drush already present" - update_status "โœ“ Drush install: Already present" - else - _t=$SECONDS - log_setup "Adding Drush..." + if [ "$SETUP_FAILED" != "true" ]; then + log_setup "Adding Drush to composer.local.json..." update_status "โณ Drush install: In progress..." - if ddev composer require drush/drush -W >> "$SETUP_LOG" 2>&1; then - log_setup "โœ“ Drush configured" + if ddev composer require drush/drush >> "$SETUP_LOG" 2>&1; then + log_setup "โœ“ Drush installed" update_status "โœ“ Drush install: Success" else - log_setup "โš  Warning: Failed to configure Drush" + log_setup "โš  Warning: Failed to install Drush (non-critical)" update_status "โš  Drush install: Warning" fi fi + fi - # Step 6: Install Drupal database + # Steps 5-6: Drupal install โ€” skipped if an earlier step failed + if [ "$SETUP_FAILED" = "true" ]; then + log_setup "โš  Skipping Drupal install due to earlier failure" + update_status "โš  Setup incomplete โ€” see drupal-setup.log for details" + else + + # Compute site name for drush si + if [ -n "$ISSUE_FORK" ] && [ -n "$ISSUE_TITLE" ]; then + SITE_NAME="#$${ISSUE_FORK}: $${ISSUE_TITLE}" + elif [ -n "$ISSUE_FORK" ]; then + SITE_NAME="Issue #$${ISSUE_FORK}" + else + SITE_NAME="Drupal Core Development" + fi - # Compute site name for drush si - if [ -n "$ISSUE_FORK" ] && [ -n "$ISSUE_TITLE" ]; then - SITE_NAME="#$${ISSUE_FORK}: $${ISSUE_TITLE}" - elif [ -n "$ISSUE_FORK" ]; then - SITE_NAME="Issue #$${ISSUE_FORK}" + if ddev drush status 2>/dev/null | grep -q "Drupal bootstrap.*Successful"; then + log_setup "โœ“ Drupal already installed" + update_status "โœ“ Drupal install: Already present" + else + _t=$SECONDS + if [ "$USING_ISSUE_FORK" = "true" ]; then + log_setup "Installing Drupal with $INSTALL_PROFILE profile (issue fork)..." else - SITE_NAME="Drupal Core Development" + log_setup "Installing Drupal with $INSTALL_PROFILE profile..." fi - - if ddev drush status 2>/dev/null | grep -q "Drupal bootstrap.*Successful"; then - log_setup "โœ“ Drupal already installed" - update_status "โœ“ Drupal install: Already present" + update_status "โณ Drupal install: In progress..." + + if ddev drush si -y "$INSTALL_PROFILE" --account-pass=admin --site-name="$SITE_NAME" >> "$SETUP_LOG" 2>&1; then + log_setup "โœ“ Drupal installed" + log_setup "" + log_setup " Admin Credentials:" + log_setup " Username: admin" + log_setup " Password: admin" + log_setup "" + update_status "โœ“ Drupal install: Success" else - _t=$SECONDS - if [ "$USING_ISSUE_FORK" = "true" ]; then - log_setup "Installing Drupal with $INSTALL_PROFILE profile (issue fork)..." - else - log_setup "Installing Drupal with $INSTALL_PROFILE profile..." - fi - update_status "โณ Drupal install: In progress..." - - if ddev drush si -y "$INSTALL_PROFILE" --account-pass=admin --site-name="$SITE_NAME" >> "$SETUP_LOG" 2>&1; then - log_setup "โœ“ Drupal installed" - log_setup "" - log_setup " Admin Credentials:" - log_setup " Username: admin" - log_setup " Password: admin" - log_setup "" - update_status "โœ“ Drupal install: Success" - else - log_setup "โœ— Failed to install Drupal" - log_setup "Check $SETUP_LOG for details" - update_status "โœ— Drupal install: Failed" - update_status "" - update_status "Manual recovery:" - update_status " cd $DRUPAL_DIR" - update_status " ddev drush si -y $INSTALL_PROFILE --account-pass=admin" - fi + log_setup "โœ— Failed to install Drupal" + log_setup "Check $SETUP_LOG for details" + update_status "โœ— Drupal install: Failed" + update_status "" + update_status "Manual recovery:" + update_status " cd $DRUPAL_DIR" + update_status " ddev drush si -y $INSTALL_PROFILE --account-pass=admin" fi - fi # end SETUP_FAILED guard - - # Step 6.5: Cache rebuild โ€” ensures a clean state after any setup path - log_setup "Running cache rebuild..." - ddev drush cr >> "$SETUP_LOG" 2>&1 || true - - # Step 6.6: Set up phpunit.xml for running core tests (numbered was originally 6.6, now follows 6.5) - if [ ! -f "phpunit.xml" ] && [ -f "phpunit-ddev.xml" ]; then - cp phpunit-ddev.xml phpunit.xml - # Replace PROJECT_NAME.ddev.site placeholder with actual workspace URL - if [ -n "$CODER_WORKSPACE_OWNER_NAME" ] && ([ -n "$VSCODE_PROXY_URI" ] || [ -n "$CODER_AGENT_URL" ]); then - if [ -n "$VSCODE_PROXY_URI" ]; then - CODER_DOMAIN=$(echo "$VSCODE_PROXY_URI" | sed -E 's|https?://[^.]+\.(.+?)(/.*)?$|\1|') - else - CODER_DOMAIN=$(echo "$CODER_AGENT_URL" | sed -E 's|https?://(.+?)(/.*)?$|\1|') - fi - SITE_URL="https://80--$${CODER_WORKSPACE_NAME}--$${CODER_WORKSPACE_OWNER_NAME}.$${CODER_DOMAIN}" - sed -i "s|PROJECT_NAME\.ddev\.site|$${SITE_URL#https://}|" phpunit.xml + fi + fi # end SETUP_FAILED guard + + # Step 6.5: Cache rebuild โ€” ensures a clean state after any setup path + log_setup "Running cache rebuild..." + ddev drush cr >> "$SETUP_LOG" 2>&1 || true + + # Step 6.6: Set up phpunit.xml for running core tests + if [ ! -f "phpunit.xml" ] && [ -f "phpunit-ddev.xml" ]; then + cp phpunit-ddev.xml phpunit.xml + # Replace PROJECT_NAME.ddev.site placeholder with actual workspace URL + if [ -n "$CODER_WORKSPACE_OWNER_NAME" ] && ([ -n "$VSCODE_PROXY_URI" ] || [ -n "$CODER_AGENT_URL" ]); then + if [ -n "$VSCODE_PROXY_URI" ]; then + CODER_DOMAIN=$(echo "$VSCODE_PROXY_URI" | sed -E 's|https?://[^.]+\.(.+?)(/.*)?$|\1|') + else + CODER_DOMAIN=$(echo "$CODER_AGENT_URL" | sed -E 's|https?://(.+?)(/.*)?$|\1|') fi - log_setup "โœ“ phpunit.xml configured (run tests with: ddev exec vendor/bin/phpunit web/core/tests/...)" + SITE_URL="https://80--$${CODER_WORKSPACE_NAME}--$${CODER_WORKSPACE_OWNER_NAME}.$${CODER_DOMAIN}" + sed -i "s|PROJECT_NAME\.ddev\.site|$${SITE_URL#https://}|" phpunit.xml fi + log_setup "โœ“ phpunit.xml configured (run tests with: ddev exec vendor/bin/phpunit core/tests/...)" + fi - # Step 7: Install custom DDEV launch command - mkdir -p ~/.ddev/commands/host - cat > ~/.ddev/commands/host/launch << 'LAUNCH_EOF' + # Step 7: Install custom DDEV launch command + mkdir -p ~/.ddev/commands/host + cat > ~/.ddev/commands/host/launch << 'LAUNCH_EOF' #!/usr/bin/env bash ## Description: Show Coder URLs for this Drupal workspace @@ -1223,13 +998,17 @@ else echo "One-time login: ddev drush uli (run when Drupal is installed)" fi echo "" +echo "Useful commands (from ddev-drupal-dev add-on):" +echo " ddev add-module # Clone a contrib module for development" +echo " ddev phpunit [--db=sqlite|mysql|pgsql] # Run PHPUnit tests" +echo " ddev remove-module # Remove a contrib module" +echo " See: https://github.com/amateescu/ddev-drupal-dev" +echo "" LAUNCH_EOF - chmod +x ~/.ddev/commands/host/launch - log_setup "โœ“ Custom DDEV launch command installed" - update_status "โœ“ DDEV launch command: Installed" - - fi # End of "if project creation succeeded" + chmod +x ~/.ddev/commands/host/launch + log_setup "โœ“ Custom DDEV launch command installed" + update_status "โœ“ DDEV launch command: Installed" # Timing summary TOTAL_TIME=$((SECONDS - SCRIPT_START)) From 12f2929bf4a7786123b5bea83295947dd1b8681a Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sun, 10 May 2026 11:20:35 -0600 Subject: [PATCH 2/5] fix(ci): update drupal-core integration test paths for new scaffolding With amateescu/ddev-drupal-dev, Drupal's index.php is at the project root (not web/) and the git repo is at drupal-core/ (not repos/drupal/). Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/drupal-integration-test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/drupal-integration-test.yml b/.github/workflows/drupal-integration-test.yml index 1df2af5..fb3da84 100644 --- a/.github/workflows/drupal-integration-test.yml +++ b/.github/workflows/drupal-integration-test.yml @@ -131,7 +131,7 @@ jobs: - &verify-webroot name: Verify workspace โ€” web root exists - run: coder ssh ${{ env.WORKSPACE_NAME }} -- test -f /home/coder/drupal-core/web/index.php + run: coder ssh ${{ env.WORKSPACE_NAME }} -- test -f /home/coder/drupal-core/index.php - &verify-drush name: Verify workspace โ€” Drush DB connected @@ -366,11 +366,11 @@ jobs: run: coder ssh ${{ env.WORKSPACE_NAME }} -- ddev --version - name: Verify workspace โ€” web root exists - run: coder ssh ${{ env.WORKSPACE_NAME }} -- test -f /home/coder/drupal-core/web/index.php + run: coder ssh ${{ env.WORKSPACE_NAME }} -- test -f /home/coder/drupal-core/index.php - name: Verify workspace โ€” issue branch checked out run: | - CURRENT=$(coder ssh ${{ env.WORKSPACE_NAME }} -- git -C /home/coder/drupal-core/repos/drupal branch --show-current | tr -d '\r\n') + CURRENT=$(coder ssh ${{ env.WORKSPACE_NAME }} -- git -C /home/coder/drupal-core branch --show-current | tr -d '\r\n') echo "Current branch: $CURRENT Expected: ${{ env.ISSUE_BRANCH }}" [[ "$CURRENT" == "${{ env.ISSUE_BRANCH }}" ]] || { echo "ERROR: wrong branch" >&2; exit 1; } @@ -514,11 +514,11 @@ jobs: run: coder ssh ${{ env.WORKSPACE_NAME }} -- ddev --version - name: Verify workspace โ€” web root exists - run: coder ssh ${{ env.WORKSPACE_NAME }} -- test -f /home/coder/drupal-core/web/index.php + run: coder ssh ${{ env.WORKSPACE_NAME }} -- test -f /home/coder/drupal-core/index.php - name: Verify workspace โ€” issue branch checked out run: | - CURRENT=$(coder ssh ${{ env.WORKSPACE_NAME }} -- git -C /home/coder/drupal-core/repos/drupal branch --show-current | tr -d '\r\n') + CURRENT=$(coder ssh ${{ env.WORKSPACE_NAME }} -- git -C /home/coder/drupal-core branch --show-current | tr -d '\r\n') echo "Current branch: $CURRENT Expected: ${{ env.ISSUE_BRANCH }}" [[ "$CURRENT" == "${{ env.ISSUE_BRANCH }}" ]] || { echo "ERROR: wrong branch" >&2; exit 1; } From f6e12d9508f1d991de16ebaa21d83e821c30ba96 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sun, 10 May 2026 11:51:12 -0600 Subject: [PATCH 3/5] fix(drupal-core): move DRUPAL_BRANCH definition before git clone section DRUPAL_BRANCH was computed after the git clone block that used it, causing the empty-branch condition to trigger git checkout of an empty string. This set SETUP_FAILED=true, skipping drush si and breaking the CI drush db-connected check. Co-Authored-By: Claude Sonnet 4.6 --- drupal-core/template.tf | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drupal-core/template.tf b/drupal-core/template.tf index 9602c0f..f3ff4e6 100644 --- a/drupal-core/template.tf +++ b/drupal-core/template.tf @@ -583,6 +583,15 @@ STATUS_HEADER if [ -n "$ISSUE_TITLE" ]; then log_setup " Title: $ISSUE_TITLE"; fi fi + # Drupal version, branch, and DDEV project type โ€” computed early so the git clone + # section can check out the correct branch before DDEV config runs. + DRUPAL_VERSION="${data.coder_parameter.drupal_version.value}" + case "$DRUPAL_VERSION" in + 10) DDEV_PROJECT_TYPE="drupal10"; DRUPAL_BRANCH="10.x" ;; + 11) DDEV_PROJECT_TYPE="drupal11"; DRUPAL_BRANCH="11.x" ;; + *) DDEV_PROJECT_TYPE="drupal12"; DRUPAL_BRANCH="main" ;; + esac + # Step 1: Clone Drupal core (first run) or verify existing checkout CACHE_SEED="/home/coder-cache-seed" SETUP_START=$SECONDS @@ -665,21 +674,6 @@ STATUS_HEADER cd "$DRUPAL_DIR" || exit 1 # Step 2: Configure DDEV (must be done before composer create) - # Derive project type from the Drupal major version parameter (let DDEV pick default PHP version) - DRUPAL_VERSION="${data.coder_parameter.drupal_version.value}" - case "$DRUPAL_VERSION" in - 10) DDEV_PROJECT_TYPE="drupal10" ;; - 11) DDEV_PROJECT_TYPE="drupal11" ;; - *) DDEV_PROJECT_TYPE="drupal12" ;; - esac - - # Map version to git branch (non-main versions need a dedicated branch checkout) - case "$DRUPAL_VERSION" in - 10) DRUPAL_BRANCH="10.x" ;; - 11) DRUPAL_BRANCH="11.x" ;; - *) DRUPAL_BRANCH="main" ;; - esac - # Always regenerate .ddev/config.yaml from scratch so DDEV picks its own defaults # for the project type (e.g. correct PHP version). Preserving an old config.yaml # would leave stale fields like php_version untouched even when project-type changes. From d9ce5e38d99f2d0771a6667e014376f25d427a55 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sun, 10 May 2026 12:17:02 -0600 Subject: [PATCH 4/5] docs(drupal-core): update cache seed for amateescu scaffolding The cache no longer needs a full DDEV project (vendor/, composer.json, etc.). Only repos/drupal/ is needed as a git --reference hint for faster workspace clones. update-drupal-cache now runs git fetch instead of ddev composer update; service drops the Docker dependency and uses a 5-minute timeout. server-setup.md Step 10 updated with new initial setup, migration steps for existing servers, and updated troubleshooting. Co-Authored-By: Claude Sonnet 4.6 --- docs/admin/server-setup.md | 108 +++++++++--------- .../scripts/drupal-cache-updater.service | 7 +- drupal-core/scripts/update-drupal-cache | 50 ++------ 3 files changed, 68 insertions(+), 97 deletions(-) diff --git a/docs/admin/server-setup.md b/docs/admin/server-setup.md index 4432afd..7ee7ccf 100644 --- a/docs/admin/server-setup.md +++ b/docs/admin/server-setup.md @@ -855,51 +855,29 @@ This deploys three templates: ## Step 10: Set Up the Drupal Core Seed Cache (optional, highly recommended) -The `drupal-core` template can provision a Drupal core development environment faster on new workspaces using a **seed cache** on the host. Without the cache, first-time workspace setup downloads a full git clone and all composer dependencies (~10-13 minutes). With the cache, the composer install phase is nearly instant; total workspace startup is 3-5 minutes (the remaining time is the Drupal site install, which always runs fresh). +The `drupal-core` template can provision workspaces faster using a **seed cache** on the host. The cache is a plain git clone of drupal/drupal. New workspaces pass it as a `--reference` hint to `git clone`, reusing local git objects and avoiding several hundred MB of network transfer. Composer install still runs fresh inside each workspace. -The cache is a standing DDEV project on the host that is periodically refreshed. New workspaces copy the git checkout and vendor directory from it. The database is always installed fresh via `ddev drush si` โ€” this avoids schema-drift reliability problems with pre-built DB snapshots. - -### Prerequisites - -DDEV must be installed on the Coder server itself (not just inside workspaces). The host DDEV project runs on the host Docker daemon, separate from the Sysbox workspace containers. - -Follow the [DDEV Linux installation instructions](https://docs.ddev.com/en/stable/users/install/ddev-installation/#ddev-installation-linux) to install DDEV on the host. - -> **User note:** The seed cache must be owned and operated by a normal (non-root) user. DDEV refuses to run as root. All the commands below, and the systemd service, must run as that user โ€” not with `sudo`. +The database is always installed fresh via `ddev drush si`. ### One-time initial setup -Run these commands as your normal (non-root) user โ€” **not** as root: - ```bash -mkdir -p ~/cache/drupal-core-seed -cd ~/cache/drupal-core-seed - -# Configure DDEV project -ddev config --project-type=drupal12 --php-version=8.5 --docroot=web \ - --project-name=drupal-core-seed -ddev start - -# Create the full drupal-core development project (takes 5-10 minutes) -ddev composer create-project joachim-n/drupal-core-development-project --no-interaction - -# Add Drush -ddev composer require drush/drush +mkdir -p ~/cache/drupal-core-seed/repos +git clone https://git.drupalcode.org/project/drupal.git \ + ~/cache/drupal-core-seed/repos/drupal ``` -After this runs, the seed directory contains: +The seed directory contains only: -| Path | Contents | -|------|----------| -| `composer.json` / `composer.lock` | Project definition | -| `repos/drupal/` | Git clone of Drupal core | -| `vendor/` | All Composer packages | -| `web/` | Docroot (symlinked) | -| `.ddev/` | Host DDEV config โ€” **not** copied to workspaces | +| Path | Contents | +|------------------|---------------------------| +| `repos/drupal/` | Git clone of Drupal core | + +No DDEV, no vendor directory, no composer files โ€” just the git objects. ### Install the hourly update timer -The update script runs `composer update` to keep the cache current with Drupal HEAD. Install it as an hourly systemd timer: +The update script runs `git fetch --all --prune` to keep the cache current. Install it as an hourly systemd timer: ```bash REPO=~/workspace/coder-ddev # adjust if your repo is elsewhere @@ -929,8 +907,6 @@ systemctl list-timers drupal-cache-updater.timer ### Manual refresh -Run an update at any time (e.g. after a major Drupal release): - ```bash /usr/local/bin/update-drupal-cache @@ -942,6 +918,37 @@ sudo systemctl start drupal-cache-updater.service journalctl -u drupal-cache-updater.service -f ``` +### Migrating from the old joachim-n cache structure + +If your server has an existing seed cache built with `joachim-n/drupal-core-development-project` (the old scaffolding), the `repos/drupal/.git` directory is already there and works as a git reference hint immediately โ€” no urgent action is needed. New workspaces will use it automatically. + +When convenient, migrate each server to the simpler structure: + +```bash +SEED_DIR=~/cache/drupal-core-seed + +# 1. Stop the DDEV seed project (no longer needed) +cd "$SEED_DIR" && ddev stop --remove-data 2>/dev/null || true + +# 2. Install the updated update script (replaces composer update with git fetch) +REPO=~/workspace/coder-ddev +sudo install -m 755 $REPO/drupal-core/scripts/update-drupal-cache \ + /usr/local/bin/update-drupal-cache +sudo install -m 644 $REPO/drupal-core/scripts/drupal-cache-updater.service \ + /etc/systemd/system/ +sudo systemctl daemon-reload + +# 3. Verify the timer still works +sudo systemctl start drupal-cache-updater.service +journalctl -u drupal-cache-updater.service --no-pager | tail -20 + +# 4. Clean up old files no longer needed (repos/drupal/ stays) +cd "$SEED_DIR" +rm -rf vendor web composer.json composer.lock .ddev core +``` + +After step 4, the seed directory contains only `repos/drupal/`. + ### Template variable The template uses a `cache_path` variable for the host-side seed directory. The `Makefile` defaults `DRUPAL_CACHE_PATH` to `~/cache/drupal-core-seed` (resolved to the home directory of whoever runs `make`), so `make push-template-drupal-core` works without any override as long as your seed directory is at that path. @@ -956,11 +963,9 @@ make push-template-drupal-core DRUPAL_CACHE_PATH=/your/cache/path When a workspace starts for the first time: -1. The startup script checks for a valid seed at `/home/coder-cache-seed` (the read-only bind mount of `cache_path`) -2. **Cache hit:** `rsync` copies the project files (excluding `.ddev/`), `ddev composer install` ensures vendor is current (near-instant with vendor already present), then `ddev drush si` installs Drupal fresh (~2-3 min) -3. **Cache miss** (path absent or incomplete): falls back to full `ddev composer create-project` + `ddev drush si` โ€” slower but always works - -The database is always installed fresh โ€” there is no pre-built DB snapshot. This avoids schema-drift failures that occurred when the cached DB became stale relative to Drupal HEAD. +1. The startup script checks for `repos/drupal/.git` at `/home/coder-cache-seed` (the read-only bind mount of `cache_path`) +2. **Cache hit:** `git clone --reference` reuses local git objects for the initial clone (fast), then `ddev composer install` runs fresh inside the container +3. **Cache miss** (path absent or `repos/drupal/.git` missing): `git clone` runs without a reference โ€” slower but always works Check workspace startup logs in the Coder dashboard or at `/tmp/drupal-setup.log` inside the workspace to confirm which path was taken. @@ -968,21 +973,18 @@ Check workspace startup logs in the Coder dashboard or at `/tmp/drupal-setup.log **Cache not being used:** -- Verify the seed directory exists and is populated: `ls $SEED_DIR/composer.json $SEED_DIR/vendor` -- Confirm `cache_path` in the deployed template matches your actual seed directory (check with `coder templates versions list drupal-core`) -- Check the workspace startup log for the "Cache mount check" diagnostic block โ€” it shows exactly which files were found or missing at the bind mount path -- Look for "Cache hit" in the log; "No cache available" means the path is absent or the seed was never initialized - -**Seed project won't start after server reboot:** -```bash -cd ~/cache/drupal-core-seed && ddev start -``` +- Verify the seed directory has a git clone: `ls ~/cache/drupal-core-seed/repos/drupal/.git` +- Confirm `cache_path` in the deployed template matches your actual seed directory +- Look for "with reference from cache seed" in `/tmp/drupal-setup.log`; absence means the path was missing or the clone check failed **Update script fails:** + ```bash -cd ~/cache/drupal-core-seed -ddev describe # verify DDEV is running -ddev logs # check container logs for errors +git -C ~/cache/drupal-core-seed/repos/drupal fetch --all --prune +# If this fails, check network connectivity or re-clone: +rm -rf ~/cache/drupal-core-seed/repos/drupal +git clone https://git.drupalcode.org/project/drupal.git \ + ~/cache/drupal-core-seed/repos/drupal ``` --- diff --git a/drupal-core/scripts/drupal-cache-updater.service b/drupal-core/scripts/drupal-cache-updater.service index 878b344..34abdfc 100644 --- a/drupal-core/scripts/drupal-cache-updater.service +++ b/drupal-core/scripts/drupal-cache-updater.service @@ -1,12 +1,9 @@ [Unit] Description=Update drupal-core seed cache for Coder workspaces -After=docker.service -Requires=docker.service [Service] Type=oneshot # Must run as the user who owns the seed cache directory โ€” NOT root. -# DDEV refuses to run as root; this service must run as a normal user. # Change User= to the account that owns the cache (e.g. your server's admin user). User=YOURUSER WorkingDirectory=%h @@ -16,8 +13,8 @@ WorkingDirectory=%h ExecStart=/usr/local/bin/update-drupal-cache StandardOutput=journal StandardError=journal -# Allow up to 20 minutes for composer update -TimeoutStartSec=1200 +# Allow up to 5 minutes for git fetch +TimeoutStartSec=300 [Install] WantedBy=multi-user.target diff --git a/drupal-core/scripts/update-drupal-cache b/drupal-core/scripts/update-drupal-cache index bbf6e7b..9d2cac1 100755 --- a/drupal-core/scripts/update-drupal-cache +++ b/drupal-core/scripts/update-drupal-cache @@ -4,13 +4,10 @@ # Refreshes the drupal-core seed cache used by the drupal-core Coder template. # Run this script on the Coder host server as the user who owns the seed directory. # -# The seed cache is a pre-built drupal-core project containing: -# - repos/drupal/ Drupal core git clone -# - vendor/ Composer packages -# -# New workspaces copy from this cache (rsync + git fetch + ddev composer install) -# instead of downloading all packages from Packagist, saving several minutes. -# The database is always installed fresh in each workspace via ddev drush si. +# The seed cache is a plain git clone of drupal/drupal at repos/drupal/ inside +# the seed directory. New workspaces pass it as a --reference hint to git clone, +# which reuses the local git objects and avoids downloading several hundred MB. +# Composer install still runs fresh inside each workspace. # # Usage: # ./update-drupal-cache [--seed-dir PATH] @@ -20,11 +17,7 @@ # Default: ~/cache/drupal-core-seed (resolved to the running user's home) # The Coder template's cache_path variable must be set to the same path. # -# Note: This script must run as the user who owns the seed directory (not root). -# DDEV refuses to run as root. The systemd service (drupal-cache-updater.service) -# must set User= to the cache owner โ€” see that file and docs/admin/server-setup.md. -# -# Note: when run via the systemd timer, the seed directory is taken from the default +# Note: When run via the systemd timer, the seed directory is taken from the default # or from the ExecStart line in drupal-cache-updater.service โ€” edit that file to pass # --seed-dir if your seed directory differs from the default. @@ -46,14 +39,10 @@ while [[ $# -gt 0 ]]; do esac done -if [ ! -d "$SEED_DIR" ]; then - echo "Error: Seed directory not found: $SEED_DIR" >&2 - echo "Run the initial setup first. See docs/admin/server-setup.md." >&2 - exit 1 -fi +GIT_DIR="$SEED_DIR/repos/drupal" -if [ ! -f "$SEED_DIR/composer.json" ]; then - echo "Error: composer.json not found in $SEED_DIR โ€” seed not initialized." >&2 +if [ ! -d "$GIT_DIR/.git" ]; then + echo "Error: Git clone not found at $GIT_DIR" >&2 echo "Run the initial setup first. See docs/admin/server-setup.md." >&2 exit 1 fi @@ -63,27 +52,10 @@ echo "Seed directory: $SEED_DIR" echo "Started: $(date)" echo "" -cd "$SEED_DIR" - -echo "Starting DDEV seed project..." -ddev poweroff -ddev start -y - -pushd ${SEED_DIR}/repos/drupal >/dev/null -git pull -popd >/dev/null - -# Update composer dependencies (also updates repos/drupal git checkout via path repo) -echo "Running composer update..." -ddev composer update --with-all-dependencies - -ddev composer require drush/drush +echo "Fetching Drupal core git objects..." +git -C "$GIT_DIR" fetch --all --prune echo "" echo "=== Seed cache updated successfully ===" echo "Completed: $(date)" -echo "" -echo "New workspaces will use this cache automatically." -echo "Cache contents:" -echo " composer.json/lock: $(stat -c '%y' composer.lock 2>/dev/null | cut -d. -f1 || echo 'unknown')" -echo " Drupal HEAD: $(git -C repos/drupal log -1 --format='%h %s' 2>/dev/null || echo 'unknown')" +echo "Drupal HEAD: $(git -C "$GIT_DIR" log -1 --format='%h %s' 2>/dev/null || echo 'unknown')" From b97bd646f9029b78b6546a2ddbe05f4c7de98767 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sun, 10 May 2026 12:23:34 -0600 Subject: [PATCH 5/5] refactor(drupal-core): drop repos/drupal/ path from cache seed and docs The cache seed is now a plain git clone at the seed directory root. The old repos/drupal/ nesting was pure legacy from the joachim-n scaffolding. Template checks for $CACHE_SEED/.git; update script and docs updated accordingly. README, quickstart, and test script all rewritten for the amateescu/ddev-drupal-dev flow. Co-Authored-By: Claude Sonnet 4.6 --- docs/admin/server-setup.md | 52 +++----- docs/user/quickstart.md | 30 +++-- drupal-core/README.md | 91 ++++++------- drupal-core/scripts/test-issue-branches.sh | 147 +++++++-------------- drupal-core/scripts/update-drupal-cache | 22 ++- drupal-core/template.tf | 4 +- 6 files changed, 138 insertions(+), 208 deletions(-) diff --git a/docs/admin/server-setup.md b/docs/admin/server-setup.md index 7ee7ccf..4441da9 100644 --- a/docs/admin/server-setup.md +++ b/docs/admin/server-setup.md @@ -862,18 +862,10 @@ The database is always installed fresh via `ddev drush si`. ### One-time initial setup ```bash -mkdir -p ~/cache/drupal-core-seed/repos -git clone https://git.drupalcode.org/project/drupal.git \ - ~/cache/drupal-core-seed/repos/drupal +git clone https://git.drupalcode.org/project/drupal.git ~/cache/drupal-core-seed ``` -The seed directory contains only: - -| Path | Contents | -|------------------|---------------------------| -| `repos/drupal/` | Git clone of Drupal core | - -No DDEV, no vendor directory, no composer files โ€” just the git objects. +The seed directory IS the git clone โ€” no subdirectory nesting. No DDEV, no vendor, no composer files. ### Install the hourly update timer @@ -920,34 +912,35 @@ journalctl -u drupal-cache-updater.service -f ### Migrating from the old joachim-n cache structure -If your server has an existing seed cache built with `joachim-n/drupal-core-development-project` (the old scaffolding), the `repos/drupal/.git` directory is already there and works as a git reference hint immediately โ€” no urgent action is needed. New workspaces will use it automatically. +If your server has an existing seed cache built with `joachim-n/drupal-core-development-project`, the startup script now checks for `.git` at the seed root โ€” not inside `repos/drupal/`. New workspaces will fall back to a direct clone (slower) until migration is complete. -When convenient, migrate each server to the simpler structure: +Run these steps on each server: ```bash SEED_DIR=~/cache/drupal-core-seed +REPO=~/workspace/coder-ddev -# 1. Stop the DDEV seed project (no longer needed) +# 1. Stop the old DDEV seed project cd "$SEED_DIR" && ddev stop --remove-data 2>/dev/null || true -# 2. Install the updated update script (replaces composer update with git fetch) -REPO=~/workspace/coder-ddev +# 2. Move the git clone to the seed root, remove everything else +mv "$SEED_DIR/repos/drupal" /tmp/drupal-git-tmp +rm -rf "$SEED_DIR" +mv /tmp/drupal-git-tmp "$SEED_DIR" + +# 3. Install the updated update script and service sudo install -m 755 $REPO/drupal-core/scripts/update-drupal-cache \ /usr/local/bin/update-drupal-cache sudo install -m 644 $REPO/drupal-core/scripts/drupal-cache-updater.service \ /etc/systemd/system/ sudo systemctl daemon-reload -# 3. Verify the timer still works +# 4. Verify it works sudo systemctl start drupal-cache-updater.service -journalctl -u drupal-cache-updater.service --no-pager | tail -20 - -# 4. Clean up old files no longer needed (repos/drupal/ stays) -cd "$SEED_DIR" -rm -rf vendor web composer.json composer.lock .ddev core +journalctl -u drupal-cache-updater.service --no-pager | tail -10 ``` -After step 4, the seed directory contains only `repos/drupal/`. +After migration, `~/cache/drupal-core-seed` is the git clone itself โ€” `.git` is at the root. ### Template variable @@ -963,9 +956,9 @@ make push-template-drupal-core DRUPAL_CACHE_PATH=/your/cache/path When a workspace starts for the first time: -1. The startup script checks for `repos/drupal/.git` at `/home/coder-cache-seed` (the read-only bind mount of `cache_path`) +1. The startup script checks for `.git` at `/home/coder-cache-seed` (the read-only bind mount of `cache_path`) 2. **Cache hit:** `git clone --reference` reuses local git objects for the initial clone (fast), then `ddev composer install` runs fresh inside the container -3. **Cache miss** (path absent or `repos/drupal/.git` missing): `git clone` runs without a reference โ€” slower but always works +3. **Cache miss** (path absent or no `.git` at root): `git clone` runs without a reference โ€” slower but always works Check workspace startup logs in the Coder dashboard or at `/tmp/drupal-setup.log` inside the workspace to confirm which path was taken. @@ -973,18 +966,17 @@ Check workspace startup logs in the Coder dashboard or at `/tmp/drupal-setup.log **Cache not being used:** -- Verify the seed directory has a git clone: `ls ~/cache/drupal-core-seed/repos/drupal/.git` +- Verify the seed directory is a git clone: `ls ~/cache/drupal-core-seed/.git` - Confirm `cache_path` in the deployed template matches your actual seed directory -- Look for "with reference from cache seed" in `/tmp/drupal-setup.log`; absence means the path was missing or the clone check failed +- Look for "with reference from cache seed" in `/tmp/drupal-setup.log`; absence means the path was missing or `.git` was not at the root **Update script fails:** ```bash -git -C ~/cache/drupal-core-seed/repos/drupal fetch --all --prune +git -C ~/cache/drupal-core-seed fetch --all --prune # If this fails, check network connectivity or re-clone: -rm -rf ~/cache/drupal-core-seed/repos/drupal -git clone https://git.drupalcode.org/project/drupal.git \ - ~/cache/drupal-core-seed/repos/drupal +rm -rf ~/cache/drupal-core-seed +git clone https://git.drupalcode.org/project/drupal.git ~/cache/drupal-core-seed ``` --- diff --git a/docs/user/quickstart.md b/docs/user/quickstart.md index 8b2a31e..c5edee4 100644 --- a/docs/user/quickstart.md +++ b/docs/user/quickstart.md @@ -1,6 +1,6 @@ # Quickstart: Drupal Core Development on coder.ddev.com -Cloud-hosted DDEV workspaces for Drupal core development. Full environment โ€” Drupal core clone, running site, drush โ€” ready in about a minute. +Cloud-hosted DDEV workspaces for Drupal core development. Full environment โ€” Drupal core clone, running site, drush โ€” ready in about five minutes. [![Open in Coder](https://coder.ddev.com/open-in-coder.svg)](https://coder.ddev.com/templates/coder/drupal-core/workspace?mode=manual) @@ -16,7 +16,7 @@ Go to **[coder.ddev.com](https://coder.ddev.com)** and sign in with GitHub. Click the button above, or go to **Create Workspace** โ†’ select the **drupal-core** template โ†’ click **Create Workspace**. -Wait about a minute for the startup script to complete. Watch progress in the **Logs** tab. +Wait about five minutes for the startup script to complete. Watch progress in the **Logs** tab. --- @@ -31,15 +31,14 @@ The running site has the Umami demo profile installed. Admin credentials: `admin ## Code layout ``` -~/drupal-core/ -โ”œโ”€โ”€ repos/drupal/ # Drupal core git clone โ€” edit files here -โ”‚ โ””โ”€โ”€ core/ -โ”œโ”€โ”€ web/ # Web docroot (core/ symlinked from repos/drupal/) -โ”œโ”€โ”€ .ddev/ # DDEV config -โ””โ”€โ”€ vendor/ # Composer-managed dependencies +~/drupal-core/ # Drupal core git clone โ€” edit files here +โ”œโ”€โ”€ core/ # Drupal core source +โ”œโ”€โ”€ index.php # Entry point +โ”œโ”€โ”€ .ddev/ # DDEV config +โ””โ”€โ”€ composer.local.json # Local dependencies (drush, dev modules) ``` -Make your changes in `repos/drupal/` โ€” they are immediately reflected in the running site. +Edit files directly in `~/drupal-core/` โ€” changes are immediately reflected in the running site. --- @@ -52,8 +51,11 @@ ddev drush uli # Clear cache ddev drush cr -# Run Drupal tests (from repos/drupal/) -ddev exec phpunit web/core/tests/... +# Run Drupal tests (provided by ddev-drupal-dev add-on) +ddev phpunit core/modules/node + +# Install a contrib module for development +ddev add-module token # Open the site in your browser ddev launch @@ -77,7 +79,7 @@ When working on an issue, the workspace surfaces issue info in several places: To push your changes back: ```bash -cd ~/drupal-core/repos/drupal +cd ~/drupal-core # ... make changes ... @@ -93,7 +95,7 @@ If you prefer to set up manually: ```bash # In the workspace terminal: -cd ~/drupal-core/repos/drupal +cd ~/drupal-core # Create a branch git checkout -b my-fix @@ -132,4 +134,4 @@ tail -50 /tmp/drupal-setup.log ddev describe ``` -See also: [full getting-started guide](getting-started.md) ยท [DDEV docs](https://docs.ddev.com/) ยท [Drupal core contribution guide](https://www.drupal.org/contribute/development) +See also: [full getting-started guide](getting-started.md) ยท [DDEV docs](https://docs.ddev.com/) ยท [Drupal core contribution guide](https://www.drupal.org/contribute/development) ยท [ddev-drupal-dev add-on](https://github.com/amateescu/ddev-drupal-dev) diff --git a/drupal-core/README.md b/drupal-core/README.md index 3489e84..fc6705a 100644 --- a/drupal-core/README.md +++ b/drupal-core/README.md @@ -1,6 +1,6 @@ # Drupal Core Development Template -Automated Coder workspace for Drupal core development using [joachim-n/drupal-core-development-project](https://github.com/joachim-n/drupal-core-development-project). Sets up a professional development environment with Drupal core, DDEV, and a demo site. +Automated Coder workspace for Drupal core development using the [amateescu/ddev-drupal-dev](https://github.com/amateescu/ddev-drupal-dev) DDEV add-on. Sets up a professional development environment with Drupal core, DDEV, and a demo site. **New? See the [quickstart guide](../docs/user/quickstart.md).** @@ -8,26 +8,23 @@ Automated Coder workspace for Drupal core development using [joachim-n/drupal-co ## Features -- **Professional Setup**: Uses the drupal-core-development-project template -- **Clean Git Clone**: Drupal core in `repos/drupal/` directory -- **Proper Structure**: Web root at `web/` with Composer management +- **Direct Git Clone**: Drupal core cloned as the project root โ€” no composer project wrapper +- **Add-on Overlay**: [`amateescu/ddev-drupal-dev`](https://github.com/amateescu/ddev-drupal-dev) provides `ddev add-module`, `ddev phpunit`, and a `composer.local.json` overlay so core's `composer.json` stays untouched - **Demo Site**: Umami demo profile pre-installed (configurable) - **Full DDEV**: Complete DDEV environment with automatic PHP version selection -- **Issue Fork Support**: Check out any Drupal.org issue branch, with automatic Composer dependency resolution -- **VS Code**: Opens directly to Drupal core project root +- **Issue Fork Support**: Check out any Drupal.org issue branch via git remote +- **VS Code**: Opens directly to the Drupal core project root - **Port Forwarding**: HTTP (80) - **Custom Launch Command**: `ddev launch` shows Coder-specific instructions ## Initial Setup Time -When a seed cache is available on the server (the default), first workspace creation takes approximately **3-5 minutes**: -- rsync from seed cache: ~3s -- git fetch: ~1s -- composer install: ~2s -- Drupal site install (ddev drush si): ~2-3 min -- DDEV start: ~15s +First workspace creation takes approximately **5-8 minutes**: -Without a seed cache, first setup takes 10-15 minutes (full composer create + Drupal install). +- git clone (with cache seed reference hint): ~10s +- DDEV start + add-on install: ~1 min +- `ddev composer install`: ~2-3 min +- Drupal site install (`ddev drush si`): ~2-3 min Subsequent starts are fast (< 1 minute) as everything is already present. @@ -41,7 +38,7 @@ coder create --template drupal-core my-drupal-dev **Working on a specific issue:** -Use the **[Drupal Issue Picker](https://start.coder.ddev.com/drupal-issue)** โ€” enter an issue URL or number and it opens a pre-configured workspace with the issue branch already checked out and composer dependencies resolved. +Use the **[Drupal Issue Picker](https://start.coder.ddev.com/drupal-issue)** โ€” enter an issue URL or number and it opens a pre-configured workspace with the issue branch already checked out. Or manually via CLI: ```bash @@ -61,20 +58,14 @@ coder create --template drupal-core my-issue-3568144 \ ``` /home/coder/ -โ”œโ”€โ”€ drupal-core/ # Project root (VS Code opens here) -โ”‚ โ”œโ”€โ”€ repos/ -โ”‚ โ”‚ โ””โ”€โ”€ drupal/ # Drupal core git clone (clean) -โ”‚ โ”œโ”€โ”€ web/ # Web docroot -โ”‚ โ”‚ โ”œโ”€โ”€ core/ # Symlinked from repos/drupal/core -โ”‚ โ”‚ โ”œโ”€โ”€ index.php # Patched for correct app root -โ”‚ โ”‚ โ””โ”€โ”€ ... +โ”œโ”€โ”€ drupal-core/ # Drupal core git clone (VS Code opens here) +โ”‚ โ”œโ”€โ”€ core/ # Drupal core source +โ”‚ โ”œโ”€โ”€ index.php # Entry point (at project root, not web/) โ”‚ โ”œโ”€โ”€ .ddev/ # DDEV configuration -โ”‚ โ”œโ”€โ”€ vendor/ # Composer dependencies -โ”‚ โ”œโ”€โ”€ composer.json # Project dependencies -โ”‚ โ””โ”€โ”€ ... +โ”‚ โ””โ”€โ”€ composer.local.json # Local dependencies (drush, dev modules) โ”œโ”€โ”€ WELCOME.txt # Welcome message โ”œโ”€โ”€ SETUP_STATUS.txt # Setup completion status -โ””โ”€โ”€ projects/ # Additional projects directory (pre-created) +โ””โ”€โ”€ projects/ # Additional projects directory ``` ## Common Commands @@ -86,10 +77,9 @@ ddev drush uli # Get one-time admin login link ddev drush cr # Clear cache ddev drush updb # Run database updates -# Development -ddev composer require ... # Add dependencies -ddev composer update # Update dependencies -ddev exec phpunit ... # Run tests +# Development (provided by ddev-drupal-dev add-on) +ddev add-module token # Install a contrib module for development +ddev phpunit core/modules/node # Run Drupal tests # DDEV management ddev launch # Show access instructions @@ -112,8 +102,8 @@ tail -f /tmp/drupal-setup.log # View setup logs ### Network Access - Packagist: https://packagist.org (for Composer) -- GitHub: https://github.com (for drupal-core-development-project) -- Git: https://git.drupalcode.org (for Drupal core clone) +- Git: https://git.drupalcode.org (for Drupal core clone and issue forks) +- GitHub: https://github.com (for ddev-drupal-dev add-on) - Docker Hub: https://hub.docker.com ## Troubleshooting @@ -126,19 +116,21 @@ tail -50 /tmp/drupal-setup.log ``` Common issues: -- **DDEV config failed**: Check DDEV installation and Docker daemon + +- **git clone failed**: Network connectivity to git.drupalcode.org - **DDEV start failed**: Docker daemon issue, check `docker ps` -- **DDEV composer create failed**: Network connectivity or memory issue +- **composer install failed**: Network connectivity or memory issue - **Drupal install failed**: Database connection, check DDEV logs ### Manual Recovery If automatic setup fails, you can complete steps manually: ```bash cd ~/drupal-core -# Adjust project-type to match your version: drupal10, drupal11, or drupal12 -ddev config --project-type=drupal12 --docroot=web +ddev config --project-type=drupal12 ddev start -ddev composer create-project joachim-n/drupal-core-development-project . +ddev add-on get amateescu/ddev-drupal-dev +ddev restart +ddev composer install ddev composer require drush/drush ddev drush si -y demo_umami --account-pass=admin ``` @@ -157,7 +149,7 @@ coder create --template drupal-core my-11x-workspace --parameter drupal_version= # Stable 10.x branch coder create --template drupal-core my-10x-workspace --parameter drupal_version=10 ``` -The version controls the DDEV project type (PHP version) and the git branch checked out in `repos/drupal/`. Non-12.x versions always run a full Drupal site install (no cached DB snapshot). +The version controls the DDEV project type (PHP version) and the git branch checked out. ### Change Drupal Profile Set the `install_profile` parameter when creating the workspace: @@ -166,8 +158,6 @@ coder create --template drupal-core my-workspace --parameter install_profile=sta ``` Options: `demo_umami` (default), `minimal`, `standard`. -All workspaces run a full `ddev drush si` on first setup regardless of profile or whether an issue fork is specified. - ### Add Custom Commands Create scripts in `~/.ddev/commands/host/` or `.ddev/commands/web/` @@ -175,26 +165,25 @@ Create scripts in `~/.ddev/commands/host/` or `.ddev/commands/web/` - **Base Image**: `ddev/coder-ddev` (Ubuntu 24.04, DDEV, Docker, Node.js) - **Runtime**: Sysbox (secure Docker-in-Docker) -- **Project Template**: [joachim-n/drupal-core-development-project](https://github.com/joachim-n/drupal-core-development-project) +- **Add-on**: [amateescu/ddev-drupal-dev](https://github.com/amateescu/ddev-drupal-dev) - **Volumes**: - `/home/coder` - Persistent workspace data - `/var/lib/docker` - Docker images and containers -- **Drupal**: Cloned from https://git.drupalcode.org/project/drupal โ€” defaults to `main` (12.x); select 11.x or 10.x via the `drupal_version` parameter for stable branch development +- **Drupal**: Cloned from https://git.drupalcode.org/project/drupal โ€” defaults to `main` (12.x); select 11.x or 10.x via the `drupal_version` parameter ## Development Workflow 1. Make changes in VS Code (automatically opens to `/home/coder/drupal-core`) -2. Edit Drupal core files in `repos/drupal/` directory -3. Test changes via DDEV Web app (web root is at `web/`) -4. Run tests: `ddev exec phpunit ...` -5. Commit changes in `repos/drupal/`: `cd repos/drupal && git add . && git commit -m "..."` -6. Push to fork: `git remote add fork && git push fork` - -**Note**: The `repos/drupal/` directory contains the clean Drupal core git repository. Changes here are reflected in the `web/` directory via symlinks. +2. Edit Drupal core files directly in `~/drupal-core/` +3. Test changes via DDEV Web app +4. Run tests: `ddev phpunit core/modules/...` +5. Commit: `cd ~/drupal-core && git add . && git commit -m "..."` +6. Push to fork: `git push issue HEAD` ## Support -- **DDEV Docs**: https://docs.ddev.com/ -- **Drupal Docs**: https://www.drupal.org/docs -- **Coder Docs**: https://coder.com/docs +- **Add-on docs**: [amateescu/ddev-drupal-dev](https://github.com/amateescu/ddev-drupal-dev) +- **DDEV Docs**: [docs.ddev.com](https://docs.ddev.com/) +- **Drupal Docs**: [drupal.org/docs](https://www.drupal.org/docs) +- **Coder Docs**: [coder.com/docs](https://coder.com/docs) - **Template Issues**: File issues in this repository diff --git a/drupal-core/scripts/test-issue-branches.sh b/drupal-core/scripts/test-issue-branches.sh index fe13100..7f1924a 100755 --- a/drupal-core/scripts/test-issue-branches.sh +++ b/drupal-core/scripts/test-issue-branches.sh @@ -1,25 +1,25 @@ #!/usr/bin/env bash -# test-issue-branches.sh โ€” Test joachim-n/drupal-core-development-project -# against known Drupal core issue branches to validate composer fix logic. +# test-issue-branches.sh โ€” Test amateescu/ddev-drupal-dev scaffolding +# against Drupal core branches and issue forks. # # Usage: # bash drupal-core/scripts/test-issue-branches.sh # run all default tests # bash drupal-core/scripts/test-issue-branches.sh ISSUE:BRANCH:TYPE # run one issue fork # bash drupal-core/scripts/test-issue-branches.sh ::BRANCH:TYPE # run one plain branch # -# Triples format: ISSUE:BRANCH:DDEV_PROJECT_TYPE +# Triple format: ISSUE:BRANCH:DDEV_PROJECT_TYPE # Leave ISSUE empty (::BRANCH:TYPE) for plain origin-branch tests without an issue fork. -# BRANCH is the git branch to check out from origin (e.g. 10.6.x, 11.x, main). -# Leave BRANCH empty (::TYPE or ISSUE::TYPE) to skip checkout and stay on main. +# BRANCH is the git branch to check out (e.g. 10.6.x, 11.x, main). +# Leave BRANCH empty to stay on main. # -# Requirements: ddev, jq, git +# Requirements: ddev, git # Projects are created in ~/tmp/drupal-test-/ and left in place after the run. -# To clean up: cd ~/tmp/drupal-test- && ddev delete -Oy +# To clean up: cd ~/tmp/drupal-test- && ddev delete -Oy && cd && rm -rf ~/tmp/drupal-test- # Default test matrix (issue:branch:ddev-project-type triples) # ddev project type determines PHP version: drupal10/11 -> PHP 8.4, drupal12 -> PHP 8.5 DEFAULT_TESTS=( - # Plain version tests (no issue fork) โ€” validates non-main branch checkout + composer fixes + # Plain version tests (no issue fork) โ€” validates non-main branch checkout "::10.6.x:drupal10" "::11.x:drupal11" "::main:drupal12" @@ -27,7 +27,6 @@ DEFAULT_TESTS=( "3380334:3380334-user-update-10000:drupal10" "3515218:3515218-deprecate-nodeispage-and:drupal11" "3562560:3562560-show-both-minor:drupal11" - "3164889:3164889-issue-with-the:drupal11" "2555609:2555609-bulk-publish-logging:drupal12" ) @@ -45,7 +44,6 @@ log() { echo "[$(date '+%H:%M:%S')] $*"; } for PAIR in "${TESTS[@]}"; do ISSUE="${PAIR%%:*}" if [ -z "$ISSUE" ]; then - # ::BRANCH:TYPE format โ€” strip the two leading colons then parse normally _inner="${PAIR##::}" BRANCH="${_inner%%:*}" PROJECT_TYPE="${_inner##*:}" @@ -54,64 +52,45 @@ for PAIR in "${TESTS[@]}"; do BRANCH="${REST%%:*}" PROJECT_TYPE="${REST##*:}" fi - # Default project type if not specified - [ "$PROJECT_TYPE" = "$BRANCH" ] && PROJECT_TYPE="drupal11" - # Directory name: use issue number if present, else branch name (main โ†’ "main", 10.6.x โ†’ "10.6.x") + [ "$PROJECT_TYPE" = "$BRANCH" ] && PROJECT_TYPE="drupal12" DIR_KEY="${ISSUE:-${BRANCH:-main}}" PROJECT_DIR="$HOME/tmp/drupal-test-$DIR_KEY" - REPOS_DIR="$PROJECT_DIR/repos/drupal" + TARGET_BRANCH="${BRANCH:-main}" START=$SECONDS log "========================================================" if [ -n "$ISSUE" ]; then log "Testing issue #$ISSUE branch: $BRANCH type: $PROJECT_TYPE" else - log "Testing plain branch: ${BRANCH:-main} type: $PROJECT_TYPE" + log "Testing plain branch: $TARGET_BRANCH type: $PROJECT_TYPE" fi log "Project dir: $PROJECT_DIR" log "========================================================" - mkdir -p "$PROJECT_DIR" - cd "$PROJECT_DIR" - - # --- Configure and start DDEV if needed --- - if ! ddev describe >/dev/null 2>&1; then - log "Configuring DDEV project (type: $PROJECT_TYPE)..." - ddev config --project-name "drupal-test-$DIR_KEY" --project-type "$PROJECT_TYPE" --docroot . \ - --composer-version 2 2>&1 | tail -5 - ddev start 2>&1 | tail -10 - else - log "DDEV project already configured" - fi - - # --- composer create-project --- - if [ ! -f "composer.json" ]; then - log "Running composer create-project..." - ddev composer create-project --no-install --no-interaction \ - "joachim-n/drupal-core-development-project" . 2>&1 | tail -20 + # --- Clone (or reuse existing clone) --- + if [ ! -d "$PROJECT_DIR/.git" ]; then + log "Cloning Drupal core..." + if ! git clone https://git.drupalcode.org/project/drupal.git "$PROJECT_DIR" 2>&1; then + log "ERROR: git clone failed" + RESULTS["$DIR_KEY"]="FAIL (git clone)" + DURATIONS["$DIR_KEY"]=$((SECONDS - START)) + continue + fi else - log "composer.json already present โ€” skipping create-project" + log "Clone already present โ€” reusing" fi - if [ ! -d "$REPOS_DIR/.git" ]; then - log "ERROR: repos/drupal/.git not found after create-project" - RESULTS["$DIR_KEY"]="FAIL (no repos/drupal)" - DURATIONS["$DIR_KEY"]=$((SECONDS - START)) - cd "$HOME" - continue - fi + cd "$PROJECT_DIR" # --- Checkout branch --- - CURRENT_BRANCH=$(git -C "$REPOS_DIR" branch --show-current 2>/dev/null || echo "") - TARGET_BRANCH="${BRANCH:-main}" + CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "") if [ "$CURRENT_BRANCH" = "$TARGET_BRANCH" ]; then log "Already on branch: $TARGET_BRANCH" elif [ -n "$ISSUE" ]; then - # Issue fork: fetch from issue-specific remote log "Adding issue fork remote and fetching..." - git -C "$REPOS_DIR" remote remove issue 2>/dev/null || true - git -C "$REPOS_DIR" remote add issue "https://git.drupalcode.org/issue/drupal-$ISSUE.git" - if ! git -C "$REPOS_DIR" fetch issue 2>&1; then + git remote remove issue 2>/dev/null || true + git remote add issue "https://git.drupalcode.org/issue/drupal-$ISSUE.git" + if ! git fetch issue 2>&1; then log "ERROR: git fetch from issue remote failed" RESULTS["$DIR_KEY"]="FAIL (git fetch)" DURATIONS["$DIR_KEY"]=$((SECONDS - START)) @@ -119,8 +98,7 @@ for PAIR in "${TESTS[@]}"; do continue fi log "Checking out branch: $BRANCH" - if ! (git -C "$REPOS_DIR" checkout -b "$BRANCH" "issue/$BRANCH" 2>&1 || \ - git -C "$REPOS_DIR" checkout "$BRANCH" 2>&1); then + if ! (git checkout -b "$BRANCH" "issue/$BRANCH" 2>&1 || git checkout "$BRANCH" 2>&1); then log "ERROR: branch checkout failed" RESULTS["$DIR_KEY"]="FAIL (git checkout)" DURATIONS["$DIR_KEY"]=$((SECONDS - START)) @@ -128,11 +106,9 @@ for PAIR in "${TESTS[@]}"; do continue fi elif [ "$TARGET_BRANCH" != "main" ]; then - # Plain origin branch (e.g. 10.6.x, 11.x) - log "Fetching from origin and checking out $TARGET_BRANCH..." - git -C "$REPOS_DIR" fetch origin 2>&1 | tail -3 - if ! (git -C "$REPOS_DIR" checkout -b "$TARGET_BRANCH" "origin/$TARGET_BRANCH" 2>&1 || \ - git -C "$REPOS_DIR" checkout "$TARGET_BRANCH" 2>&1); then + log "Checking out $TARGET_BRANCH..." + if ! (git checkout -b "$TARGET_BRANCH" "origin/$TARGET_BRANCH" 2>&1 || \ + git checkout "$TARGET_BRANCH" 2>&1); then log "ERROR: branch checkout failed" RESULTS["$DIR_KEY"]="FAIL (git checkout)" DURATIONS["$DIR_KEY"]=$((SECONDS - START)) @@ -142,55 +118,28 @@ for PAIR in "${TESTS[@]}"; do log "Checked out $TARGET_BRANCH" fi - # --- Apply composer.json fixes --- - # joachim-n/drupal-core-development-project uses "*" for all drupal/* constraints. - # Issue fork branches present as dev-ISSUEBRANCH; drupal/core-recommended's N.x-dev - # requirement won't match that, so Fix 1+2 adds an inline alias for issue forks only. - # Named release branches (10.6.x, 11.x) present at 10.6.x-dev / 11.x-dev โ€” the "*" - # constraints from the scaffold work fine. 12.x (main) also needs no fix. - cd "$PROJECT_DIR" - - CHECKED_OUT_BRANCH=$(git -C "$REPOS_DIR" branch --show-current 2>/dev/null || echo "") - TARGET_ALIAS=$(jq -r '.require["drupal/core"]' \ - "$REPOS_DIR/composer/Metapackage/CoreRecommended/composer.json" 2>/dev/null || echo "") - ACTUAL_DRUPAL_MAJOR=$(echo "$TARGET_ALIAS" | grep -oE '^[0-9]+' || echo "11") - if [ -z "$TARGET_ALIAS" ]; then - log "WARNING: could not read TARGET_ALIAS from CoreRecommended; defaulting to 11.x-dev" - ACTUAL_DRUPAL_MAJOR="11" - TARGET_ALIAS="11.x-dev" - fi - log "Detected Drupal $ACTUAL_DRUPAL_MAJOR.x (CoreRecommended requires: $TARGET_ALIAS)" - - # Fix 1+2 (issue forks on 10.x/11.x only): inline alias so path repo packages satisfy - # each other's N.x-dev constraints. Issue fork branches present as dev-ISSUEBRANCH, which - # doesn't satisfy drupal/core-recommended's requirement of e.g. 10.6.x-dev. Named release - # branches (10.6.x, 11.x) already present at 10.6.x-dev / 11.x-dev so no fix is needed โ€” - # the original "*" constraints in the scaffold work fine. 12.x also needs no fix. - if [ "$ACTUAL_DRUPAL_MAJOR" != "12" ] && [ -n "$ISSUE" ]; then - jq --arg val "dev-$CHECKED_OUT_BRANCH as $TARGET_ALIAS" \ - '.require |= with_entries(if (.key | startswith("drupal/")) and .key != "drupal/drupal" then .value = $val else . end)' \ - composer.json > composer.json.tmp && mv composer.json.tmp composer.json - jq --arg branch "dev-$CHECKED_OUT_BRANCH" \ - '.require["drupal/drupal"] = $branch' \ - composer.json > composer.json.tmp && mv composer.json.tmp composer.json - log " Inline alias: dev-$CHECKED_OUT_BRANCH as $TARGET_ALIAS; drupal/drupal pinned" + # --- Configure DDEV --- + if ! ddev describe >/dev/null 2>&1; then + log "Configuring DDEV ($PROJECT_TYPE)..." + ddev config --project-name "drupal-test-$DIR_KEY" --project-type "$PROJECT_TYPE" 2>&1 | tail -5 + ddev start 2>&1 | tail -10 + else + log "DDEV project already configured" + ddev start 2>&1 | tail -5 fi - # Fix 3: pin composer/composer when json-schema conflict present - # drupal/core-dev on some branches (10.x, 11.2.x) requires justinrainbow/json-schema ^5.2, - # but composer 2.9.x requires ^6.5.1 โ€” conflict. See https://www.drupal.org/project/drupal/issues/3557585 - _core_dev_json_schema=$(jq -r '.require["justinrainbow/json-schema"] // ""' \ - "$REPOS_DIR/composer/Metapackage/DevDependencies/composer.json" 2>/dev/null || echo "") - if echo "$_core_dev_json_schema" | grep -q '^\^5'; then - jq '.require["composer/composer"] = "~2.8.1" | .config.audit["block-insecure"] = false' \ - composer.json > composer.json.tmp && mv composer.json.tmp composer.json - log " Pinned composer/composer ~2.8.1 (json-schema conflict detected)" - fi + # --- Install add-on and composer install --- + log "Installing ddev-drupal-dev add-on..." + ddev add-on get amateescu/ddev-drupal-dev 2>&1 | tail -5 + ddev restart 2>&1 | tail -5 - # --- Run composer update -W --- - log "Running ddev composer update -W..." + log "Running ddev composer install..." COMPOSER_EXIT=0 - ddev composer update -W 2>&1 || COMPOSER_EXIT=$? + ddev composer install 2>&1 || COMPOSER_EXIT=$? + + if [ "$COMPOSER_EXIT" = "0" ]; then + ddev composer require drush/drush 2>&1 | tail -5 + fi # --- Record result --- ELAPSED=$((SECONDS - START)) diff --git a/drupal-core/scripts/update-drupal-cache b/drupal-core/scripts/update-drupal-cache index 9d2cac1..f93e7ab 100755 --- a/drupal-core/scripts/update-drupal-cache +++ b/drupal-core/scripts/update-drupal-cache @@ -4,17 +4,17 @@ # Refreshes the drupal-core seed cache used by the drupal-core Coder template. # Run this script on the Coder host server as the user who owns the seed directory. # -# The seed cache is a plain git clone of drupal/drupal at repos/drupal/ inside -# the seed directory. New workspaces pass it as a --reference hint to git clone, -# which reuses the local git objects and avoids downloading several hundred MB. -# Composer install still runs fresh inside each workspace. +# The seed cache is a plain git clone of drupal/drupal. New workspaces pass it +# as a --reference hint to git clone, reusing local git objects and avoiding +# several hundred MB of network transfer. Composer install still runs fresh +# inside each workspace. # # Usage: # ./update-drupal-cache [--seed-dir PATH] # # Options: -# --seed-dir PATH Absolute path to the seed directory. -# Default: ~/cache/drupal-core-seed (resolved to the running user's home) +# --seed-dir PATH Absolute path to the seed directory (the git clone root). +# Default: ~/cache/drupal-core-seed # The Coder template's cache_path variable must be set to the same path. # # Note: When run via the systemd timer, the seed directory is taken from the default @@ -39,10 +39,8 @@ while [[ $# -gt 0 ]]; do esac done -GIT_DIR="$SEED_DIR/repos/drupal" - -if [ ! -d "$GIT_DIR/.git" ]; then - echo "Error: Git clone not found at $GIT_DIR" >&2 +if [ ! -d "$SEED_DIR/.git" ]; then + echo "Error: Git clone not found at $SEED_DIR" >&2 echo "Run the initial setup first. See docs/admin/server-setup.md." >&2 exit 1 fi @@ -53,9 +51,9 @@ echo "Started: $(date)" echo "" echo "Fetching Drupal core git objects..." -git -C "$GIT_DIR" fetch --all --prune +git -C "$SEED_DIR" fetch --all --prune echo "" echo "=== Seed cache updated successfully ===" echo "Completed: $(date)" -echo "Drupal HEAD: $(git -C "$GIT_DIR" log -1 --format='%h %s' 2>/dev/null || echo 'unknown')" +echo "Drupal HEAD: $(git -C "$SEED_DIR" log -1 --format='%h %s' 2>/dev/null || echo 'unknown')" diff --git a/drupal-core/template.tf b/drupal-core/template.tf index f3ff4e6..5e52230 100644 --- a/drupal-core/template.tf +++ b/drupal-core/template.tf @@ -608,9 +608,9 @@ STATUS_HEADER DRUPAL_SETUP_NEEDED=true update_status "โณ Git clone: In progress..." _t=$SECONDS - if [ -d "$CACHE_SEED/repos/drupal/.git" ]; then + if [ -d "$CACHE_SEED/.git" ]; then log_setup "Cloning Drupal core (with reference from cache seed)..." - git clone --reference "$CACHE_SEED/repos/drupal" https://git.drupalcode.org/project/drupal.git "$DRUPAL_DIR" >> "$SETUP_LOG" 2>&1 || \ + git clone --reference "$CACHE_SEED" https://git.drupalcode.org/project/drupal.git "$DRUPAL_DIR" >> "$SETUP_LOG" 2>&1 || \ git clone https://git.drupalcode.org/project/drupal.git "$DRUPAL_DIR" >> "$SETUP_LOG" 2>&1 else log_setup "Cloning Drupal core..."