Skip to content

Commit 6d85160

Browse files
rfayclaude
andauthored
feat: add drupal-contrib template with beta unified issue picker, fixes #59 (#122)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2b8719f commit 6d85160

18 files changed

Lines changed: 3161 additions & 19 deletions

‎.github/workflows/drupal-contrib-integration-test.yml‎

Lines changed: 386 additions & 0 deletions
Large diffs are not rendered by default.

‎.github/workflows/drupal-integration-test.yml‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ name: Drupal Integration Tests
3131
env:
3232
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
3333

34+
concurrency:
35+
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
36+
cancel-in-progress: true
37+
3438
on:
3539
schedule:
3640
- cron: '0 4 * * *'
@@ -60,7 +64,7 @@ jobs:
6064
run:
6165
shell: bash -euo pipefail {0}
6266
env:
63-
WORKSPACE_NAME: ci-drupal-${{ matrix.drupal_version }}-${{ github.run_id }}
67+
WORKSPACE_NAME: cd-${{ matrix.drupal_version }}-${{ github.run_number }}-${{ github.run_attempt }}
6468
CI: "true"
6569
DDEV_NONINTERACTIVE: "true"
6670
NO_COLOR: "1"
@@ -110,6 +114,7 @@ jobs:
110114
--parameter issue_fork= \
111115
--parameter issue_branch= \
112116
--parameter install_profile=minimal \
117+
--parameter share_drupal_site=owner \
113118
--yes
114119
115120
- &verify-agent
@@ -200,7 +205,7 @@ jobs:
200205
run:
201206
shell: bash -euo pipefail {0}
202207
env:
203-
WORKSPACE_NAME: ci-drupal-fork-${{ github.run_id }}
208+
WORKSPACE_NAME: cd-fork-${{ github.run_number }}-${{ github.run_attempt }}
204209
CI: "true"
205210
DDEV_NONINTERACTIVE: "true"
206211
NO_COLOR: "1"
@@ -261,7 +266,7 @@ jobs:
261266
coder templates push drupal-core \
262267
--directory drupal-core \
263268
--activate=false \
264-
--name ci-${{ github.run_id }} \
269+
--name cd-${{ github.run_number }}-${{ github.run_attempt }} \
265270
--yes \
266271
--variable workspace_image_registry=index.docker.io/ddev/coder-ddev \
267272
--variable cache_path=/tmp/ci-no-cache
@@ -270,12 +275,13 @@ jobs:
270275
run: |
271276
coder create ${{ env.WORKSPACE_NAME }} \
272277
--template drupal-core \
273-
--template-version ci-${{ github.run_id }} \
278+
--template-version cd-${{ github.run_number }}-${{ github.run_attempt }} \
274279
--parameter "vscode_extensions=[]" \
275280
--parameter drupal_version=${{ env.ISSUE_FORK_VERSION }} \
276281
--parameter issue_fork=${{ env.ISSUE_FORK }} \
277282
--parameter issue_branch=${{ env.ISSUE_BRANCH }} \
278283
--parameter install_profile=minimal \
284+
--parameter share_drupal_site=owner \
279285
--yes
280286
281287
- name: Verify workspace — agent connected
@@ -350,4 +356,4 @@ jobs:
350356
351357
- name: Archive CI template version
352358
if: always()
353-
run: coder templates versions archive drupal-core ci-${{ github.run_id }} --yes || true
359+
run: coder templates versions archive drupal-core cd-${{ github.run_number }}-${{ github.run_attempt }} --yes || true

‎.github/workflows/integration-test.yml‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ env:
4444
on:
4545
push:
4646
branches: [main]
47+
paths-ignore:
48+
- 'drupal-core/**'
49+
- 'drupal-contrib/**'
4750
pull_request:
51+
paths-ignore:
52+
- 'drupal-core/**'
53+
- 'drupal-contrib/**'
4854
schedule:
4955
- cron: '0 3 * * *'
5056
workflow_dispatch:
@@ -82,8 +88,8 @@ jobs:
8288
run:
8389
shell: bash -euo pipefail {0}
8490
env:
85-
CI_TAG: ${{ github.run_id }}-${{ github.run_attempt }}
86-
WORKSPACE_NAME: ci-${{ matrix.ws_name }}-${{ github.run_id }}-${{ github.run_attempt }}
91+
CI_TAG: ${{ github.run_number }}-${{ github.run_attempt }}
92+
WORKSPACE_NAME: ci-${{ matrix.ws_name }}-${{ github.run_number }}-${{ github.run_attempt }}
8793
CI: "true"
8894
DDEV_NONINTERACTIVE: "true"
8995
NO_COLOR: "1"

‎CLAUDE.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,25 @@ This project provides a Coder v2+ template for DDEV-based development environmen
1919

