9dc149f9838edf0504605a90039592fd3ab8d2af
[drupal-init-tools.git] / libexec / bootstrap.sh
1 #!/bin/bash
2 # Bootstrap a Drupal project
3 #
4 # Copyright (C) 2017  Antonio Ospite <ao2@ao2.it>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 set -e
20
21 usage() {
22   cat <<EOF
23 usage: drin $(basename "$0" .sh) [--devel|--overwrite-profile|-h|--help]
24
25 Bootstrap a Drupal project, using settings from a 'bootstrap.conf' file.
26
27 Options:
28   --devel              install drupal/devel and use a settings.local.php file
29   --overwrite-profile  allow overwriting the installation profile of the site
30                        with a profile copied from the current working directory
31   -h, --help           display this usage message and exit
32
33 EOF
34 }
35
36 while [ $# -gt 0 ];
37 do
38   case "$1" in
39     -h|--help)
40       usage
41       exit 0
42       ;;
43     --devel)
44       DEVEL_MODE="true"
45       ;;
46     --overwrite-profile)
47       OVERWRITE_PROFILE="true"
48       ;;
49     -*)
50       echo "Error: Unknown option '${1}'" 1>&2
51       ;;
52   esac
53   shift
54 done
55
56 [ -f "bootstrap.conf" ] || { echo "Aborting, run this command from the Drupal project directory." 1>&2; exit 1; }
57
58 # shellcheck disable=SC1091
59 . bootstrap.conf
60
61 declare -p DB_NAME
62 declare -p DB_USER
63 declare -p DB_PASS
64
65 declare -p ACCOUNT_NAME
66 declare -p ACCOUNT_PASS
67 declare -p ACCOUNT_MAIL
68
69 declare -p SITE_NAME
70 declare -p SITE_MAIL
71 declare -p SITE_BASE_PATH
72
73 declare -p TRUSTED_HOSTS
74
75 declare -p WEB_SERVER_GROUP
76
77 [ "x$INSTALLATION_PROFILE" = "x" ] && { echo "INSTALLATION_PROFILE not specified, using the \"standard\" profile!"; INSTALLATION_PROFILE="standard"; }
78
79 if [ "$MYSQL_PASSWORDLESS_ACCESS" = true ];
80 then
81   MYSQL_SU_USER="${USER}"
82 else
83   # XXX Deprecate MYSQL_ROOT_PASSWORD, it will be removed eventually,
84   # but for now add some backwards compatibility mapping.
85   if [ "x$MYSQL_ROOT_PASSWORD" != "x" ];
86   then
87     echo "WARN: MYSQL_ROOT_PASSWORD is deprecated, use MYSQL_SU_USER and MYSQL_SU_PASSWORD" 1>&2
88     MYSQL_SU_USER="root"
89     MYSQL_SU_PASSWORD="$MYSQL_ROOT_PASSWORD"
90   fi
91
92   if [ "x$MYSQL_SU_USER" = "x" ];
93   then
94     echo "Aborting, for password regulated access specify MYSQL_SU_USER in bootstrap.conf" 1>&2
95     exit 1
96   fi
97
98   if [ "x$MYSQL_SU_PASSWORD" = "x" ];
99   then
100     read -r -s -p "MySQL password for \"${MYSQL_SU_USER}\": " MYSQL_SU_PASSWORD
101     echo
102   fi
103
104   DRUSH_DB_SU_CREDENTIALS=(--db-su-pw'='"${MYSQL_SU_PASSWORD}")
105 fi
106
107 DRUSH_DB_SU_CREDENTIALS+=(--db-su'='"${MYSQL_SU_USER}")
108
109 WEB_ROOT="${PWD}/web"
110
111 command -v composer &> /dev/null || { echo "Aborting, 'composer' not available." 1>&2; exit 1; }
112 command -v git &> /dev/null || { echo "Aborting, 'git' not available." 1>&2; exit 1; }
113
114 [ -d "$WEB_ROOT" ] || composer install
115
116 DRUSH="${PWD}/vendor/bin/drush"
117 DRUPAL_CONSOLE="${PWD}/vendor/bin/drupal"
118
119 [ -x "$DRUSH" ] || { echo "Aborting, '$DRUSH' not available." 1>&2; exit 1; }
120 [ -x "$DRUPAL_CONSOLE" ] || { echo "Aborting, '$DRUPAL_CONSOLE' not available." 1>&2; exit 1; }
121
122 # The following becomes unnecessary if the installation profile gets pulled in
123 # by composer.json, like suggested in
124 # https://github.com/drupal-composer/drupal-project/issues/249
125 if ! echo "$INSTALLATION_PROFILE" | grep -q -E "^(minimal|standard)$";
126 then
127   if [ -d "${WEB_ROOT}/profiles/${INSTALLATION_PROFILE}" ] && [ "$OVERWRITE_PROFILE" != "true" ];
128   then
129     echo "Installation profile '$INSTALLATION_PROFILE' already there." 1>&2
130     echo "Use --overwrite-profile to copy over it." 1>&2
131     exit 1
132   else
133     if [ -d "$INSTALLATION_PROFILE" ];
134     then
135       cp -a "$INSTALLATION_PROFILE" "${WEB_ROOT}/profiles"
136     else
137       echo "Local installation profile '$INSTALLATION_PROFILE' not found." 1>&2
138       echo "Cannot honour the --overwrite-profile option." 1>&2
139     fi
140   fi
141 fi
142
143 # Make sure that drush knows what the actual base URI is, this is needed to
144 # have a consistent behavior between the cli and the web interface, for
145 # example in the case of modules that use base_path().
146 if grep -q "^[[:space:]]*uri:" drush/drush.yml;
147 then
148   sed -i -e "s@^\([[:space:]]*\)uri: .*@\1uri: 'http://localhost/${SITE_BASE_PATH}'@g" drush/drush.yml
149 else
150   echo "" >> drush/drush.yml
151   echo "options:" >> drush/drush.yml
152   echo "  uri: 'http://localhost/${SITE_BASE_PATH}'" >> drush/drush.yml
153 fi
154
155 pushd "$WEB_ROOT"
156
157 # Update the install_profile setting if it's already there
158 if grep -q "^\\\$settings\['install_profile'\] =" sites/default/settings.php;
159 then
160   chmod 755 sites/default
161   chmod 644 sites/default/settings.php
162   sed -i -e "s/^\(\$settings\['install_profile'\]\) = '[^']*';/\1 = '$INSTALLATION_PROFILE';/g" sites/default/settings.php
163   chmod 444 sites/default/settings.php
164   chmod 555 sites/default
165 fi
166
167 # Install the site
168 $DRUSH --verbose --yes \
169   site-install \
170   "${DRUSH_DB_SU_CREDENTIALS[@]}" \
171   --db-url="mysql://${DB_USER}:${DB_PASS}@localhost/${DB_NAME}" \
172   --site-name="$SITE_NAME" \
173   --site-mail="$SITE_MAIL" \
174   --sites-subdir="default" \
175   --account-name="$ACCOUNT_NAME" \
176   --account-pass="$ACCOUNT_PASS" \
177   --account-mail="$ACCOUNT_MAIL" \
178   "$INSTALLATION_PROFILE"
179
180 if $DRUSH pm-list --type=module --field=name --status=enabled --pipe | grep -q "^locale$";
181 then
182   # This is necessary for multi-language sites, it fixes some issues like:
183   #   "The Translation source field needs to be installed."
184   $DRUSH --yes entity-updates
185
186   # Update translations of contrib modules
187   $DRUSH --yes locale-update
188 fi
189
190 # This fixes permissions when installing under $HOME/public_html/
191 chmod 775 sites/default/files
192 sudo chgrp -R "$WEB_SERVER_GROUP" sites/default/files
193
194 [ -d ../config/sync ] && sudo chgrp -R "$WEB_SERVER_GROUP" ../config/sync
195
196 # Enable clean URLs
197 sed -i "s@\(# \)\{0,1\}RewriteBase .*\$@RewriteBase ${SITE_BASE_PATH}@" .htaccess
198
199 chmod 755 sites/default
200 chmod 644 sites/default/settings.php
201
202 # Add some basic settings to settings.php
203 if ! grep -q "^\\\$settings\['trusted_host_patterns'\] =" sites/default/settings.php;
204 then
205   echo "\$settings['trusted_host_patterns'] = [" >> sites/default/settings.php
206   for host in "${TRUSTED_HOSTS[@]}"
207   do
208     echo "  '^${host}\$'," >> sites/default/settings.php
209   done
210   echo "];" >> sites/default/settings.php
211 fi
212
213 if [ "$DEVEL_MODE" = "true" ];
214 then
215   # NOTE: don't run composer under web/ but in the project dir
216   composer --working-dir=../ require drupal/devel
217   $DRUSH --yes en devel
218
219   if [ ! -e sites/default/settings.local.php ];
220   then
221     cp sites/example.settings.local.php sites/default/settings.local.php
222
223     # Disable some overly permissive settings
224     sed -i -e "s/^\(\$settings\['rebuild_access'\]\).*$/\1 = FALSE;/g" sites/default/settings.local.php
225     sed -i -e "s/^\(\$settings\['skip_permissions_hardening'\]\).*$/\1 = FALSE;/g" sites/default/settings.local.php
226
227     chmod 444 sites/default/settings.local.php
228   fi
229
230   if ! grep -q "^include \$app_root . '/' . \$site_path . '/settings.local.php';" sites/default/settings.php;
231   then
232     echo "include \$app_root . '/' . \$site_path . '/settings.local.php';" >> sites/default/settings.php
233   fi
234 fi
235
236 chmod 444 sites/default/settings.php
237 chmod 555 sites/default
238
239 # If using a git checkout of Drupal core, set up a diff alias.
240 #
241 # This is useful because the Automated Test infrastructure of drupal.org does
242 # not expect patches to be created from a split core directory.
243 if [ -d core/.git ];
244 then
245   git -C core/ config --local alias.core-diff "diff --src-prefix=a/core/ --dst-prefix=b/core/"
246   echo "Added a 'git core-diff' command to the drupal/core repository clone."
247   echo "This command helps creating core patches ready for upstream."
248 fi
249
250 popd