From c84b8bb45931136365570a0aa2c646334981481b Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sat, 26 Sep 2026 17:43:59 -0600 Subject: [PATCH 1/3] Fix phpunit SIMPLETEST_BASE_URL failures in drupal-core, fixes #211 drupal-core always omits ddev-router, so DDEV never populates DDEV_PRIMARY_URL. amateescu/ddev-drupal-dev's own config.drupal-dev.yaml sets SIMPLETEST_BASE_URL=${DDEV_PRIMARY_URL}, which is therefore always empty, failing every phpunit functional/JS test with "You must provide a SIMPLETEST_BASE_URL environment variable". Reproduced live on a staging workspace, including the exact SettingSummariesContentTypeTest::testWorkflowSummary test from the issue report. Override SIMPLETEST_BASE_URL to the web container's own Docker-network hostname (http://web), which is reachable regardless of routing, via a config.zzz-coder-test-env.yaml file named to sort after the add-on's own config file so it wins. Also point BROWSERTEST_OUTPUT_BASE_URL at the real Coder proxy URL instead of the container-only http://web, so failed-test debug links are actually clickable from outside. drupal-contrib is unaffected: its ddev-drupal-contrib add-on already hardcodes SIMPLETEST_BASE_URL=http://web rather than relying on DDEV_PRIMARY_URL. Add a phpunit smoke-test step to both drupal-integration-test.yml and drupal-contrib-integration-test.yml's GH-runner jobs so this class of regression is caught in CI going forward. Co-Authored-By: Claude Sonnet 5 --- .../drupal-contrib-integration-test.yml | 24 ++++++++++++++ .github/workflows/drupal-integration-test.yml | 12 +++++++ drupal-core/template.tf | 33 +++++++++++++++++++ image/scripts/.gitignore_global | 1 + 4 files changed, 70 insertions(+) diff --git a/.github/workflows/drupal-contrib-integration-test.yml b/.github/workflows/drupal-contrib-integration-test.yml index b28ac3d..052a977 100644 --- a/.github/workflows/drupal-contrib-integration-test.yml +++ b/.github/workflows/drupal-contrib-integration-test.yml @@ -175,6 +175,18 @@ jobs: echo "--- end ---" echo "$MODULES" | grep -iw "${{ matrix.project }}" + - name: Verify workspace — PHPUnit functional test runs + # Runs a core test (present in every project's web root) rather than + # a module-specific one, so this step doesn't need to vary per matrix + # entry. Same regression class as drupal-core issue #211: if this + # template ever stopped setting SIMPLETEST_BASE_URL to a value + # reachable from inside the web container, every functional test + # would fail with "You must provide a SIMPLETEST_BASE_URL + # environment variable". + run: | + coder ssh ${{ env.WORKSPACE_NAME }} -- env -C /home/coder/${{ matrix.project }} \ + ddev phpunit --filter testTitle web/core/modules/system/tests/src/Functional/System/PageTitleTest.php + - name: Record expected host directory run: | OWNER=$(coder whoami --output json | jq -r 'if type == "array" then .[0].username else .username end') @@ -562,6 +574,18 @@ jobs: echo "--- end ---" echo "$MODULES" | grep -iw "${{ matrix.project }}" + - name: Verify workspace — PHPUnit functional test runs + # Runs a core test (present in every project's web root) rather than + # a module-specific one, so this step doesn't need to vary per matrix + # entry. Same regression class as drupal-core issue #211: if this + # template ever stopped setting SIMPLETEST_BASE_URL to a value + # reachable from inside the web container, every functional test + # would fail with "You must provide a SIMPLETEST_BASE_URL + # environment variable". + run: | + coder ssh ${{ env.WORKSPACE_NAME }} -- env -C /home/coder/${{ matrix.project }} \ + ddev phpunit --filter testTitle web/core/modules/system/tests/src/Functional/System/PageTitleTest.php + - name: Record owner run: | OWNER=$(coder whoami --output json | jq -r 'if type == "array" then .[0].username else .username end') diff --git a/.github/workflows/drupal-integration-test.yml b/.github/workflows/drupal-integration-test.yml index e2dc8f2..6aad51f 100644 --- a/.github/workflows/drupal-integration-test.yml +++ b/.github/workflows/drupal-integration-test.yml @@ -159,6 +159,17 @@ jobs: name: Verify workspace — Drush DB connected run: coder ssh ${{ env.WORKSPACE_NAME }} -- ddev drush status --fields=db-status | grep -i connected + - &verify-phpunit + # Regression check for #211: amateescu/ddev-drupal-dev's own + # SIMPLETEST_BASE_URL=${DDEV_PRIMARY_URL} is empty because this + # template always omits ddev-router, which broke every phpunit + # functional test. See the SIMPLETEST_BASE_URL override written in + # template.tf's Step 4. + name: Verify workspace — PHPUnit functional test runs (#211) + run: | + coder ssh ${{ env.WORKSPACE_NAME }} -- \ + ddev phpunit --filter testTitle core/modules/system/tests/src/Functional/System/PageTitleTest.php + - &record-host-dir name: Record expected host directory run: | @@ -309,6 +320,7 @@ jobs: - *verify-ddev - *verify-webroot - *verify-drush + - *verify-phpunit - *record-host-dir - *verify-http diff --git a/drupal-core/template.tf b/drupal-core/template.tf index 468d51a..7692a7f 100644 --- a/drupal-core/template.tf +++ b/drupal-core/template.tf @@ -393,6 +393,8 @@ resource "coder_agent" "main" { elif [ -f "$HOME/.gitignore_global" ]; then grep -qxF 'config.coder.yaml' "$HOME/.gitignore_global" || \ echo 'config.coder.yaml' >> "$HOME/.gitignore_global" + grep -qxF 'config.zzz-coder-test-env.yaml' "$HOME/.gitignore_global" || \ + echo 'config.zzz-coder-test-env.yaml' >> "$HOME/.gitignore_global" fi if [ -n "$CODER_WORKSPACE_OWNER_NAME" ]; then git config --global user.name "$CODER_WORKSPACE_OWNER_NAME" @@ -809,6 +811,37 @@ WELCOME_STATIC fi if [ "$SETUP_FAILED" != "true" ]; then + # The add-on's own .ddev/config.drupal-dev.yaml sets SIMPLETEST_BASE_URL + # from DDEV_PRIMARY_URL, but this template always omits ddev-router (see + # Step 2), and DDEV leaves DDEV_PRIMARY_URL empty whenever the router is + # disabled -- so phpunit fails every functional test with "You must + # provide a SIMPLETEST_BASE_URL environment variable" (fixes #211). + # Override it with the web container's own Docker-network hostname, + # which is always reachable from both PHP-CLI and the chrome container + # regardless of routing. The filename must sort alphabetically after + # "config.drupal-dev.yaml" so DDEV layers it on top and this value wins. + # + # BROWSERTEST_OUTPUT_BASE_URL only prefixes the human-clickable debug + # links phpunit prints for failed browser tests -- those HTML + # snapshots live in the docroot and are served over the same URL as + # the site itself, so point it at the real Coder proxy URL (matches + # coder_app.drupal-site's subdomain) rather than the container-only + # http://web, so the links are actually openable from outside. + if [ -n "$CODER_DOMAIN" ]; then + BROWSERTEST_URL="https://drupal-site--$${CODER_WORKSPACE_NAME}--$${CODER_WORKSPACE_OWNER_NAME}.$CODER_DOMAIN" + else + BROWSERTEST_URL="http://web" + fi + cat > .ddev/config.zzz-coder-test-env.yaml << TESTENV_EOF +#ddev-generated +#ddev-silent-no-warn +# Auto-generated by workspace startup -- do not edit. See Step 4 in template.tf. +web_environment: + - SIMPLETEST_BASE_URL=http://web + - BROWSERTEST_OUTPUT_BASE_URL=$BROWSERTEST_URL +TESTENV_EOF + log_setup "✓ .ddev/config.zzz-coder-test-env.yaml written (SIMPLETEST_BASE_URL override)" + log_setup "Restarting DDEV to activate add-on..." ddev restart >> "$SETUP_LOG" 2>&1 || true diff --git a/image/scripts/.gitignore_global b/image/scripts/.gitignore_global index 261c962..1930893 100644 --- a/image/scripts/.gitignore_global +++ b/image/scripts/.gitignore_global @@ -1,5 +1,6 @@ # DDEV Coder integration config.coder.yaml +config.zzz-coder-test-env.yaml # macOS .DS_Store From b77742b9fa9bde1772adabaf71b37dc32baf4711 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sat, 26 Sep 2026 18:13:26 -0600 Subject: [PATCH 2/3] Fix D12 core/tests missing due to dev-branch dist zip stripping, fixes #216 The new phpunit CI step added earlier in this branch failed on the "Contrib skipto D12 (plain, GH)" cell with "Cannot open bootstrap script core/tests/bootstrap.php": https://github.com/ddev/coder-ddev/actions/runs/36280470996/job/108511195288 drupal_version=12 has no stable tag yet, so it resolves to the 12.x-dev branch (see #212). Composer's default dist install for a -dev/branch version fetches a GitHub zipball, which is a git-archive snapshot honoring drupal/core's own .gitattributes export-ignore rules -- and those strip core/tests entirely. D10/D11 are unaffected since they resolve to real tagged releases, whose dist packages aren't built this way. Verified: a plain `git clone` of the same ref includes tests/, and forcing `composer config preferred-install.drupal/core source` (so Composer does a real clone instead of downloading the zipball) fixes it end-to-end -- confirmed core/tests present and the CI smoke test (`ddev phpunit web/core/modules/system/tests/src/Functional/System/PageTitleTest.php`) passing on a fresh workspace. Set that config only for drupal_version=12, before `ddev poser` runs; D10/D11 are untouched since forcing source there would only slow down every install for no benefit. Co-Authored-By: Claude Sonnet 5 --- drupal-contrib/template.tf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drupal-contrib/template.tf b/drupal-contrib/template.tf index d471f93..94629b2 100644 --- a/drupal-contrib/template.tf +++ b/drupal-contrib/template.tf @@ -738,6 +738,22 @@ COMPOSE_EOF # symfony/runtime) that aren't pre-listed in allow-plugins. jq 'if .config == null then .config = {} else . end | .config["allow-plugins"] = true' composer.json > composer.json.tmp && mv composer.json.tmp composer.json + # D12 has no stable tagged release yet, so DRUPAL_CORE_CONSTRAINT below + # resolves to the 12.x-dev branch. Composer's default dist install for a + # -dev/branch version fetches a GitHub zipball (a git-archive snapshot), + # which honors drupal/core's own .gitattributes export-ignore rules and + # strips the core/tests directory -- so any test referencing core (e.g. + # `ddev phpunit web/core/modules/...`) fails with "Cannot open bootstrap + # script core/tests/bootstrap.php". A real `git clone` (source install) + # does not apply export-ignore, so force source installs for drupal/core + # on D12 only -- D10/D11 use real tagged releases, whose dist packages + # already include tests, and forcing source there would just slow down + # every install for no benefit. + if [ "$DRUPAL_VERSION" = "12" ]; then + jq 'if .config == null then .config = {} else . end | .config["preferred-install"]["drupal/core"] = "source"' composer.json > composer.json.tmp && mv composer.json.tmp composer.json + log_setup "✓ drupal/core preferred-install set to source (D12 dev branch strips core/tests from dist)" + fi + # Obtain a GitHub token for Composer OAuth — routes downloads through the # authenticated GitHub API instead of anonymous codeload.github.com # (which is prone to transient HTTP/2 400s and rate limits). From c9438733e7ff85ae1abd228f7da85d50be27401f Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Sat, 26 Sep 2026 18:22:25 -0600 Subject: [PATCH 3/3] Clarify that D12's constraint tracks the main branch via composer alias Confirmed with the user: D12 is already meant to track HEAD of drupal/core's main branch, matching how people actually work on D12 issues locally. The "12.x-dev" constraint achieves this indirectly -- it's not a branch name but the version composer's branch-alias maps main onto -- which was non-obvious enough to be worth spelling out. No behavior change. Co-Authored-By: Claude Sonnet 5 --- drupal-contrib/template.tf | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drupal-contrib/template.tf b/drupal-contrib/template.tf index 94629b2..c796d31 100644 --- a/drupal-contrib/template.tf +++ b/drupal-contrib/template.tf @@ -687,6 +687,17 @@ COMPOSE_EOF # HEAD as the workflow comment above claims. DRUPAL_CORE_CONSTRAINT="^$DRUPAL_VERSION" if [ "$DRUPAL_VERSION" = "12" ]; then + # "12.x-dev" isn't a literal branch name -- it's the version string that + # drupal/core's composer.json branch-alias (extra.branch-alias) maps its + # actual default git branch onto, so this constraint resolves to the + # HEAD of that branch (currently "main"; installed packages report as + # "dev-main"). People fixing D12 issues normally work against "main" + # directly, so this constraint is meant to track exactly that -- it's + # just expressed as a version, not a branch name, because that's what + # lets other packages' "^12"-style requirements resolve against the + # same install (the reason #212 picked this form over "dev-main" + # literally). Expect this whole workaround to go away once 12.0.0 + # ships and a normal tagged release exists to depend on instead. DRUPAL_CORE_CONSTRAINT="12.x-dev" fi ddev dotenv set .ddev/.env.web --drupal-core "$DRUPAL_CORE_CONSTRAINT"