2020
- Use `jq` (not `python3 -m json.tool`) for JSON pretty-printing and querying
2121

22+
## Before Pushing / Pre-push Checklist
23+
24+
Run these before every push to avoid CI failures:
25+
26+
```bash
27+
# Terraform formatting (CI runs terraform fmt -check -recursive)
28+
terraform fmt -recursive
29+
30+
# Terraform validation for each template you touched
31+
terraform -chdir=drupal-core init -backend=false && terraform -chdir=drupal-core validate
32+
terraform -chdir=drupal-contrib init -backend=false && terraform -chdir=drupal-contrib validate
33+
34+
# Terraform tests (plan-level, no real infrastructure)
35+
terraform -chdir=drupal-core test
36+
terraform -chdir=drupal-contrib test
37+
```
38+
39+
`terraform fmt -recursive` must be run from the repo root. It is non-destructive (rewrites in place) and the CI check fails with exit code 3 if any file is not formatted.
40+
2241
## Working with Coder Workspaces via SSH
2342

2443
After running `coder config-ssh --yes`, workspaces are available as SSH hosts named `<workspace>.coder`. Use `scp` to copy files in or out, then `ssh` to execute scripts non-interactively:
@@ -39,6 +58,10 @@ ssh mp1.coder ddev list
3958

4059
When running commands via `coder ssh -- ...` or piped heredocs, the PTY allocation causes interactive prompts and pipe-stall issues. Writing a script to `/tmp/` and executing it via `ssh workspace.coder bash /tmp/script.sh` is reliable for multi-step operations.
4160

61+
**CI scripting rule**: In GitHub Actions, for any `coder ssh` invocation that does more than a single trivial command, push a script file and run it — do not use `bash -c "..."`. Single commands with standard flags (e.g. `git -C /path branch --show-current`) are fine inline. Anything with `&&`, conditionals, or multiple statements belongs in a script file under the template's `scripts/` directory.
62+
63+
To run a command in a specific directory without a shell wrapper, use `env -C <dir> <cmd>` (available on Ubuntu 24.04 via GNU coreutils): `coder ssh ws -- env -C /home/coder/myproject ddev drush status`
64+
4265
## Essential Commands
4366

4467
### Template Management

‎Makefile‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ DOCKERFILE_DIR := image
77
DOCKERFILE := $(DOCKERFILE_DIR)/Dockerfile
88

99
# Template directories (name == directory name == Coder template name)
10-
TEMPLATES := user-defined-web drupal-core freeform
10+
TEMPLATES := user-defined-web drupal-core drupal-contrib freeform
1111

1212
# Host path to the drupal-core seed cache (bind-mounted read-only into workspaces).
1313
# This path is specific to the server where the template is deployed.
@@ -30,13 +30,16 @@ IMAGE_LATEST := $(IMAGE_NAME):latest
3030
TEMPLATE_VARS_user-defined-web := --variable workspace_image_registry=index.docker.io/$(IMAGE_NAME)
3131
TEMPLATE_VARS_drupal-core := --variable workspace_image_registry=index.docker.io/$(IMAGE_NAME) \
3232
--variable cache_path=$(DRUPAL_CACHE_PATH)
33+
TEMPLATE_VARS_drupal-contrib := --variable workspace_image_registry=index.docker.io/$(IMAGE_NAME)
3334
TEMPLATE_VARS_freeform := --variable workspace_image_registry=index.docker.io/$(IMAGE_NAME)
3435

3536
# Per-template display metadata set via `coder templates edit` after push
3637
# (coder templates push only supports --name, not --description)
3738
TEMPLATE_EDIT_user-defined-web := --display-name "DDEV Web Workspace"
3839
TEMPLATE_EDIT_drupal-core := --display-name "Drupal Core Development" \
3940
--description "Drupal core dev environment: full DDEV stack, core clone, Umami demo site. Ready in about a minute."
41+
TEMPLATE_EDIT_drupal-contrib := --display-name "Drupal Contrib Development" \
42+
--description "Drupal contrib module/theme dev: clone any drupal.org project, optional issue branch checkout. Ready in 5-10 minutes."
4043
TEMPLATE_EDIT_freeform := --display-name "DDEV Freeform (Traefik)" --default-ttl 24h
4144

4245
# Shared recipe for pushing any template (call with template name as argument)
@@ -167,12 +170,16 @@ push-template-user-defined-web: ## Push user-defined-web template to Coder
167170
push-template-drupal-core: ## Push drupal-core template to Coder
168171
$(call push_template,drupal-core)
169172

173+
.PHONY: push-template-drupal-contrib
174+
push-template-drupal-contrib: ## Push drupal-contrib template to Coder
175+
$(call push_template,drupal-contrib)
176+
170177
.PHONY: push-template-freeform
171178
push-template-freeform: ## Push freeform template to Coder
172179
$(call push_template,freeform)
173180

