Skip to content

Commit c145fa8

Browse files
Merge pull request #13 from emulsify-ds/feat-refine-compat-with-emulsify-drupal
feat: support Emulsify Drupal 6.x child theme generation workflow
2 parents 889b52b + 53d643e commit c145fa8

7 files changed

Lines changed: 303 additions & 35 deletions

File tree

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6+
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
7+
FIXTURE_DIR="${FIXTURE_DIR:-${TMPDIR:-/tmp}/emulsify-tools-generation-smoke}"
8+
DRUPAL_VERSION="${DRUPAL_VERSION:-11.3.*}"
9+
EMULSIFY_VERSION="${EMULSIFY_VERSION:-^6}"
10+
TOOLS_VERSION="${TOOLS_VERSION:-1.0.99}"
11+
DRUSH_VERSION="${DRUSH_VERSION:-^13}"
12+
THEME_NAME="${THEME_NAME:-watson}"
13+
DB_URL="${DB_URL:-sqlite://sites/default/files/.ht.sqlite}"
14+
LOCAL_PACKAGE_DIR="${FIXTURE_DIR}/local/emulsify_tools"
15+
16+
cleanup_fixture() {
17+
if [[ -d "$FIXTURE_DIR" ]]; then
18+
chmod -R u+w "$FIXTURE_DIR" 2>/dev/null || true
19+
rm -rf "$FIXTURE_DIR"
20+
fi
21+
}
22+
23+
log() {
24+
printf '\n==> %s\n' "$*"
25+
}
26+
27+
fail() {
28+
printf '\nERROR: %s\n' "$*" >&2
29+
exit 1
30+
}
31+
32+
assert_dir() {
33+
local dir="$1"
34+
35+
[[ -d "$dir" ]] || fail "Expected directory missing: ${dir}"
36+
}
37+
38+
assert_file() {
39+
local file="$1"
40+
41+
[[ -f "$file" ]] || fail "Expected file missing: ${file}"
42+
}
43+
44+
assert_not_exists() {
45+
local path="$1"
46+
47+
[[ ! -e "$path" ]] || fail "Unexpected path exists: ${path}"
48+
}
49+
50+
assert_contains() {
51+
local file="$1"
52+
local expected="$2"
53+
54+
grep -Fq "$expected" "$file" || fail "Expected ${file} to contain: ${expected}"
55+
}
56+
57+
assert_matches() {
58+
local file="$1"
59+
local pattern="$2"
60+
61+
grep -Eq "$pattern" "$file" || fail "Expected ${file} to match: ${pattern}"
62+
}
63+
64+
assert_command_fails_with() {
65+
local expected="$1"
66+
shift
67+
local output
68+
local status
69+
70+
set +e
71+
output="$("$@" 2>&1)"
72+
status=$?
73+
set -e
74+
75+
[[ "$status" -ne 0 ]] || fail "Expected command to fail: $*"
76+
grep -Fq "$expected" <<<"$output" || fail "Expected failed command output to contain: ${expected}"
77+
}
78+
79+
command -v composer >/dev/null || fail "composer is required."
80+
command -v php >/dev/null || fail "php is required."
81+
if [[ "$DB_URL" == sqlite://* ]]; then
82+
php -r 'exit(extension_loaded("pdo_sqlite") ? 0 : 1);' || fail "The pdo_sqlite PHP extension is required for DB_URL=${DB_URL}."
83+
fi
84+
85+
if [[ -x "$REPO_ROOT/vendor/bin/yaml-lint" ]]; then
86+
log "Linting module YAML files"
87+
"$REPO_ROOT/vendor/bin/yaml-lint" \
88+
"$REPO_ROOT/emulsify_tools.info.yml" \
89+
"$REPO_ROOT/emulsify_tools.services.yml" \
90+
"$REPO_ROOT/drush.services.yml"
91+
fi
92+
93+
if [[ "${KEEP_FIXTURE:-0}" != "1" ]]; then
94+
trap cleanup_fixture EXIT
95+
fi
96+
97+
log "Creating disposable Drupal fixture at ${FIXTURE_DIR}"
98+
cleanup_fixture
99+
composer create-project "drupal/recommended-project:${DRUPAL_VERSION}" "$FIXTURE_DIR" \
100+
--no-interaction \
101+
--no-progress
102+
103+
log "Copying this checkout as Drupal.org package drupal/emulsify_tools ${TOOLS_VERSION}"
104+
mkdir -p "$LOCAL_PACKAGE_DIR"
105+
tar \
106+
--exclude='.git' \
107+
--exclude='node_modules' \
108+
--exclude='vendor' \
109+
--exclude='.DS_Store' \
110+
-C "$REPO_ROOT" \
111+
-cf - . | tar -C "$LOCAL_PACKAGE_DIR" -xf -
112+
113+
php -r '
114+
$file = $argv[1];
115+
$json = json_decode(file_get_contents($file), true);
116+
$json["name"] = "drupal/emulsify_tools";
117+
file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL);
118+
' "$LOCAL_PACKAGE_DIR/composer.json"
119+
120+
cd "$FIXTURE_DIR"
121+
122+
repository_json="$(php -r '
123+
echo json_encode([
124+
"type" => "path",
125+
"url" => $argv[1],
126+
"options" => [
127+
"symlink" => false,
128+
"versions" => [
129+
"drupal/emulsify_tools" => $argv[2],
130+
],
131+
],
132+
], JSON_UNESCAPED_SLASHES);
133+
' "$LOCAL_PACKAGE_DIR" "$TOOLS_VERSION")"
134+
135+
composer config --json repositories.local_emulsify_tools "$repository_json"
136+
composer config prefer-stable true
137+
# This disposable compatibility fixture should test generation, not audit policy.
138+
composer config audit.block-insecure false
139+
140+
log "Installing Emulsify Drupal ${EMULSIFY_VERSION}, Emulsify Tools ${TOOLS_VERSION}, and Drush"
141+
composer require \
142+
"drupal/emulsify:${EMULSIFY_VERSION}" \
143+
"drupal/emulsify_tools:${TOOLS_VERSION}" \
144+
"drush/drush:${DRUSH_VERSION}" \
145+
--with-all-dependencies \
146+
--no-interaction \
147+
--no-progress
148+
149+
log "Installing Drupal fixture"
150+
mkdir -p web/sites/default/files
151+
vendor/bin/drush site:install minimal \
152+
--db-url="$DB_URL" \
153+
--site-name='Emulsify Tools generation smoke' \
154+
--account-name=admin \
155+
--account-pass=admin \
156+
-y
157+
158+
log "Enabling Emulsify Tools and the Emulsify parent theme"
159+
vendor/bin/drush pm:enable emulsify_tools -y
160+
vendor/bin/drush theme:enable emulsify -y
161+
vendor/bin/drush cr -y
162+
163+
log "Checking that the public Drush command is discoverable"
164+
vendor/bin/drush list | grep -Fq 'emulsify_tools:bake' || fail "Drush command emulsify_tools:bake was not discovered."
165+
vendor/bin/drush help emulsify >/dev/null || fail "Drush help for emulsify failed."
166+
vendor/bin/drush help emulsify_tools:bake >/dev/null || fail "Drush help for emulsify_tools:bake failed."
167+
168+
log "Generating ${THEME_NAME} with drush emulsify"
169+
vendor/bin/drush emulsify "$THEME_NAME"
170+
171+
theme_dir="web/themes/custom/${THEME_NAME}"
172+
info_file="${theme_dir}/${THEME_NAME}.info.yml"
173+
174+
log "Validating generated child theme files"
175+
assert_dir "$theme_dir"
176+
assert_file "$info_file"
177+
assert_matches "$info_file" '^[[:space:]]*base theme:[[:space:]]*emulsify[[:space:]]*$'
178+
assert_contains "$info_file" 'drupal:emulsify_tools (^1.0)'
179+
assert_file "${theme_dir}/config/install/${THEME_NAME}.settings.yml"
180+
assert_file "${theme_dir}/config/schema/${THEME_NAME}.schema.yml"
181+
assert_not_exists "${theme_dir}/whisk.info.emulsify.yml"
182+
assert_not_exists "${theme_dir}/config/install/whisk.settings.yml"
183+
assert_not_exists "${theme_dir}/config/schema/whisk.schema.yml"
184+
assert_not_exists "${theme_dir}/project.emulsify.json"
185+
186+
log "Confirming existing destination fails safely through drush emulsify_tools:bake"
187+
guard_checksum_before="$(cksum "$info_file")"
188+
assert_command_fails_with \
189+
"The destination theme already exists: themes/custom/${THEME_NAME}" \
190+
vendor/bin/drush emulsify_tools:bake "$THEME_NAME"
191+
guard_checksum_after="$(cksum "$info_file")"
192+
[[ "$guard_checksum_before" == "$guard_checksum_after" ]] || fail "Existing destination was modified: ${info_file}"
193+
194+
log "Confirming missing Whisk source fails clearly"
195+
emulsify_theme_path="$(vendor/bin/drush php:eval 'echo DRUPAL_ROOT . "/" . \Drupal::service("extension.list.theme")->getPath("emulsify");')"
196+
whisk_dir="${emulsify_theme_path}/whisk"
197+
missing_whisk_dir="${whisk_dir}.generation-smoke-missing"
198+
assert_dir "$whisk_dir"
199+
mv "$whisk_dir" "$missing_whisk_dir"
200+
assert_command_fails_with \
201+
"The Emulsify Whisk source directory was not found:" \
202+
vendor/bin/drush emulsify_tools:bake missing_source_theme
203+
mv "$missing_whisk_dir" "$whisk_dir"
204+
assert_not_exists "web/themes/custom/missing_source_theme"
205+
206+
log "Enabling generated child theme"
207+
vendor/bin/drush theme:enable "$THEME_NAME" -y
208+
vendor/bin/drush config:set system.theme default "$THEME_NAME" -y
209+
vendor/bin/drush cr -y
210+
211+
log "Emulsify Tools generation smoke test passed"

README.md

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
# Emulsify Tools module
22

3-
This module provides two Twig extensions used in the [Emulsify Design System](https://github.com/emulsify-ds/) as well as a theme generation Drush command.
3+
This module provides Twig helpers used in the [Emulsify Design System](https://github.com/emulsify-ds/) and the Drush child theme generation workflow for Emulsify Drupal 6.x.
4+
5+
## Compatibility
6+
7+
Emulsify Tools 1.x is intended for the Emulsify Drupal 6.x child theme generation workflow. The paired Emulsify Drupal 6.x release line supports Drupal `^10.3 || ^11`.
48

59
## Usage
610

7-
---
11+
### Child theme generation
812

9-
### Drush
13+
Emulsify Tools 1.x provides the supported Drush workflow for generating Emulsify Drupal 6.x child themes. Use either command form:
1014

11-
`drush emulsify_tools:bake [theme_name]`
15+
```
16+
drush emulsify my_theme
17+
drush emulsify_tools:bake my_theme
18+
```
1219

13-
`drush emulsify [theme_name]`
20+
The commands are equivalent. The generated child theme uses `emulsify` as its runtime parent theme and should be created under the Drupal custom theme path expected by the command, such as `web/themes/custom/my_theme` in a Composer-based Drupal project.
21+
22+
Drupal core Starterkit-based generation is being prepared for the Emulsify Drupal 7.x release line. For Emulsify Drupal 6.x, use Emulsify Tools for child theme generation.
1423

1524
### BEM Twig Extension
1625

17-
Twig function that inserts static classes into Pattern Lab and adds them to the Attributes object in Drupal
26+
The `bem()` Twig function builds BEM class names and returns them in a form that can be printed into Drupal template attributes.
1827

1928
#### Simple block name (required argument):
2029

@@ -66,7 +75,7 @@ This creates:
6675

6776
### Add Attributes Twig Extension
6877

69-
Twig function that merges with template level attributes in Drupal and prevents them from trickling down into includes.
78+
The `add_attributes()` Twig function merges additional attributes with Drupal's template-level attributes and prevents those attributes from trickling into child includes.
7079

7180
```
7281
{% set additional_attributes = {
@@ -102,6 +111,31 @@ Can also be used with the BEM Function:
102111

103112
1. Run `npm install` to install dependencies. You're done!
104113

114+
### Generation Smoke Test
115+
116+
To validate the Emulsify Drupal 6.x child theme generation workflow against this checkout, run:
117+
118+
```
119+
.github/scripts/generation-smoke.sh
120+
```
121+
122+
The script creates a disposable Drupal fixture site, installs Emulsify Drupal `^6`, installs this checkout as Emulsify Tools `1.x`, verifies both Drush command help targets, runs `drush emulsify watson`, validates the generated theme files, and enables the generated child theme. It intentionally does not test Drupal core Starterkit generation.
123+
124+
Requirements: Composer and PHP. The default SQLite fixture database also requires `pdo_sqlite`.
125+
126+
Optional environment variables:
127+
128+
```
129+
FIXTURE_DIR=/tmp/emulsify-tools-generation-smoke
130+
DRUPAL_VERSION=11.3.*
131+
EMULSIFY_VERSION=^6
132+
TOOLS_VERSION=1.0.99
133+
DRUSH_VERSION=^13
134+
THEME_NAME=watson
135+
DB_URL=sqlite://sites/default/files/.ht.sqlite
136+
KEEP_FIXTURE=1
137+
```
138+
105139
### Committing Changes
106140

107141
To facilitate automatic semantic release versioning, we utilize the [Conventional Changelog](https://github.com/conventional-changelog/conventional-changelog) standard through Commitizen. Follow these steps when commiting your work to ensure a better tomorrow.

drush.services.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
services:
2+
emulsify_tools.commands:
3+
class: Drupal\emulsify_tools\Drush\Commands\SubThemeCommands
4+
arguments: ['@extension.list.theme', '@plugin.manager.archiver', '@emulsify_tools.subtheme_generator', '@emulsify_tools.filesystem']
5+
tags:
6+
- { name: drush.command }

emulsify_tools.info.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Emulsify Tools
22
type: module
33
description: Toolset of useful Twig extensions and a subtheme generation command.
4-
core_version_requirement: ^10 || ^11
4+
core_version_requirement: ^10.3 || ^11
55
package: Emulsify
66

77
# Information added by Drupal.org packaging script on 2023-02-16

emulsify_tools.services.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ services:
99
parent: twig.extension
1010
tags:
1111
- { name: twig.extension }
12-
emulsify_tools.commands:
13-
class: Drupal\emulsify_tools\Drush\Commands\SubThemeCommands
14-
arguments: ['@extension.list.theme', '@plugin.manager.archiver', '@emulsify_tools.subtheme_generator', '@file_system']
15-
tags:
16-
- { name: drush.command }
1712
emulsify_tools.subtheme_generator:
1813
class: Drupal\emulsify_tools\SubThemeGenerator
14+
arguments: ['@emulsify_tools.filesystem']
15+
emulsify_tools.filesystem:
16+
class: Symfony\Component\Filesystem\Filesystem

0 commit comments

Comments
 (0)