68bf0dff4e7ed067e60a2d738c043ab31e8abad0
[gnupg-doc.git] / tools / build-website.sh
1 #!/bin/sh
2 # Build the gnupg.org website from a git working directory.
3 #
4 # This script requires two users
5 #
6 #   webbuilder - the user to run this script
7 #   webbuild-x - the user used by this script to run emacs
8 #
9 # A certain directory layout is required with permissions setup
10 # so that the webbuild-x has only write access to the stage area
11 # and to its own home directory.  The script checks the permissions.
12 #
13 # The trigger-website-build scripts is expected to be installed
14 # as git post-merge hook.
15 #
16 # These cronjobs are required for user webbuilder:
17 # --8<---------------cut here---------------start------------->8---
18 # # Pull the master branch of the web pages
19 # */20  * * * * cd /home/webbuilder/gnupg-doc && git pull -q origin master
20 #
21 # # In case of race conditions we try to build every few ours again.
22 # 35  */7 * * * /home/webbuilder/bin/build-website.sh --cron
23 # --8<---------------cut here---------------end--------------->8---
24 #
25 # /etc/sudoers needs this:
26 # --8<---------------cut here---------------start------------->8---
27 # # Let webbuilder run any command as user webbuild-x
28 # webbuilder         ALL = (webbuild-x) NOPASSWD: ALL
29 # --8<---------------cut here---------------end--------------->8---
30 #
31
32 set -e
33
34 pgm=build-website.sh
35 mainuser=webbuilder
36 workuser=webbuild-x
37
38 # We use a fixed HOME so that this script can be run here from other
39 # accounts.
40 HOME=$(awk </etc/passwd -F: '$1=="'$mainuser'" {print $6;exit}')
41 if [ ! -d "$HOME" ]; then
42    echo "$pgm: directory '${HOME}' missing" >&2;
43    exit 1
44 fi
45
46 reponame=gnupg-doc
47 htdocs_web="/var/www/www/www.gnupg.org/htdocs"
48 htdocs_blog="/var/www/www/www.gnupg.org/misc/blog"
49
50 workuser_dir=$HOME/${workuser}
51 log_dir="$HOME/log"
52 root_dir="$HOME/${reponame}"
53 stage_dir="$HOME/${reponame}-stage"
54 LOCKFILE="${log_dir}/${reponame}.lock"
55
56 if [ x"$1" = x"--git" ]; then
57   shift
58   exec  >>${log_dir}/"$reponame".log 2>&1
59   echo "$(date -u -Iseconds) gpgweb site build was git triggered"
60 elif [ x"$1" = x"--cron" ]; then
61   shift
62   exec  >>${log_dir}/"$reponame".log 2>&1
63   echo "$(date -u -Iseconds) gpgweb site build was cron triggered"
64 fi
65
66 if ! id $workuser >/dev/null 2>&1 ; then
67    echo "$pgm: sudo user '${workuser}' not available" >&2;
68    exit 1
69 fi
70
71 # Check directories
72 for f in "${workuser_dir}" "${root_dir}" "${stage_dir}"; do
73   if [ ! -d "$f" ]; then
74      echo "$pgm: directory '$f' missing" >&2;
75      exit 1
76   fi
77 done
78 want="2775:${workuser}:${mainuser}"
79 for f in "${workuser_dir}" "${stage_dir}"; do
80   x=$(stat -c '%a:%U:%G' "$f")
81   if [ x"$x" != x"$want" ]; then
82     echo "$pgm: directory '$f' has wrong permissions" >&2
83     echo "$pgm:   want: $want" >&2
84     echo "$pgm:   have: $x" >&2
85     exit 1
86   fi
87 done
88
89 cd "${root_dir}"
90
91 #
92 # Take a lock so that only one instacne of this script runs.
93 #
94 if ! lockfile -l 7200 -r 2 $LOCKFILE; then
95     echo "$pgm: another instance is still running" >&2
96     exit 0
97 fi
98 trap "rm -f $LOCKFILE" 0
99
100
101 # These flags are set to the stage directory iof a sync is required
102 sync_web=
103 sync_blog=
104
105 #
106 # Build main part
107 #
108 subdir=web
109
110 revlastfile="${log_dir}/${reponame}.$(echo $subdir | tr / _).revlast"
111 buildlog="${log_dir}/${reponame}.$(echo $subdir | tr / _).log"
112 rev="$(git rev-parse --verify HEAD:$subdir)"
113 if [ -z "$rev" ]; then
114    echo "$pgm: No git revision found" >&2;
115    exit 1
116 fi
117 revlast="$(head -1 ${revlastfile} 2>/dev/null || true)"
118 if [ x"$rev" = x"$revlast" ]; then
119    echo "$pgm: No need to build $subdir" >&2;
120 else
121
122   echo "$(date -u -Iseconds) build started for $subdir" | tee ${buildlog}
123
124   if [ ! -d ${stage_dir}/${subdir} ]; then
125       sudo -u webbuild-x mkdir ${stage_dir}/${subdir}
126   fi
127
128   sudo 2>>${buildlog} -u webbuild-x emacs24 -q --batch  \
129   --eval "(require 'assoc)" \
130   --eval "(require 'org)" \
131   --eval "(setq make-backup-files nil)" \
132   --eval "(setq gpgweb-root-dir  \"${root_dir}/${subdir}/\")" \
133   --eval "(setq gpgweb-stage-dir \"${stage_dir}/${subdir}/\")" \
134   --eval "(require 'gpgweb (concat gpgweb-root-dir \"share/gpgweb.el\"))" \
135   --eval "(setq org-publish-use-timestamps-flag nil)" \
136   --eval "(setq org-export-html-toplevel-hlevel 1)" \
137   --eval "(setq org-export-html-coding-system 'utf-8)" \
138   --eval "(gpgweb-setup-project)" \
139   --eval "(org-publish-initialize-cache \"gpgweb\")" \
140   --eval "(message \"root=(%s)\" gpgweb-root-dir)" \
141   --eval "(org-publish \"gpgweb\" t nil)"
142
143   echo "$rev" > ${revlastfile}
144   sync_web=${stage_dir}/${subdir}
145   echo "$(date -u -Iseconds) build finished for $subdir" | tee -a ${buildlog}
146 fi
147
148
149 #
150 # Build blogs
151 #
152 subdir=misc/blog.gnupg.org
153
154 revlastfile="${log_dir}/${reponame}.$(echo $subdir | tr / _).revlast"
155 buildlog="${log_dir}/${reponame}.$(echo $subdir | tr / _).log"
156 rev="$(git rev-parse --verify HEAD:$subdir)"
157 if [ -z "$rev" ]; then
158    echo "$pgm: No git revision found" >&2;
159    exit 1
160 fi
161 revlast="$(head -1 ${revlastfile} 2>/dev/null || true)"
162 if [ x"$rev" = x"$revlast" ]; then
163    echo "$pgm: No need to build $subdir" >&2;
164 else
165
166   echo "$(date -u -Iseconds) build started for $subdir" | tee ${buildlog}
167
168   if [ ! -d ${stage_dir}/${subdir} ]; then
169       sudo -u webbuild-x mkdir -p ${stage_dir}/${subdir}
170   fi
171   cd ${stage_dir}/${subdir}
172
173   # We need to initialize that org cache to use our own publish function
174   # despite that we do not use any org-publish feature
175   echo "$pgm: Rendering blogs" >&2
176   sudo 2>>${buildlog} -u webbuild-x emacs24 -q --batch \
177   --eval "(require 'assoc)" \
178   --eval "(require 'org)" \
179   --eval "(setq gpgweb-root-dir \"${root_dir}/web/\")" \
180   --eval "(setq gpgweb-blog-dir \"${root_dir}/${subdir}/\")" \
181   --eval "(setq gpgweb-stage-dir \"${stage_dir}/${subdir}/\")" \
182   --eval "(require 'gpgweb (concat gpgweb-root-dir \"share/gpgweb.el\"))" \
183   --eval "(setq org-publish-use-timestamps-flag nil)" \
184   --eval "(setq org-export-html-toplevel-hlevel 1)" \
185   --eval "(setq org-export-html-coding-system 'utf-8)" \
186   --eval "(gpgweb-setup-project)" \
187   --eval "(org-publish-initialize-cache \"gpgweb\")" \
188   --eval "(message \"root=(%s)\" gpgweb-root-dir)" \
189   --eval "(gpgweb-publish-blogs)"
190
191   echo "$pgm: Updating blog index" >&2
192   indexcreator="${root_dir}/${subdir}/update-index.sh"
193   if [ ! -f $indexcreator ]; then
194     echo "$pgm: $indexcreator not found" >&2
195     exit 1
196   fi
197   sudo -u webbuild-x ${indexcreator}
198
199   echo "$rev" > ${revlastfile}
200   sync_blog=${stage_dir}/${subdir}
201   echo "$(date -u -Iseconds) build finished for $subdir" | tee -a ${buildlog}
202
203 fi
204
205
206 #
207 # Sync to the webspace
208 #
209 cd "${root_dir}"
210 any_sync=
211
212 if [ -n "$sync_web" ]; then
213   cd "$sync_web"
214   rsync -rlt --exclude '*~' --exclude '*.tmp' \
215         . ${htdocs_web}/
216   touch ${htdocs_web}/donate/donors.dat
217   cd ${htdocs_web}
218   ln -sf ../../howtos.gnupg.org/htdocs howtos
219   ln -sf software related_software
220   ln -sf software/index.html features.html
221   cd "$sync_web"
222   any_sync=yes
223 fi
224
225 if [ -n "$sync_blog" ]; then
226   cd "$sync_blog"
227   rsync -rt --links --exclude '*~' --exclude '*.sh' \
228         --exclude '*tmp' --exclude '*.org' --exclude headlines.txt \
229         . ${htdocs_blog}/
230   any_sync=yes
231 fi
232
233 if [ "$any_sync" = yes ]; then
234   $HOME/bin/mkkudos.sh --verbose --force
235 fi
236
237
238 #
239 # Print warnings when the scripts are out of date
240 # (For security reasons the scripts need to be installed manually.)
241 #
242 for f in trigger-website-build build-website.sh mkkudos.sh \
243          append-to-donors.sh ; do
244   if ! cmp -s ${HOME}/bin/$f tools/$f ; then
245     echo "$pgm: Warning: A newer version of $f is available" >&2;
246   fi
247 done
248
249 exit 0