174181
.PHONY: push-all-templates
175-
push-all-templates: push-template-user-defined-web push-template-drupal-core push-template-freeform ## Push all templates to Coder (no image build)
182+
push-all-templates: push-template-user-defined-web push-template-drupal-core push-template-drupal-contrib push-template-freeform ## Push all templates to Coder (no image build)
176183
@echo "All templates pushed!"
177184

178185
# --- Deploy targets ---
@@ -189,6 +196,10 @@ deploy-user-defined-web-no-cache: build-and-push-no-cache push-template-user-def
189196
deploy-drupal-core: push-template-drupal-core ## Deploy drupal-core template (uses existing image)
190197
@echo "Deployment of drupal-core complete!"
191198

199+
.PHONY: deploy-drupal-contrib
200+
deploy-drupal-contrib: push-template-drupal-contrib ## Deploy drupal-contrib template (uses existing image)
201+
@echo "Deployment of drupal-contrib complete!"
202+
192203
.PHONY: deploy-freeform
193204
deploy-freeform: push-template-freeform ## Deploy freeform template (uses existing image)
194205
@echo "Deployment of freeform complete!"

‎README.md‎

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Fully automated Drupal core development environment, including issue fork suppor
123123
- **Setup**: Automatic (Drupal core cloned and installed, ~30s with seed cache)
124124
- **Use Case**: Drupal core development, contribution, patch testing
125125
- **Template Directory**: `drupal-core/`
126-
- **Issue Picker**: [start.coder.ddev.com/drupal-issue](https://start.coder.ddev.com/drupal-issue) — paste any drupal.org issue URL to launch a workspace with the issue branch pre-checked-out
126+
- **Issue Picker**: [start.coder.ddev.com/drupal-issue](https://start.coder.ddev.com/drupal-issue) — paste any drupal.org issue URL; the picker auto-detects core vs. contrib and routes to the right template
127127
- **Includes**:
128128
- Pre-cloned Drupal core (main branch by default)
129129
- Issue fork checkout with automatic Composer dependency resolution (Drupal 10, 11, and 12/main)
@@ -136,20 +136,43 @@ Fully automated Drupal core development environment, including issue fork suppor
136136
coder create --template drupal-core my-drupal-dev
137137
```
138138

139+
### drupal-contrib (Drupal Contrib Development)
140+
141+
Automated environment for developing Drupal contrib modules and themes, with optional issue branch support.
142+
143+
- **Setup**: Automatic (module/theme cloned, Drupal installed as dev dependency via `ddev-drupal-contrib`, ~5-10 min)
144+
- **Use Case**: Contrib module/theme development, issue queue work on any drupal.org project
145+
- **Template Directory**: `drupal-contrib/`
146+
- **Issue Picker**: [start.coder.ddev.com/drupal-issue](https://start.coder.ddev.com/drupal-issue) — paste a drupal.org issue or project URL; auto-detects contrib
147+
- **Includes**:
148+
- Any drupal.org project cloned (modules and themes)
149+
- Issue fork checkout via `issue_fork` + `issue_branch` parameters
150+
- DDEV with [`ddev-drupal-contrib`](https://github.com/ddev/ddev-drupal-contrib) addon (adds `ddev phpunit`, `ddev phpcs`, `ddev phpstan`)
151+
- Drupal installed as a dev dependency (module/theme auto-symlinked into web root)
152+
153+
**Create workspace:**
154+
```bash
155+
coder create --template drupal-contrib my-contrib-dev \
156+
--parameter project_name=token \
157+
--parameter drupal_version=11
158+
```
159+
139160
### Choosing a Template
140161

141162
- Use **user-defined-web** for:
142-
- Contrib module development
143-
- Site building
163+
- Site building and custom site projects
144164
- General Drupal/PHP projects
145165
- Maximum flexibility
146166

147167
- Use **drupal-core** for:
148-
- Drupal core patches
149-
- Core issue queue work
168+
- Drupal core patches and issue queue work
150169
- Testing Drupal core changes
151170
- Learning Drupal internals
152171

172+
- Use **drupal-contrib** for:
173+
- Contrib module or theme development
174+
- Working on drupal.org contrib issue queues
175+
153176
## Usage
154177

155178
Create a new workspace using your chosen template:
@@ -160,6 +183,10 @@ coder create --template user-defined-web <workspace-name>
160183

161184
# Drupal core development environment
162185
coder create --template drupal-core <workspace-name>
186+
187+
# Drupal contrib module/theme development
188+
coder create --template drupal-contrib <workspace-name> \
189+
--parameter project_name=token --parameter drupal_version=11
163190
```
164191

165192
**Access your project:**

0 commit comments

Comments
 (0)