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