PY3: change shebang to python3 in script dir
[garming/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 load_samba_stable_versions() {
131         check_args "${FUNCNAME}" "$#" "0" || return 1
132
133         test -n "${version-}" && {
134                 return 0
135         }
136
137         local SAMBA_VERSION_MAJOR=$(grep '^SAMBA_VERSION_MAJOR=' VERSION | cut -d '=' -f2 | xargs)
138         local SAMBA_VERSION_MINOR=$(grep '^SAMBA_VERSION_MINOR=' VERSION | cut -d '=' -f2 | xargs)
139         local SAMBA_VERSION_RELEASE=$(grep '^SAMBA_VERSION_RELEASE=' VERSION | cut -d '=' -f2 | xargs)
140
141         version="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.${SAMBA_VERSION_RELEASE}"
142         tagname="${productbase}-${version}"
143
144         test ${SAMBA_VERSION_RELEASE} -gt 0 || {
145                 return 0
146         }
147
148         oldversion="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.$(expr ${SAMBA_VERSION_RELEASE} - 1)"
149         oldtagname="${productbase}-${oldversion}"
150         patchfile="${productbase}-${oldversion}-${version}.diffs"
151
152         return 0
153 }
154
155 verify_samba_stable() {
156         check_args "${FUNCNAME}" "$#" "0" || return 1
157
158         test -f VERSION || {
159                 echo "VERSION doesn't exist"
160                 return 1
161         }
162
163         grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
164                 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
165                 return 1
166         }
167
168         local VARS=""
169         VARS="${VARS} SAMBA_VERSION_REVISION"
170         VARS="${VARS} SAMBA_VERSION_TP_RELEASE"
171         VARS="${VARS} SAMBA_VERSION_ALPHA_RELEASE"
172         VARS="${VARS} SAMBA_VERSION_BETA_RELEASE"
173         VARS="${VARS} SAMBA_VERSION_PRE_RELEASE"
174         VARS="${VARS} SAMBA_VERSION_RC_RELEASE"
175         VARS="${VARS} SAMBA_VERSION_RELEASE_NICKNAME"
176         VARS="${VARS} SAMBA_VERSION_VENDOR_SUFFIX"
177         VARS="${VARS} SAMBA_VERSION_VENDOR_PATCH"
178         for var in ${VARS}; do
179                 grep -q "^${var}" VERSION && {
180                         grep -q "^${var}=$" VERSION || {
181                                 echo "${var} found in stable version"
182                                 return 1
183                         }
184                 }
185         done
186
187         load_samba_stable_versions
188
189         test x"${product}" = x"samba-stable" && {
190                 test -f "announce.${tagname}.quotation.txt" || {
191                         echo ""
192                         echo "announce.${tagname}.quotation.txt missing!"
193                         echo ""
194                         echo "Please create it and retry"
195                         echo ""
196                         echo "The content should look like this:"
197                         echo "cat announce.${tagname}.quotation.txt"
198                         echo '======================================================'
199                         echo '                "Some text'
200                         echo '                 from someone."'
201                         echo ''
202                         echo '                 The author'
203                         echo '======================================================'
204                         echo ""
205                         return 1
206                 }
207         }
208
209         test -n "${oldtagname}" || {
210                 return 0
211         }
212
213         local verify_out="${TMPDIR}/verify-${oldtagname}.out"
214
215         echo "Verifying oldtagname: ${oldtagname}"
216
217         git tag -v "${oldtagname}" >${verify_out} 2>&1 || {
218                 echo "failed to verify old tag[${oldtagname}]"
219                 echo ""
220                 cat "${verify_out}"
221                 return 1
222         }
223
224         grep -q "${GPG_KEYID}" "${verify_out}" || {
225                 echo "oldtagname[${oldtagname}] was not generated with GPG_KEYID[${GPG_KEYID}]!"
226                 echo ""
227                 cat "${verify_out}"
228                 return 1
229         }
230
231         echo "Verifying ${oldtagname}.tar.gz and ${oldtagname}.tar.asc"
232
233         test -f "${oldtagname}.tar.gz" || {
234                 echo "${oldtagname}.tar.gz does not exist"
235                 return 1
236         }
237
238         test -f "${oldtagname}.tar.asc" || {
239                 echo "${oldtagname}.tar.asc does not exist"
240                 return 1
241         }
242
243         zcat "${oldtagname}.tar.gz" | gpg --verify "${oldtagname}.tar.asc" - 2>${verify_out} || {
244                 echo "Failed to verify ${oldtagname}.tar.asc"
245                 return 1
246         }
247
248         grep -q "${GPG_KEYID}" "${verify_out}" || {
249                 echo "${oldtagname}.tar.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
250                 echo ""
251                 cat "${verify_out}"
252                 return 1
253         }
254
255         return 0
256 }
257
258 verify_release() {
259         check_args "${FUNCNAME}" "$#" "0" || return 1
260
261         test -n "${verify_fn}" || {
262                 echo "verify_fn variable empty"
263                 return 1
264         }
265
266         echo "Running ${verify_fn}"
267         ${verify_fn}
268 }
269
270 create_release() {
271         check_args "${FUNCNAME}" "$#" "0" || return 1
272
273         echo "Releasing product ${product}"
274
275         test -n "${tagname}" && {
276                 git tag -l "${tagname}" | grep -q "${tagname}" && {
277                         echo "tagname[${tagname}] already exist"
278                         return 1
279                 }
280
281                 local _tgzname="${tagname}.tar.gz"
282                 test -e "${_tgzname}" && {
283                         echo "_tgzname[${_tgzname}] already exist"
284                         return 1
285                 }
286         }
287
288         echo "Building release tarball"
289         local tgzname=$(make dist 2>&1 | grep ^Created | cut -d' ' -f2)
290         test -f "${tgzname}" || {
291                 echo "Failed to create tarball"
292                 return 1
293         }
294         CLEANUP_FILES="${CLEANUP_FILES} ${tgzname}"
295
296         local name=$(echo "${tgzname}" | cut -d '-' -f1)
297         test x"${name}" = x"${productbase}" || {
298                 echo "Invalid tgzname[${tgzname}]"
299                 return 1
300         }
301
302         local _tagname=$(basename ${tgzname} .tar.gz)
303         test -n "${tagname}" && {
304                 test x"${_tagname}" = x"${tagname}" || {
305                         echo "Invalid tgzname[${tgzname}]"
306                         return 1
307                 }
308         }
309         tagname="${_tagname}"
310
311         local tarname=$(basename ${tgzname} .gz)
312         echo "Tarball: ${tarname}"
313         gunzip -f ${tgzname} || {
314                 echo "Failed to decompress tarball ${tarname}"
315                 return 1
316         }
317         test -f "${tarname}" || {
318                 echo "Failed to decompress tarball ${tarname}"
319                 return 1
320         }
321         CLEANUP_FILES="${CLEANUP_FILES} ${tarname}"
322
323         # tagname is global
324         echo "Tagging as ${tagname}"
325         git tag -u ${GPG_KEYID} -s "${tagname}" -m "${productbase}: tag release ${tagname}" || {
326                 return 1
327         }
328         CLEANUP_TAGS="${CLEANUP_TAGS} ${tagname}"
329
330         echo "Signing ${tarname} => ${tarname}.asc"
331         rm -f "${tarname}.asc"
332         gpg -u "${GPG_USER}" --detach-sign --armor ${tarname} || {
333                 return 1
334         }
335         test -f "${tarname}.asc" || {
336                 echo "Failed to create signature ${tarname}.asc"
337                 return 1
338         }
339         CLEANUP_FILES="${CLEANUP_FILES} ${tarname}.asc"
340         echo "Compressing ${tarname} => ${tgzname}"
341         gzip -f -9 ${tarname}
342         test -f "${tgzname}" || {
343                 echo "Failed to compress ${tgzname}"
344                 return 1
345         }
346
347         return 0
348 }
349
350 patch_release() {
351         check_args "${FUNCNAME}" "$#" "0" || return 1
352         require_tagname "${FUNCNAME}"
353
354         test -n "${patchfile}" || {
355                 return 0
356         }
357
358         local oldpwd=$(pwd)
359         echo "Generating ${patchfile}"
360         (
361                 set -e
362                 set -u
363                 pushd "${TMPDIR}"
364                 tar xfz "${oldpwd}/${oldtagname}.tar.gz"
365                 tar xfz "${oldpwd}/${tagname}.tar.gz"
366                 diff -Npur "${oldtagname}/" "${tagname}/" > "${patchfile}"
367                 popd
368         )
369         CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}"
370         mv "${TMPDIR}/${patchfile}" "${patchfile}" || {
371                 echo "failed cmd[mv ${TMPDIR}/${patchfile} ${patchfile}]"
372                 return 1
373         }
374
375         echo "Signing ${patchfile} => ${patchfile}.asc"
376         rm -f "${patchfile}.asc"
377         CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.asc"
378         gpg -u "${GPG_USER}" --detach-sign --armor ${patchfile} || {
379                 return 1
380         }
381         test -f "${patchfile}.asc" || {
382                 echo "Failed to create signature ${patchfile}.asc"
383                 return 1
384         }
385         echo "Compressing ${patchfile} => ${patchfile}.gz"
386         CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.gz"
387         gzip -f -9 ${patchfile}
388         test -f "${patchfile}.gz" || {
389                 echo "Failed to compress ${patchfile}.gz"
390                 return 1
391         }
392
393         return 0
394 }
395
396 whatsnew_release() {
397         check_args "${FUNCNAME}" "$#" "0" || return 1
398         require_tagname "${FUNCNAME}"
399
400         echo "extract ${tagname}.WHATSNEW.txt"
401         tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt > ${tagname}.WHATSNEW.txt
402         CLEANUP_FILES="${CLEANUP_FILES} ${tagname}.WHATSNEW.txt"
403
404         return 0
405 }
406
407 check_nopatch() {
408         check_args "${FUNCNAME}" "$#" "0" || return 1
409         require_tagname "${FUNCNAME}"
410
411         local verify_out="${TMPDIR}/verify-${oldtagname}.out"
412
413         echo "Verifying tagname: ${tagname}"
414
415         git tag -v "${tagname}" >${verify_out} 2>&1 || {
416                 echo "failed to verify tag[${tagname}]"
417                 echo ""
418                 cat "${verify_out}"
419                 return 1
420         }
421         grep -q "${GPG_KEYID}" "${verify_out}" || {
422                 echo "tagname[${tagname}] was not generated with GPG_KEYID[${GPG_KEYID}]!"
423                 echo ""
424                 cat "${verify_out}"
425                 return 1
426         }
427
428         echo "Verifying ${tagname}.tar.gz and ${tagname}.tar.asc"
429
430         test -f "${tagname}.tar.gz" || {
431                 echo "${tagname}.tar.gz does not exist"
432                 return 1
433         }
434
435         test -f "${tagname}.tar.asc" || {
436                 echo "${tagname}.tar.asc does not exist"
437                 return 1
438         }
439
440         zcat "${tagname}.tar.gz" | gpg --verify "${tagname}.tar.asc" - 2>${verify_out} || {
441                 echo "Failed to verify ${tagname}.tar.asc"
442                 return 1
443         }
444         grep -q "${GPG_KEYID}" "${verify_out}" || {
445                 echo "${tagname}.tar.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
446                 echo ""
447                 cat "${verify_out}"
448                 return 1
449         }
450
451         ls -la ${tagname}.*
452
453         return 0
454 }
455
456 check_samba_stable() {
457         check_args "${FUNCNAME}" "$#" "0" || return 1
458         require_tagname "${FUNCNAME}"
459
460         load_samba_stable_versions
461
462         local verify_out="${TMPDIR}/verify-${oldtagname}.out"
463
464         echo "Verifying tagname: ${tagname}"
465
466         git tag -v "${tagname}" >${verify_out} 2>&1 || {
467                 echo "failed to verify tag[${tagname}]"
468                 echo ""
469                 cat "${verify_out}"
470                 return 1
471         }
472         grep -q "${GPG_KEYID}" "${verify_out}" || {
473                 echo "tagname[${tagname}] was not generated with GPG_KEYID[${GPG_KEYID}]!"
474                 echo ""
475                 cat "${verify_out}"
476                 return 1
477         }
478
479         echo "Verifying ${tagname}.tar.gz and ${tagname}.tar.asc"
480
481         test -f "${tagname}.tar.gz" || {
482                 echo "${tagname}.tar.gz does not exist"
483                 return 1
484         }
485
486         test -f "${tagname}.tar.asc" || {
487                 echo "${tagname}.tar.asc does not exist"
488                 return 1
489         }
490
491         zcat "${tagname}.tar.gz" | gpg --verify "${tagname}.tar.asc" - 2>${verify_out} || {
492                 echo "Failed to verify ${tagname}.tar.asc"
493                 return 1
494         }
495         grep -q "${GPG_KEYID}" "${verify_out}" || {
496                 echo "${tagname}.tar.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
497                 echo ""
498                 cat "${verify_out}"
499                 return 1
500         }
501
502         test -n "${patchfile}" || {
503                 ls -lart ${tagname}.*
504                 return 0
505         }
506
507         echo "Verifying ${patchfile}.gz and ${patchfile}.asc"
508
509         test -f "${patchfile}.gz" || {
510                 echo "${patchfile}.gz does not exist"
511                 return 1
512         }
513
514         test -f "${patchfile}.asc" || {
515                 echo "${patchfile}.asc does not exist"
516                 return 1
517         }
518
519         zcat "${patchfile}.gz" | gpg --verify "${patchfile}.asc" - 2>${verify_out} || {
520                 echo "Failed to verify ${patchfile}.asc"
521                 return 1
522         }
523         grep -q "${GPG_KEYID}" "${verify_out}" || {
524                 echo "${patchfile}.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
525                 echo ""
526                 cat "${verify_out}"
527                 return 1
528         }
529
530         ls -lart ${tagname}.* ${patchfile}.*
531         return 0
532 }
533
534 check_release() {
535         check_args "${FUNCNAME}" "$#" "0" || return 1
536
537         test -n "${check_fn}" || {
538                 echo "check_fn variable empty"
539                 return 1
540         }
541
542         echo "Running ${check_fn}"
543         ${check_fn}
544 }
545
546 push_release() {
547         check_args "${FUNCNAME}" "$#" "0" || return 1
548         require_tagname "${FUNCNAME}"
549
550         echo "Push git tag ${tagname} to '${repo_url}'"
551         git push "${repo_url}" "refs/tags/${tagname}:refs/tags/${tagname}" || {
552                 return 1
553         }
554
555         return 0
556 }
557
558 upload_nopatch() {
559         check_args "${FUNCNAME}" "$#" "0" || return 1
560         require_tagname "${FUNCNAME}"
561
562         echo "Upload ${tagname}.* to '${upload_url}'"
563         rsync -Pav --delay-updates ${tagname}.* "${upload_url}/" || {
564                 return 1
565         }
566         rsync ${upload_url}/${tagname}.*
567
568         return 0
569 }
570
571 upload_samba_stable() {
572         check_args "${FUNCNAME}" "$#" "0" || return 1
573         require_tagname "${FUNCNAME}"
574
575         load_samba_stable_versions
576
577         local release_url="${upload_url}samba/stable/"
578         local patch_url="${upload_url}samba/patches/"
579
580         echo "Upload ${tagname}.tar.* to '${release_url}'"
581         ls -lart ${tagname}.tar.*
582         rsync -Pav --delay-updates ${tagname}.tar.* "${release_url}/" || {
583                 return 1
584         }
585         rsync ${release_url}/${tagname}.tar.*
586
587         test -n "${patchfile}" || {
588                 return 0
589         }
590
591         echo "Upload ${patchfile}.* to '${patch_url}'"
592         ls -lart ${patchfile}.*
593         rsync -Pav --delay-updates ${patchfile}.* "${patch_url}/" || {
594                 return 1
595         }
596         rsync ${patch_url}/${patchfile}.*
597
598         return 0
599 }
600
601 upload_release() {
602         check_args "${FUNCNAME}" "$#" "0" || return 1
603
604         test -n "${upload_fn}" || {
605                 echo "upload_fn variable empty"
606                 return 1
607         }
608
609         echo "Running ${upload_fn}"
610         ${upload_fn}
611 }
612
613 announcement_samba_rc() {
614         check_args "${FUNCNAME}" "$#" "0" || return 1
615         require_tagname "${FUNCNAME}"
616
617         test -f "${tagname}.WHATSNEW.txt" || {
618                 echo "${tagname}.WHATSNEW.txt does not exist"
619                 return 1
620         }
621
622         local t=""
623         local version=$(echo "${tagname}" | sed -e 's!^samba-!!')
624         local href="#${version}"
625         local series=$(echo "${version}" | cut -d '.' -f1-2)
626         local rc=$(echo "${version}" | sed -e 's!.*rc\([0-9][0-9]*\)!\1!')
627         local rcname="${rc}th"
628         case "${rc}" in
629         1)
630                 rcname="first"
631                 ;;
632         2)
633                 rcname="second"
634                 ;;
635         3)
636                 rcname="third"
637                 ;;
638         4)
639                 rcname="fourth"
640                 ;;
641         5)
642                 rcname="fifth"
643                 ;;
644         esac
645
646         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
647         {
648                 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
649         } > announce.${tagname}.to.txt
650
651         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
652         {
653                 echo "[Announce] Samba ${version} Available for Download"
654         } > announce.${tagname}.subject.txt
655
656         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
657         {
658                 cat ${tagname}.WHATSNEW.txt
659                 echo ""
660                 echo "================"
661                 echo "Download Details"
662                 echo "================"
663                 echo ""
664                 echo "The uncompressed tarballs and patch files have been signed"
665                 echo "using GnuPG (ID ${GPG_KEYID}).  The source code can be downloaded"
666                 echo "from:"
667                 echo ""
668                 echo "        ${download_url}"
669                 echo ""
670                 echo "The release notes are available online at:"
671                 echo ""
672                 echo "        ${download_url}${tagname}.WHATSNEW.txt"
673                 echo ""
674                 echo "Our Code, Our Bugs, Our Responsibility."
675                 echo "(https://bugzilla.samba.org/)"
676                 echo ""
677                 echo "                        --Enjoy"
678                 echo "                        The Samba Team"
679         } > announce.${tagname}.mail.txt
680
681         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
682         {
683                 echo -n "-i announce.${tagname}.mail.txt "
684                 echo -n "-s \"$(cat announce.${tagname}.subject.txt | xargs)\" "
685                 echo -n "$(cat announce.${tagname}.to.txt | xargs)"
686         } > announce.${tagname}.mutt-arguments.txt
687
688         local headlinefile="posted_news/@UTCTIME@.${version}.headline.html"
689         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.headline.html"
690         {
691                 echo "<!-- BEGIN: ${headlinefile} -->"
692                 echo "<li> @UTCDATE@ <a href=\"${href}\">Samba ${version} Available for Download</a></li>"
693                 echo "<!-- END: ${headlinefile} -->"
694         } > announce.${tagname}.headline.html
695
696         local bodyfile="posted_news/@UTCTIME@.${version}.body.html"
697         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.body.html"
698         {
699                 echo "<!-- BEGIN: ${bodyfile} -->"
700                 echo "<h5><a name=\"${version}\">@UTCDATE@</a></h5>"
701                 echo "<p class="headline">Samba ${version} Available for Download</p>"
702                 echo "<p>"
703                 echo "This is the ${rcname} release candidate of the upcoming Samba ${series} release series."
704                 echo "</p>"
705                 echo "<p>"
706                 echo "The uncompressed tarball has been signed using GnuPG (ID ${GPG_KEYID})."
707                 echo "The source code can be <a href=\"${download_url}${tagname}.tar.gz\">downloaded now</a>."
708                 echo "See <a href=\"${download_url}${tagname}.WHATSNEW.txt\">the release notes for more info</a>."
709                 echo "</p>"
710                 echo "<!-- END: ${bodyfile} -->"
711         } > announce.${tagname}.body.html
712
713         local webrepo="${TMPDIR}/webrepo"
714
715         mkdir "${webrepo}" || {
716                 return 1
717         }
718         git -C "${webrepo}" init || {
719                 return 1
720         }
721
722         mkdir -p "$(dirname ${webrepo}/${headlinefile})" || {
723                 return 1
724         }
725         cp -a "announce.${tagname}.headline.html" "${webrepo}/${headlinefile}" || {
726                 return 1
727         }
728
729         mkdir -p "$(dirname ${webrepo}/${bodyfile})" || {
730                 return 1
731         }
732         cp -a "announce.${tagname}.body.html" "${webrepo}/${bodyfile}" || {
733                 return 1
734         }
735
736         git -C "${webrepo}" add "${headlinefile}" "${bodyfile}" || {
737                 return 1
738         }
739         git -C "${webrepo}" commit --signoff --message "NEWS[${version}]: Samba ${version} Available for Download" || {
740                 return 1
741         }
742         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.patch.txt"
743         git -C "${webrepo}" format-patch --stdout -1 HEAD > announce.${tagname}.patch.txt || {
744                 return 1
745         }
746
747         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
748         {
749                 ls -lart announce.${tagname}.*
750                 echo ""
751                 echo "NOTICE:"
752                 echo "You need to do the following manual steps in order"
753                 echo "to finish the announcement of ${tagname}!"
754                 echo ""
755                 echo "Change to a samba-web checkout and run"
756                 echo "  ./announce_samba_release.sh ${version} $(pwd)/announce.${tagname}.patch.txt"
757                 echo ""
758                 echo "Once the resulting commit is pushed a cron job will update "
759                 echo "the content exported by the webserver every 5-10 mins."
760                 echo "Check https://www.samba.org"
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
774         ls -lart announce.${tagname}.*
775         return 0
776 }
777
778 announcement_samba_stable() {
779         check_args "${FUNCNAME}" "$#" "0" || return 1
780         require_tagname "${FUNCNAME}"
781
782         load_samba_stable_versions
783
784         test -f "${tagname}.tar.gz" || {
785                 echo "${tagname}.tar.gz does not exist"
786                 return 1
787         }
788
789         test -f "announce.${tagname}.quotation.txt" || {
790                 echo "announce.${tagname}.quotation.txt missing!"
791                 return 1
792         }
793
794         local release_url="${download_url}samba/stable/"
795         local patch_url="${download_url}samba/patches/"
796
797         echo "extract WHATSNEW.txt"
798         tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt > ${TMPDIR}/WHATSNEW.txt
799
800         local t=""
801         local oldversion=$(echo "${oldtagname}" | sed -e 's!^samba-!!')
802         local version=$(echo "${tagname}" | sed -e 's!^samba-!!')
803         local href="#${version}"
804         local series=$(echo "${version}" | cut -d '.' -f1-2)
805         local release=$(echo "${version}" | cut -d '.' -f3)
806         local releasename="latest"
807         case "${release}" in
808         1)
809                 releasename="first"
810                 ;;
811         *)
812                 releasename="latest"
813                 ;;
814         esac
815
816         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
817         {
818                 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
819         } > announce.${tagname}.to.txt
820
821         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
822         {
823                 echo "[Announce] Samba ${version} Available for Download"
824         } > announce.${tagname}.subject.txt
825
826         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
827         {
828                 local top=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^Release notes for older releases follow:' | head -1 | cut -d ':' -f1)
829                 test -n "${top}" || {
830                         top=$(cat ${TMPDIR}/WHATSNEW.txt | wc -l)
831                 }
832                 local skip=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^[^ ]' | head -1 | cut -d ':' -f1)
833                 local headlimit=$(expr ${top} - 1 )
834                 local taillimit=$(expr ${headlimit} - \( ${skip} - 1 \))
835
836                 cat "announce.${tagname}.quotation.txt"
837                 echo ""
838                 echo ""
839                 echo "Release Announcements"
840                 echo "---------------------"
841                 echo ""
842                 head -${headlimit} ${TMPDIR}/WHATSNEW.txt | tail -${taillimit}
843                 echo ""
844                 echo "================"
845                 echo "Download Details"
846                 echo "================"
847                 echo ""
848                 echo "The uncompressed tarballs and patch files have been signed"
849                 echo "using GnuPG (ID ${GPG_KEYID}).  The source code can be downloaded"
850                 echo "from:"
851                 echo ""
852                 echo "        ${release_url}"
853                 echo ""
854                 echo "The release notes are available online at:"
855                 echo ""
856                 echo "        ${history_url}${tagname}.html"
857                 echo ""
858                 echo "Our Code, Our Bugs, Our Responsibility."
859                 echo "(https://bugzilla.samba.org/)"
860                 echo ""
861                 echo "                        --Enjoy"
862                 echo "                        The Samba Team"
863         } > announce.${tagname}.mail.txt
864
865         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
866         {
867                 echo -n "-i announce.${tagname}.mail.txt "
868                 echo -n "-s \"$(cat announce.${tagname}.subject.txt | xargs)\" "
869                 echo -n "$(cat announce.${tagname}.to.txt | xargs)"
870         } > announce.${tagname}.mutt-arguments.txt
871
872         local htmlfile="history/${tagname}.html"
873         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.html"
874         {
875                 local tmp=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^Reporting bugs & Development Discussion' | head -1 | cut -d ':' -f1)
876                 local lines=$(expr ${tmp} - 2)
877
878                 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
879                 echo ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
880                 echo '<html xmlns="http://www.w3.org/1999/xhtml">'
881
882                 echo "<head>"
883                 echo "<title>Samba ${version} - Release Notes</title>"
884                 echo "</head>"
885
886                 echo "<body>"
887                 echo "<H2>Samba ${version} Available for Download</H2>"
888
889                 echo "<p>"
890                 echo "<a href=\"${release_url}${tagname}.tar.gz\">Samba ${version} (gzipped)</a><br>"
891                 echo "<a href=\"${release_url}${tagname}.tar.asc\">Signature</a>"
892                 echo "</p>"
893
894                 test -n "${patchfile}" && {
895                         echo "<p>"
896                         echo "<a href=\"${patch_url}${patchfile}.gz\">Patch (gzipped) against Samba ${oldversion}</a><br>"
897                         echo "<a href=\"${patch_url}${patchfile}.asc\">Signature</a>"
898                         echo "</p>"
899                 }
900
901                 echo "<p>"
902                 echo "<pre>"
903                 head -${lines} ${TMPDIR}/WHATSNEW.txt | sed \
904                         -e 's!&!\&amp;!g' | sed \
905                         -e 's!<!\&lt;!g' \
906                         -e 's!>!\&gt;!g' \
907                         -e 's!ä!\&auml;!g' \
908                         -e 's!Ä!\&Auml;!g' \
909                         -e 's!ö!\&ouml;!g' \
910                         -e 's!Ö!\&Ouml;!g' \
911                         -e 's!ü!\&uuml;!g' \
912                         -e 's!Ü!\&Uuml;!g' \
913                         -e 's!ß!\&szlig;!g' \
914                         -e 's!"!\&quot;!g' \
915                         -e "s!'!\&apos;!g" \
916                         | cat
917                 echo "</pre>"
918                 echo "</p>"
919
920                 echo "</body>"
921                 echo "</html>"
922         } > announce.${tagname}.html
923
924         local headlinefile="posted_news/@UTCTIME@.${version}.headline.html"
925         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.headline.html"
926         {
927                 echo "<!-- BEGIN: ${headlinefile} -->"
928                 echo "<li> @UTCDATE@ <a href=\"${href}\">Samba ${version} Available for Download</a></li>"
929                 echo "<!-- END: ${headlinefile} -->"
930         } > announce.${tagname}.headline.html
931
932         local bodyfile="posted_news/@UTCTIME@.${version}.body.html"
933         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.body.html"
934         {
935                 echo "<!-- BEGIN: ${bodyfile} -->"
936                 echo "<h5><a name=\"${version}\">@UTCDATE@</a></h5>"
937                 echo "<p class="headline">Samba ${version} Available for Download</p>"
938                 echo "<p>"
939                 echo "This is the ${releasename} stable release of the Samba ${series} release series."
940                 echo "</p>"
941                 echo "<p>"
942                 echo "The uncompressed tarball has been signed using GnuPG (ID ${GPG_KEYID})."
943                 echo "The source code can be <a href=\"${release_url}${tagname}.tar.gz\">downloaded now</a>."
944                 test -n "${patchfile}" && {
945                         echo "A <a href=\"${patch_url}${patchfile}.gz\">patch against Samba ${oldversion}</a> is also available."
946                 }
947                 echo "See <a href=\"${history_url}${tagname}.html\">the release notes for more info</a>."
948                 echo "</p>"
949                 echo "<!-- END: ${bodyfile} -->"
950         } > announce.${tagname}.body.html
951
952         local webrepo="${TMPDIR}/webrepo"
953
954         mkdir "${webrepo}" || {
955                 return 1
956         }
957         git -C "${webrepo}" init || {
958                 return 1
959         }
960
961         mkdir -p "$(dirname ${webrepo}/${htmlfile})" || {
962                 return 1
963         }
964         cp -a "announce.${tagname}.html" "${webrepo}/${htmlfile}" || {
965                 return 1
966         }
967
968         mkdir -p "$(dirname ${webrepo}/${headlinefile})" || {
969                 return 1
970         }
971         cp -a "announce.${tagname}.headline.html" "${webrepo}/${headlinefile}" || {
972                 return 1
973         }
974
975         mkdir -p "$(dirname ${webrepo}/${bodyfile})" || {
976                 return 1
977         }
978         cp -a "announce.${tagname}.body.html" "${webrepo}/${bodyfile}" || {
979                 return 1
980         }
981
982         git -C "${webrepo}" add "${htmlfile}" "${headlinefile}" "${bodyfile}" || {
983                 return 1
984         }
985         git -C "${webrepo}" commit --signoff --message "NEWS[${version}]: Samba ${version} Available for Download" || {
986                 return 1
987         }
988         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.patch.txt"
989         git -C "${webrepo}" format-patch --stdout -1 HEAD > announce.${tagname}.patch.txt || {
990                 return 1
991         }
992
993         CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
994         {
995                 ls -lart announce.${tagname}.*
996                 echo ""
997                 echo "NOTICE:"
998                 echo "You need to do the following manual steps in order"
999                 echo "to finish the announcement of ${tagname}!"
1000                 echo ""
1001                 echo "Change to a samba-web checkout and run"
1002                 echo "  ./announce_samba_release.sh ${version} $(pwd)/announce.${tagname}.patch.txt"
1003                 echo ""
1004                 echo "Once the resulting commit is pushed a cron job will update "
1005                 echo "the content exported by the webserver every 5-10 mins."
1006                 echo "Check https://www.samba.org"
1007                 echo ""
1008                 echo "If the web content is updated, you need to send the announce mail (gpg signed)."
1009                 echo "- announce.${tagname}.to.txt contains the mail's recipients for the To: header."
1010                 echo "- announce.${tagname}.subject.txt contains the mail's subject line."
1011                 echo "- announce.${tagname}.mail.txt contains the content of the mail body."
1012                 echo "In case your're using mutt, you can use the following shortcut:"
1013                 echo "  eval mutt \$(cat announce.${tagname}.mutt-arguments.txt)"
1014                 echo ""
1015                 echo "NOTICE: you're not done yet! Read the above instructions carefully!"
1016                 echo "See: announce.${tagname}.todo.txt"
1017                 echo ""
1018         } > announce.${tagname}.todo.txt
1019
1020         ls -lart announce.${tagname}.*
1021         return 0
1022 }
1023
1024 announcement_release() {
1025         check_args "${FUNCNAME}" "$#" "0" || return 1
1026
1027         test -n "${announcement_fn}" || {
1028                 echo "announcement_fn variable empty"
1029                 return 1
1030         }
1031
1032         echo "Running ${announcement_fn}"
1033         ${announcement_fn}
1034 }
1035
1036 announce_release() {
1037         check_args "${FUNCNAME}" "$#" "0" || return 1
1038         require_tagname "${FUNCNAME}"
1039
1040         test -f "announce.${tagname}.todo.txt" || {
1041                 echo "announce.${tagname}.todo.txt does not exist"
1042                 return 1
1043         }
1044
1045         cat announce.${tagname}.todo.txt
1046         return 0
1047 }
1048
1049 case "${product}" in
1050 talloc | tdb | tevent | ldb)
1051         test -z "${GPG_USER-}" && {
1052                 GPG_USER='Samba Library Distribution Key <samba-bugs@samba.org>'
1053         }
1054
1055         test -z "${GPG_KEYID-}"  && {
1056                 GPG_KEYID='4793916113084025'
1057         }
1058
1059         productbase="${product}"
1060         srcdir="lib/${product}"
1061         repo_url="${CONF_REPO_URL}"
1062         upload_url="${CONF_UPLOAD_URL}/${product}/"
1063         download_url="${CONF_DOWNLOAD_URL}/${product}/"
1064
1065         check_fn="check_nopatch"
1066         upload_fn="upload_nopatch"
1067         fullcmds="create check push upload"
1068         ;;
1069 samba-rc)
1070         test -z "${GPG_USER-}" && {
1071                 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1072         }
1073
1074         test -z "${GPG_KEYID-}"  && {
1075                 GPG_KEYID='6F33915B6568B7EA'
1076         }
1077
1078         productbase="samba"
1079         srcdir="."
1080         repo_url="${CONF_REPO_URL}"
1081         upload_url="${CONF_UPLOAD_URL}/samba/rc/"
1082         download_url="${CONF_DOWNLOAD_URL}/samba/rc/"
1083
1084         verify_fn="verify_samba_rc"
1085         check_fn="check_nopatch"
1086         upload_fn="upload_nopatch"
1087         announcement_fn="announcement_samba_rc"
1088         fullcmds="verify create check whatsnew announcement push upload announce"
1089         ;;
1090 samba-stable)
1091         test -z "${GPG_USER-}" && {
1092                 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1093         }
1094
1095         test -z "${GPG_KEYID-}"  && {
1096                 GPG_KEYID='6F33915B6568B7EA'
1097         }
1098
1099         productbase="samba"
1100         srcdir="."
1101         repo_url="${CONF_REPO_URL}"
1102         upload_url="${CONF_UPLOAD_URL}/"
1103         download_url="${CONF_DOWNLOAD_URL}/"
1104         history_url="${CONF_HISTORY_URL}/samba/history/"
1105
1106         verify_fn="verify_samba_stable"
1107         check_fn="check_samba_stable"
1108         upload_fn="upload_samba_stable"
1109         announcement_fn="announcement_samba_stable"
1110         fullcmds="verify create patch check announcement push upload announce"
1111         ;;
1112 TODO-samba-security)
1113         test -z "${GPG_USER-}" && {
1114                 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1115         }
1116
1117         test -z "${GPG_KEYID-}"  && {
1118                 GPG_KEYID='6F33915B6568B7EA'
1119         }
1120
1121         productbase="samba"
1122         srcdir="."
1123         repo_url="${CONF_REPO_URL}"
1124         upload_url="${CONF_UPLOAD_URL}/"
1125         download_url="${CONF_DOWNLOAD_URL}/"
1126         history_url="${CONF_HISTORY_URL}/samba/history/"
1127
1128         verify_fn="verify_samba_stable"
1129         check_fn="check_samba_stable"
1130         upload_fn="upload_samba_stable"
1131         announcement_fn="announcement_samba_security"
1132         fullcmds="verify create patch check announcement"
1133         next_cmd="push"
1134         ;;
1135 *)
1136         usage
1137         echo "Unknown product ${product}"
1138         exit 1
1139 esac
1140
1141 pushd ${srcdir} || {
1142         echo "srcdir[${srcdir}] does not exist"
1143         exit 1
1144 }
1145
1146 trap_handler() {
1147         echo ""
1148         echo "ERROR: cleaning up"
1149         echo ""
1150
1151         for t in ${CLEANUP_TAGS}; do
1152                 echo "Removing tag[${t}]"
1153                 git tag -v "${t}" && {
1154                         git tag -d "${t}" || {
1155                                 echo "failed to remove tag ${t}"
1156                         }
1157                 }
1158         done
1159
1160         for f in ${CLEANUP_FILES}; do
1161                 echo "Removing file[${f}]"
1162                 test -f "${f}" && {
1163                         rm "${f}" || {
1164                                 echo "failed to remove ${f}"
1165                         }
1166                 }
1167         done
1168
1169         for d in ${CLEANUP_DIRS}; do
1170                 echo "Removing dir[${d}]"
1171                 test -d "${d}" && {
1172                         rm -rf "${d}" || {
1173                                 echo "failed to remove ${d}"
1174                         }
1175                 }
1176         done
1177 }
1178
1179 CLEANUP_TAGS=""
1180 CLEANUP_FILES=""
1181 CLEANUP_DIRS=""
1182 trap trap_handler INT QUIT TERM EXIT
1183
1184 cmd_allowed "${globalcmd}" fullrelease ${fullcmds} || {
1185         usage
1186         echo "command[${globalcmd}] not supported for product[${product}]"
1187         exit 1
1188 }
1189
1190 case "${globalcmd}" in
1191 fullrelease)
1192         check_args "${globalcmd}" "$#" "0" || exit 1
1193         cmds="${fullcmds}"
1194         ;;
1195 create)
1196         check_args "${globalcmd}" "$#" "0" || exit 1
1197         check_args "create" "$#" "0" || exit 1
1198
1199         cmds=""
1200         cmd_allowed "verify" ${fullcmds} && {
1201                 cmds="${cmds} verify"
1202         }
1203         cmds="${cmds} create"
1204         cmd_allowed "whatsnew" ${fullcmds} && {
1205                 cmds="${cmds} whatsnew"
1206         }
1207         cmd_allowed "patch" ${fullcmds} && {
1208                 cmds="${cmds} patch"
1209         }
1210         cmds="${cmds} check"
1211         cmd_allowed "announcement" ${fullcmds} && {
1212                 cmds="${cmds} announcement"
1213         }
1214         next_cmd="push"
1215         ;;
1216 push)
1217         check_args "${globalcmd}" "$#" "1" || exit 1
1218         tagname="$1"
1219         cmds="check push"
1220         next_cmd="upload"
1221         ;;
1222 upload)
1223         check_args "${globalcmd}" "$#" "1" || exit 1
1224         tagname="$1"
1225         cmds="check upload"
1226         cmd_allowed "announce" ${fullcmds} && {
1227                 next_cmd="announce"
1228         }
1229         ;;
1230 announce)
1231         check_args "${globalcmd}" "$#" "1" || exit 1
1232         tagname="$1"
1233         cmds="check announce"
1234         ;;
1235 *)
1236         usage
1237         echo "Unknown command ${globalcmd}"
1238         exit 1
1239         ;;
1240 esac
1241
1242 TMPDIR="release.$$"
1243 CLEANUP_DIRS="${CLEANUP_DIRS} ${TMPDIR}"
1244 umask 0077
1245 mkdir "${TMPDIR}"
1246 umask 0022
1247
1248 for cmd in ${cmds}; do
1249         echo "Starting subcommand[${cmd}]"
1250         ${cmd}_release || {
1251                 echo "Failed subcommand[${cmd}]"
1252                 exit 1
1253         }
1254         echo "Finished subcommand[${cmd}]"
1255 done
1256
1257 test -d "${TMPDIR}" && {
1258         rm -rf "${TMPDIR}" || {
1259                 echo "failed to remove ${TMPDIR}"
1260         }
1261 }
1262
1263 test -n "${next_cmd}" && {
1264         echo "Continue with '$0 ${product} ${next_cmd} ${tagname}'."
1265 }
1266
1267 trap - INT QUIT TERM EXIT
1268
1269 exit 0