6771b65df59f6c774e48c3de0525e378d78213a7
[vlendec/samba-autobuild/.git] / script / release.sh
1 #!/bin/bash
2 # make a release of Samba or a library
3
4 LC_ALL=C
5 export LC_ALL
6 LANG=C
7 export LANG
8 LANGUAGE=C
9 export LANGUAGE
10
11 set -u
12 set -e
13 umask 0022
14
15 CONF_REPO_URL="ssh://git.samba.org/data/git/samba.git"
16 CONF_UPLOAD_URL="samba-bugs@download-master.samba.org:/home/data/ftp/pub"
17 CONF_DOWNLOAD_URL="https://download.samba.org/pub"
18 CONF_HISTORY_URL="https://www.samba.org"
19
20 test -d ".git" || {
21         echo "Run this script from the top-level directory in the"
22         echo "repository"
23         exit 1
24 }
25
26 usage() {
27         echo "Usage: release.sh <PRODUCT> <COMMAND>"
28         echo ""
29         echo "PRODUCT: ldb, talloc, tevent, tdb, samba-rc, samba-stable"
30         echo "COMMAND: fullrelease, create, push, upload, announce"
31         echo ""
32         return 0
33 }
34
35 check_args() {
36         local cmd="$1"
37         local got_args="$2"
38         local take_args="$3"
39
40         test x"${got_args}" = x"${take_args}" || {
41                 usage
42                 echo "cmd[${cmd}] takes ${take_args} instead of ${got_args}"
43                 return 1
44         }
45
46         return 0
47 }
48
49 min_args() {
50         local cmd="$1"
51         local got_args="$2"
52         local min_args="$3"
53
54         test "${got_args}" -ge "${min_args}" || {
55                 usage
56                 echo "cmd[${cmd}] takes at least ${min_args} instead of ${got_args}"
57                 return 1
58         }
59
60         return 0
61 }
62
63 min_args "$0" "$#" "2"
64
65 product="$1"
66 globalcmd="$2"
67 shift 2
68 oldtagname=""
69 tagname=""
70 patchfile=""
71 cmds=""
72 next_cmd=""
73
74 require_tagname() {
75         min_args "${FUNCNAME}" "$#" "1" || return 1
76         local cmd="$1"
77
78         test -n "${tagname}" || {
79                 echo "cmd[${cmd}] requires '\${tagname}' variable to be set"
80                 return 1
81         }
82
83         local name=$(echo "${tagname}" | cut -d '-' -f1)
84         test x"${name}" = x"${productbase}" || {
85                 echo "Invalid tagname[${tgzname}]"
86                 return 1
87         }
88
89         return 0
90 }
91
92 cmd_allowed() {
93         min_args "${FUNCNAME}" "$#" "2" || return 1
94         local cmd="$1"
95         shift 1
96
97         echo "$@" | grep -q "\<${cmd}\>" || {
98                 return 1
99         }
100
101         return 0
102 }
103
104 verify_samba_rc() {
105         check_args "${FUNCNAME}" "$#" "0" || return 1
106
107         test -f VERSION || {
108                 echo "VERSION doesn't exist"
109                 return 1
110         }
111
112         grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
113                 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
114                 return 1
115         }
116
117         grep -q '^SAMBA_VERSION_RC_RELEASE=' VERSION || {
118                 echo "SAMBA_VERSION_RC_RELEASE= missing"
119                 return 1
120         }
121
122         grep -q '^SAMBA_VERSION_RC_RELEASE=$' VERSION && {
123                 echo "SAMBA_VERSION_RC_RELEASE= missing the rc version"
124                 return 1
125         }
126
127         return 0
128 }
129
130 verify_samba_stable() {
131         check_args "${FUNCNAME}" "$#" "0" || return 1
132
133         test -f VERSION || {
134                 echo "VERSION doesn't exist"
135                 return 1
136         }
137
138         grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
139                 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
140                 return 1
141         }
142
143         local VARS=""
144         VARS="${VARS} SAMBA_VERSION_REVISION"
145         VARS="${VARS} SAMBA_VERSION_TP_RELEASE"
146         VARS="${VARS} SAMBA_VERSION_ALPHA_RELEASE"
147         VARS="${VARS} SAMBA_VERSION_BETA_RELEASE"
148         VARS="${VARS} SAMBA_VERSION_PRE_RELEASE"
149         VARS="${VARS} SAMBA_VERSION_RC_RELEASE"
150         VARS="${VARS} SAMBA_VERSION_RELEASE_NICKNAME"
151         VARS="${VARS} SAMBA_VERSION_VENDOR_SUFFIX"
152         VARS="${VARS} SAMBA_VERSION_VENDOR_PATCH"
153         for var in ${VARS}; do
154                 grep -q "^${var}" VERSION && {
155                         grep -q "^${var}=$" VERSION || {
156                                 echo "${var} found in stable version"
157                                 return 1
158                         }
159                 }
160         done
161
162         local SAMBA_VERSION_MAJOR=$(grep '^SAMBA_VERSION_MAJOR=' VERSION | cut -d '=' -f2 | xargs)
163         local SAMBA_VERSION_MINOR=$(grep '^SAMBA_VERSION_MINOR=' VERSION | cut -d '=' -f2 | xargs)
164         local SAMBA_VERSION_RELEASE=$(grep '^SAMBA_VERSION_RELEASE=' VERSION | cut -d '=' -f2 | xargs)
165
166         test ${SAMBA_VERSION_RELEASE} -gt 0 || {
167                 return 0
168         }
169
170         local old_release=$(expr ${SAMBA_VERSION_RELEASE} - 1)
171         oldtagname="${productbase}-${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.${old_release}"
172
173         local verify_out="${TMPDIR}/verify-${oldtagname}.out"
174
175         echo "Verifying oldtagname: ${oldtagname}"
176
177         git tag -v "${oldtagname}" >${verify_out} 2>&1 || {
178                 echo "failed to verify old tag[${oldtagname}]"
179                 return 1
180         }
181
182         grep -q "${GPG_KEYID}" "${verify_out}" || {
183                 echo "oldtagname[${oldtagname}] was not generated with GPG_KEYID[${GPG_KEYID}]!"
184                 echo ""
185                 cat "${verify_out}"
186                 return 1
187         }
188
189         echo "Verifying ${oldtagname}.tar.gz and ${oldtagname}.tar.asc"
190
191         test -f "${oldtagname}.tar.gz" || {
192                 echo "${oldtagname}.tar.gz does not exist"
193                 return 1
194         }
195
196         test -f "${oldtagname}.tar.asc" || {
197                 echo "${oldtagname}.tar.asc does not exist"
198                 return 1
199         }
200
201         zcat "${oldtagname}.tar.gz" | gpg --verify "${oldtagname}.tar.asc" - 2>${verify_out} || {
202                 echo "Failed to verify ${oldtagname}.tar.asc"
203                 return 1
204         }
205
206         grep -q "${GPG_KEYID}" "${verify_out}" || {
207                 echo "${oldtagname}.tar.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
208                 echo ""
209                 cat "${verify_out}"
210                 return 1
211         }
212
213         return 0
214 }
215
216 verify_release() {
217         check_args "${FUNCNAME}" "$#" "0" || return 1
218
219         test -n "${verify_fn}" || {
220                 echo "verify_fn variable empty"
221                 return 1
222         }
223
224         echo "Running ${verify_fn}"
225         ${verify_fn}
226 }
227
228 create_release() {
229         check_args "${FUNCNAME}" "$#" "0" || return 1
230
231         echo "Releasing product ${product}"
232
233         echo "Building release tarball"
234         local tgzname=$(make dist 2>&1 | grep ^Created | cut -d' ' -f2)
235         test -f "${tgzname}" || {
236                 echo "Failed to create tarball"
237                 return 1
238         }
239         CLEANUP_FILES="${CLEANUP_FILES} ${tgzname}"
240
241         local name=$(echo "${tgzname}" | cut -d '-' -f1)
242         test x"${name}" = x"${productbase}" || {
243                 echo "Invalid tgzname[${tgzname}]"
244                 return 1
245         }
246
247         local tarname=$(basename ${tgzname} .gz)
248         echo "Tarball: ${tarname}"
249         gunzip -f ${tgzname} || {
250                 echo "Failed to decompress tarball ${tarname}"
251                 return 1
252         }
253         test -f "${tarname}" || {
254                 echo "Failed to decompress tarball ${tarname}"
255                 return 1
256         }
257         CLEANUP_FILES="${CLEANUP_FILES} ${tarname}"
258
259         # tagname is global
260         tagname=$(basename ${tarname} .tar)
261         echo "Tagging as ${tagname}"
262         git tag -u ${GPG_KEYID} -s "${tagname}" -m "${productbase}: tag release ${tagname}" || {
263                 return 1
264         }
265         CLEANUP_TAGS="${CLEANUP_TAGS} ${tagname}"
266
267         echo "Signing ${tarname} => ${tarname}.asc"
268         rm -f "${tarname}.asc"
269         gpg -u "${GPG_USER}" --detach-sign --armor ${tarname} || {
270                 return 1
271         }
272         test -f "${tarname}.asc" || {
273                 echo "Failed to create signature ${tarname}.asc"
274                 return 1
275         }
276         CLEANUP_FILES="${CLEANUP_FILES} ${tarname}.asc"
277         echo "Compressing ${tarname} => ${tgzname}"
278         gzip -f -9 ${tarname}
279         test -f "${tgzname}" || {
280                 echo "Failed to compress ${tgzname}"
281                 return 1
282         }
283
284         return 0
285 }
286
287 patch_release() {
288         check_args "${FUNCNAME}" "$#" "0" || return 1
289         require_tagname "${FUNCNAME}"
290
291         test -n "${oldtagname}" || {
292                 return 0
293         }
294
295         local oldversion=$(echo "${oldtagname}" | sed -e "s!^${productbase}-!!")
296         local version=$(echo "${tagname}" | sed -e "s!^${productbase}-!!")
297
298         local oldpwd=$(pwd)
299
300         local patchfile="patch-${oldversion}-${version}.diffs"
301         echo "Generating ${patchfile}"
302         (
303                 pushd "${TMPDIR}"
304                 tar xfz "${oldpwd}/${oldtagname}.tar.gz"
305                 tar xfz "${oldpwd}/${tagname}.tar.gz"
306                 diff -Npur "${oldtagname}/" "${tagname}/" > "${patchfile}"
307                 popd
308         )
309         CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}"
310         mv "${TMPDIR}/${patchfile}" "${patchfile}" || {
311                 echo "failed cmd[mv ${TMPDIR}/${patchfile} ${patchfile}]"
312                 return 1
313         }
314
315         echo "Signing ${patchfile} => ${patchfile}.asc"
316         rm -f "${patchfile}.asc"
317         CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.asc"
318         gpg -u "${GPG_USER}" --detach-sign --armor ${patchfile} || {
319                 return 1
320         }
321         test -f "${patchfile}.asc" || {
322                 echo "Failed to create signature ${patchfile}.asc"
323                 return 1
324         }
325         echo "Compressing ${patchfile} => ${patchfile}.gz"
326         CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.gz"
327         gzip -f -9 ${patchfile}
328         test -f "${patchfile}.gz" || {
329                 echo "Failed to compress ${patchfile}.gz"
330                 return 1
331         }
332
333         return 0
334 }
335
336 whatsnew_release() {
337         check_args "${FUNCNAME}" "$#" "0" || return 1
338         require_tagname "${FUNCNAME}"
339
340         echo "extract ${tagname}.WHATSNEW.txt"
341         tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt > ${tagname}.WHATSNEW.txt
342         CLEANUP_FILES="${CLEANUP_FILES} ${tagname}.WHATSNEW.txt"
343
344         return 0
345 }
346
347 check_nopatch() {
348         check_args "${FUNCNAME}" "$#" "0" || return 1
349         require_tagname "${FUNCNAME}"
350
351         git tag -v "${tagname}" || {
352                 echo "failed to verify tag[${tagname}]"
353                 return 1
354         }
355
356         test -f "${tagname}.tar.gz" || {
357                 echo "${tagname}.tar.gz does not exist"
358                 return 1
359         }
360
361         test -f "${tagname}.tar.asc" || {
362                 echo "${tagname}.tar.asc does not exist"
363                 return 1
364         }
365
366         ls -la ${tagname}.*
367
368         return 0
369 }
370
371 check_withpatch() {
372         check_args "${FUNCNAME}" "$#" "0" || return 1
373         require_tagname "${FUNCNAME}"
374
375         git tag -v "${tagname}" || {
376                 echo "failed to verify tag[${tagname}]"
377                 return 1
378         }
379
380         test -f "${tagname}.tar.gz" || {
381                 echo "${tagname}.tar.gz does not exist"
382                 return 1
383         }
384
385         test -f "${tagname}.tar.asc" || {
386                 echo "${tagname}.tar.asc does not exist"
387                 return 1
388         }
389
390         ls -la ${tagname}.*
391
392         test -n "${patchfile}" || {
393                 return 0
394         }
395
396         test -f "${patchfile}.gz" || {
397                 echo "${patchfile}.gz does not exist"
398                 return 1
399         }
400
401         test -f "${patchfile}.asc" || {
402                 echo "${patchfile}.asc does not exist"
403                 return 1
404         }
405
406         return 0
407 }
408
409 check_release() {
410         check_args "${FUNCNAME}" "$#" "0" || return 1
411
412         test -n "${check_fn}" || {
413                 echo "check_fn variable empty"
414                 return 1
415         }
416
417         echo "Running ${check_fn}"
418         ${check_fn}
419 }
420
421 push_release() {
422         check_args "${FUNCNAME}" "$#" "0" || return 1
423         require_tagname "${FUNCNAME}"
424
425         echo "Push git tag ${tagname} to '${repo_url}'"
426         git push "${repo_url}" "refs/tags/${tagname}:refs/tags/${tagname}" || {
427                 return 1
428         }
429
430         return 0
431 }
432
433 upload_release() {
434         check_args "${FUNCNAME}" "$#" "0" || return 1
435         require_tagname "${FUNCNAME}"
436
437         echo "Upload ${tagname}.* to '${upload_url}'"
438         rsync -Pav ${tagname}.* "${upload_url}/" || {
439                 return 1
440         }
441         rsync ${upload_url}/${tagname}.*
442
443         return 0
444 }
445
446 announce_samba_rc() {
447         check_args "${FUNCNAME}" "$#" "0" || return 1
448         require_tagname "${FUNCNAME}"
449
450         test -f "${tagname}.WHATSNEW.txt" || {
451                 echo "${tagname}.WHATSNEW.txt does not exist"
452                 return 1
453         }
454
455         local t=""
456         local utcdate=$(date --utc +"%d %B %Y")
457         local utctime=$(date --utc +"%Y%m%d-%H%M%S")
458         local version=$(echo "${tagname}" | sed -e 's!^samba-!!')
459         local href="#${version}"
460         local series=$(echo "${version}" | cut -d '.' -f1-2)
461         local rc=$(echo "${version}" | sed -e 's!.*rc\([0-9][0-9]*\)!\1!')
462         local rcname="${rc}th"
463         case "${rc}" in
464         1)
465                 rcname="first"
466                 ;;
467         2)
468                 rcname="second"
469                 ;;
470         3)
471                 rcname="third"
472                 ;;
473         4)
474                 rcname="fourth"
475                 ;;
476         5)
477                 rcname="fifth"
478                 ;;
479         esac
480
481         {
482                 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
483         } > announce.${tagname}.to.txt
484         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
485
486         {
487                 echo "[Announce] Samba ${version} Available for Download"
488         } > announce.${tagname}.subject.txt
489         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
490
491         {
492                 cat ${tagname}.WHATSNEW.txt
493                 echo ""
494                 echo "================"
495                 echo "Download Details"
496                 echo "================"
497                 echo ""
498                 echo "The uncompressed tarballs and patch files have been signed"
499                 echo "using GnuPG (ID 6568B7EA).  The source code can be downloaded"
500                 echo "from:"
501                 echo ""
502                 echo "        ${download_url}"
503                 echo ""
504                 echo "The release notes are available online at:"
505                 echo ""
506                 echo "        ${download_url}${tagname}.WHATSNEW.txt"
507                 echo ""
508                 echo "Our Code, Our Bugs, Our Responsibility."
509                 echo "(https://bugzilla.samba.org/)"
510                 echo ""
511                 echo "                        --Enjoy"
512                 echo "                        The Samba Team"
513         } > announce.${tagname}.mail.txt
514         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
515
516         {
517                 echo -n "-i announce.${tagname}.mail.txt "
518                 echo -n "-s \"$(cat announce.${tagname}.subject.txt | xargs)\" "
519                 echo -n "$(cat announce.${tagname}.to.txt | xargs)"
520         } > announce.${tagname}.mutt-arguments.txt
521         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
522
523         local headlinefile="${utctime}.${version}.headline.html"
524         {
525                 echo "<!-- BEGIN: posted_news/${headlinefile} -->"
526                 echo "<li> ${utcdate} <a href=\"${href}\">Samba ${version} Available for Download</a></li>"
527                 echo "<!-- END: posted_news/${headlinefile} -->"
528         } > ${headlinefile}
529         CLEANUP_FILES="${CLEANUP_FILES} ${headlinefile}"
530
531         local bodyfile="${utctime}.${version}.body.html"
532         {
533                 echo "<!-- BEGIN: posted_news/${bodyfile} -->"
534                 echo "<h5><a name=\"${version}\">${utcdate}</a></h5>"
535                 echo "<p class="headline">Samba ${version} Available for Download</p>"
536                 echo "<p>"
537                 echo "This is the ${rcname} release candidate of the upcoming Samba ${series} release series."
538                 echo "</p>"
539                 echo "<p>"
540                 echo "The uncompressed tarball has been signed using GnuPG (ID ${GPG_KEYID})."
541                 echo "The source code can be <a href=\"${download_url}${tagname}.tar.gz\">downloaded now</a>."
542                 echo "See <a href=\"${download_url}${tagname}.WHATSNEW.txt\">the release notes for more info</a>."
543                 echo "</p>"
544                 echo "<!-- END: posted_news/${bodyfile} -->"
545                 echo ""
546         } > ${bodyfile}
547         CLEANUP_FILES="${CLEANUP_FILES} ${bodyfile}"
548
549         {
550                 ls -lart announce.${tagname}.* ${headlinefile} ${bodyfile}
551                 echo ""
552                 echo "NOTICE:"
553                 echo "You need to do the following manual steps in order"
554                 echo "to finish the announcement of ${tagname}!"
555                 echo ""
556                 echo "Copy the following files into the posted_news/"
557                 echo "subdirectory of the samba-web.git repository and commit them:"
558                 echo "  ${headlinefile}"
559                 echo "  ${bodyfile}"
560                 echo ""
561                 echo "  cp -a ${utctime}.${version}.*.html /path/to/samba-web/posted_news/"
562                 echo "  pushd /path/to/samba-web"
563                 echo "  git add posted_news/${utctime}.${version}.*.html"
564                 echo "  git commit --signoff --message \"NEWS[${version}]: Samba ${version} Available for Download\""
565                 echo "  git show -p --stat HEAD"
566                 echo "  git push ..."
567                 echo "  popd"
568                 echo ""
569                 echo "Once the resulting commit is pushed a cron job will update "
570                 echo "the content exported by the webserver every 5mins."
571                 echo ""
572                 echo "If the web content is updated, you need to send the announce mail (gpg signed)."
573                 echo "- announce.${tagname}.to.txt contains the mail's recipients for the To: header."
574                 echo "- announce.${tagname}.subject.txt contains the mail's subject line."
575                 echo "- announce.${tagname}.mail.txt contains the content of the mail body."
576                 echo "In case your're using mutt, you can use the following shortcut:"
577                 echo "  eval mutt \$(cat announce.${tagname}.mutt-arguments.txt)"
578                 echo ""
579                 echo "NOTICE: you're not done yet! Read the above instructions carefully!"
580                 echo "See: announce.${tagname}.todo.txt"
581                 echo ""
582         } > announce.${tagname}.todo.txt
583         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
584
585         cat announce.${tagname}.todo.txt
586
587         return 0
588 }
589
590 announce_samba_stable() {
591         check_args "${FUNCNAME}" "$#" "0" || return 1
592         require_tagname "${FUNCNAME}"
593
594         test -f "${tagname}.tar.gz" || {
595                 echo "${tagname}.tar.gz does not exist"
596                 return 1
597         }
598
599         echo "extract WHATSNEW.txt"
600         tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt > ${TMPDIR}/WHATSNEW.txt
601
602         # TODO: up to '^Release notes for older releases follow:'
603         cp -a ${TMPDIR}/WHATSNEW.txt ${TMPDIR}/WHATSNEW.top
604
605         local t=""
606         local utcdate=$(date --utc +"%d %B %Y")
607         local utctime=$(date --utc +"%Y%m%d-%H%M%S")
608         local version=$(echo "${tagname}" | sed -e 's!^samba-!!')
609         local href="#${version}"
610         local series=$(echo "${version}" | cut -d '.' -f1-2)
611         local release=$(echo "${version}" | cut -d '.' -f3)
612         local releasename="latest"
613         case "${release}" in
614         1)
615                 releasename="first"
616                 ;;
617         *)
618                 releasename="latest"
619                 ;;
620         esac
621
622         {
623                 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
624         } > announce.${tagname}.to.txt
625         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
626
627         {
628                 echo "[Announce] Samba ${version} Available for Download"
629         } > announce.${tagname}.subject.txt
630         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
631
632         {
633                 cat ${TMPDIR}/WHATSNEW.top
634                 echo ""
635                 echo "================"
636                 echo "Download Details"
637                 echo "================"
638                 echo ""
639                 echo "The uncompressed tarballs and patch files have been signed"
640                 echo "using GnuPG (ID 6568B7EA).  The source code can be downloaded"
641                 echo "from:"
642                 echo ""
643                 echo "        ${download_url}"
644                 echo ""
645                 echo "The release notes are available online at:"
646                 echo ""
647                 echo "        ${history_url}${tagname}.html"
648                 echo ""
649                 echo "Our Code, Our Bugs, Our Responsibility."
650                 echo "(https://bugzilla.samba.org/)"
651                 echo ""
652                 echo "                        --Enjoy"
653                 echo "                        The Samba Team"
654         } > announce.${tagname}.mail.txt
655         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
656
657         {
658                 echo -n "-i announce.${tagname}.mail.txt "
659                 echo -n "-s \"$(cat announce.${tagname}.subject.txt | xargs)\" "
660                 echo -n "$(cat announce.${tagname}.to.txt | xargs)"
661         } > announce.${tagname}.mutt-arguments.txt
662         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
663
664         {
665                 local tmp=$(cat ${TMPDIR}/WHATSNEW.top | grep -n '^Reporting bugs & Development Discussion' | head -1 | cut -d ':' -f1)
666                 local lines=$(expr ${tmp} - 2)
667
668                 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
669                 echo ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
670                 echo '<html xmlns="http://www.w3.org/1999/xhtml">'
671
672                 echo "<head>"
673                 echo "<title>Samba ${version} - Release Notes</title>"
674                 echo "</head>"
675
676                 echo "<body>"
677                 echo "<H2>Samba ${version} Available for Download</H2>"
678
679                 echo "<p>"
680                 echo "<a href=\"${download_url}${tagname}.tar.gz\">Samba ${version} (gzipped)</a><br>"
681                 echo "<a href=\"${download_url}${tagname}.tar.asc\">Signature</a>"
682                 echo "</p>"
683
684                 echo "<p>"
685                 echo "<pre>"
686                 head -${lines} ${TMPDIR}/WHATSNEW.top | sed \
687                         -e 's!&!\&amp;!g' | sed \
688                         -e 's!<!\&lt;!g' \
689                         -e 's!>!\&gt;!g' \
690                         -e 's!ä!\&auml;!g' \
691                         -e 's!Ä!\&Auml;!g' \
692                         -e 's!ö!\&ouml;!g' \
693                         -e 's!Ö!\&Ouml;!g' \
694                         -e 's!ü!\&uuml;!g' \
695                         -e 's!Ü!\&Uuml;!g' \
696                         -e 's!ß!\&szlig;!g' \
697                         -e 's!"!\&quot;!g' \
698                         -e "s!'!\&apos;!g" \
699                         | cat
700                 echo "</pre>"
701                 echo "</p>"
702
703                 echo "</body>"
704                 echo "</html>"
705         } > announce.${tagname}.html
706         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.html"
707
708         local headlinefile="${utctime}.${version}.headline.html"
709         {
710                 echo "<!-- BEGIN: posted_news/${headlinefile} -->"
711                 echo "<li> ${utcdate} <a href=\"${href}\">Samba ${version} Available for Download</a></li>"
712                 echo "<!-- END: posted_news/${headlinefile} -->"
713         } > ${headlinefile}
714         CLEANUP_FILES="${CLEANUP_FILES} ${headlinefile}"
715
716         local bodyfile="${utctime}.${version}.body.html"
717         {
718                 echo "<!-- BEGIN: posted_news/${bodyfile} -->"
719                 echo "<h5><a name=\"${version}\">${utcdate}</a></h5>"
720                 echo "<p class="headline">Samba ${version} Available for Download</p>"
721                 echo "<p>"
722                 echo "This is the ${releasename} stable release of the Samba ${series} release series."
723                 echo "</p>"
724                 echo "<p>"
725                 echo "The uncompressed tarball has been signed using GnuPG (ID ${GPG_KEYID})."
726                 echo "The source code can be <a href=\"${download_url}${tagname}.tar.gz\">downloaded now</a>."
727                 #test -n "${patchfile}" && {
728                 #       echo "A <a href=\"...\"> patch against Samba ${oldversion}</a> is also available."
729                 #}
730                 echo "See <a href=\"${history_url}${tagname}.html\">the release notes for more info</a>."
731                 echo "</p>"
732                 echo "<!-- END: posted_news/${bodyfile} -->"
733                 echo ""
734         } > ${bodyfile}
735         CLEANUP_FILES="${CLEANUP_FILES} ${bodyfile}"
736
737         {
738                 ls -lart announce.${tagname}.* ${headlinefile} ${bodyfile}
739                 echo ""
740                 echo "NOTICE:"
741                 echo "You need to do the following manual steps in order"
742                 echo "to finish the announcement of ${tagname}!"
743                 echo ""
744                 echo "Copy the following files into the posted_news/"
745                 echo "subdirectory of the samba-web.git repository and commit them:"
746                 echo "  ${headlinefile}"
747                 echo "  ${bodyfile}"
748                 echo ""
749                 echo "  cp -a ${utctime}.${version}.*.html /path/to/samba-web/posted_news/"
750                 echo "  cp -a announce.${tagname}.html /path/to/samba-web/history/${tagname}.html"
751                 echo "  pushd /path/to/samba-web"
752                 echo "  git add posted_news/${utctime}.${version}.*.html"
753                 echo "  git add history/${tagname}.html"
754                 echo "  git commit --signoff --message \"NEWS[${version}]: Samba ${version} Available for Download\""
755                 echo "  git show -p --stat HEAD"
756                 echo "  git push ..."
757                 echo "  popd"
758                 echo ""
759                 echo "Once the resulting commit is pushed a cron job will update "
760                 echo "the content exported by the webserver every 5mins."
761                 echo ""
762                 echo "If the web content is updated, you need to send the announce mail (gpg signed)."
763                 echo "- announce.${tagname}.to.txt contains the mail's recipients for the To: header."
764                 echo "- announce.${tagname}.subject.txt contains the mail's subject line."
765                 echo "- announce.${tagname}.mail.txt contains the content of the mail body."
766                 echo "In case your're using mutt, you can use the following shortcut:"
767                 echo "  eval mutt \$(cat announce.${tagname}.mutt-arguments.txt)"
768                 echo ""
769                 echo "NOTICE: you're not done yet! Read the above instructions carefully!"
770                 echo "See: announce.${tagname}.todo.txt"
771                 echo ""
772         } > announce.${tagname}.todo.txt
773         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
774
775         cat announce.${tagname}.todo.txt
776
777         return 0
778 }
779
780 announce_release() {
781         check_args "${FUNCNAME}" "$#" "0" || return 1
782
783         test -n "${announce_fn}" || {
784                 echo "announce_fn variable empty"
785                 return 1
786         }
787
788         echo "Running ${announce_fn}"
789         ${announce_fn}
790 }
791
792 case "${product}" in
793 talloc | tdb | tevent | ldb)
794         test -z "${GPG_USER-}" && {
795                 GPG_USER='Samba Library Distribution Key <samba-bugs@samba.org>'
796         }
797
798         test -z "${GPG_KEYID-}"  && {
799                 GPG_KEYID='13084025'
800         }
801
802         productbase="${product}"
803         srcdir="lib/${product}"
804         repo_url="${CONF_REPO_URL}"
805         upload_url="${CONF_UPLOAD_URL}/${product}/"
806         download_url="${CONF_DOWNLOAD_URL}/${product}/"
807
808         check_fn="check_nopatch"
809         fullcmds="create check push upload"
810         ;;
811 samba-rc)
812         test -z "${GPG_USER-}" && {
813                 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
814         }
815
816         test -z "${GPG_KEYID-}"  && {
817                 GPG_KEYID='6568B7EA'
818         }
819
820         productbase="samba"
821         srcdir="."
822         repo_url="${CONF_REPO_URL}"
823         upload_url="${CONF_UPLOAD_URL}/samba/rc/"
824         download_url="${CONF_DOWNLOAD_URL}/samba/rc/"
825
826         verify_fn="verify_samba_rc"
827         check_fn="check_nopatch"
828         announce_fn="announce_samba_rc"
829         fullcmds="verify create check whatsnew push upload announce"
830         ;;
831 samba-stable)
832         test -z "${GPG_USER-}" && {
833                 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
834         }
835
836         test -z "${GPG_KEYID-}"  && {
837                 GPG_KEYID='6568B7EA'
838         }
839
840         productbase="samba"
841         srcdir="."
842         repo_url="${CONF_REPO_URL}"
843         upload_url="${CONF_UPLOAD_URL}/samba/stable/"
844         download_url="${CONF_DOWNLOAD_URL}/samba/stable/"
845         history_url="${CONF_HISTORY_URL}/samba/history/"
846
847         verify_fn="verify_samba_stable"
848         check_fn="check_withpatch"
849         announce_fn="announce_samba_stable"
850         fullcmds="verify create patch check push upload announce"
851         ;;
852 TODO-samba-security)
853         test -z "${GPG_USER-}" && {
854                 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
855         }
856
857         test -z "${GPG_KEYID-}"  && {
858                 GPG_KEYID='6568B7EA'
859         }
860
861         productbase="samba"
862         srcdir="."
863         repo_url="${CONF_REPO_URL}"
864         upload_url="${CONF_UPLOAD_URL}/samba/stable/"
865         download_url="${CONF_DOWNLOAD_URL}/samba/stable/"
866
867         verify_fn="verify_samba_stable"
868         check_fn="check_withpatch"
869         announce_fn="announce_samba_security"
870         fullcmds="verify create patch check"
871         next_cmd="push"
872         ;;
873 *)
874         usage
875         echo "Unknown product ${product}"
876         exit 1
877 esac
878
879 pushd ${srcdir} || {
880         echo "srcdir[${srcdir}] does not exist"
881         exit 1
882 }
883
884 trap_handler() {
885         echo ""
886         echo "ERROR: cleaning up"
887         echo ""
888
889         for t in ${CLEANUP_TAGS}; do
890                 echo "Removing tag[${t}]"
891                 git tag -v "${t}" && {
892                         git tag -d "${t}" || {
893                                 echo "failed to remove tag ${t}"
894                         }
895                 }
896         done
897
898         for f in ${CLEANUP_FILES}; do
899                 echo "Removing file[${f}]"
900                 test -f "${f}" && {
901                         rm "${f}" || {
902                                 echo "failed to remove ${f}"
903                         }
904                 }
905         done
906
907         for d in ${CLEANUP_DIRS}; do
908                 echo "Removing dir[${d}]"
909                 test -d "${d}" && {
910                         rm -rf "${d}" || {
911                                 echo "failed to remove ${d}"
912                         }
913                 }
914         done
915 }
916
917 CLEANUP_TAGS=""
918 CLEANUP_FILES=""
919 CLEANUP_DIRS=""
920 trap trap_handler INT QUIT TERM EXIT
921
922 cmd_allowed "${globalcmd}" fullrelease ${fullcmds} || {
923         usage
924         echo "command[${globalcmd}] not supported for product[${product}]"
925         exit 1
926 }
927
928 case "${globalcmd}" in
929 fullrelease)
930         check_args "${globalcmd}" "$#" "0" || exit 1
931         cmds="${fullcmds}"
932         ;;
933 create)
934         check_args "${globalcmd}" "$#" "0" || exit 1
935         check_args "create" "$#" "0" || exit 1
936
937         cmds=""
938         cmd_allowed "verify" ${fullcmds} && {
939                 cmds="${cmds} verify"
940         }
941         cmds="${cmds} create"
942         cmd_allowed "whatsnew" ${fullcmds} && {
943                 cmds="${cmds} whatsnew"
944         }
945         cmd_allowed "patch" ${fullcmds} && {
946                 cmds="${cmds} patch"
947         }
948         cmds="${cmds} check"
949         next_cmd="push"
950         ;;
951 push)
952         check_args "${globalcmd}" "$#" "1" || exit 1
953         tagname="$1"
954         cmds="check push"
955         next_cmd="upload"
956         ;;
957 upload)
958         check_args "${globalcmd}" "$#" "1" || exit 1
959         tagname="$1"
960         cmds="check upload"
961         cmd_allowed "symlinks" ${fullcmds} && {
962                 cmds="${cmds} symlinks"
963         }
964         cmd_allowed "announce" ${fullcmds} && {
965                 next_cmd="announce"
966         }
967         ;;
968 announce)
969         check_args "${globalcmd}" "$#" "1" || exit 1
970         tagname="$1"
971         cmds="check announce"
972         ;;
973 *)
974         usage
975         echo "Unknown command ${globalcmd}"
976         exit 1
977         ;;
978 esac
979
980 TMPDIR="release.$$"
981 CLEANUP_DIRS="${CLEANUP_DIRS} ${TMPDIR}"
982 umask 0077
983 mkdir "${TMPDIR}"
984 umask 0022
985
986 for cmd in ${cmds}; do
987         echo "Starting subcommand[${cmd}]"
988         ${cmd}_release || {
989                 echo "Failed subcommand[${cmd}]"
990                 exit 1
991         }
992         echo "Finished subcommand[${cmd}]"
993 done
994
995 test -d "${TMPDIR}" && {
996         rm -rf "${TMPDIR}" || {
997                 echo "failed to remove ${TMPDIR}"
998         }
999 }
1000
1001 test -n "${next_cmd}" && {
1002         echo "Continue with '$0 ${product} ${next_cmd} ${tagname}'."
1003 }
1004
1005 trap - INT QUIT TERM EXIT
1006
1007 exit 0