python: Use secrets.token_bytes instead of random
[Samba.git] / script / release.sh
blobb144f74e817958fa6c9107ef4969cb738add30e5
1 #!/bin/bash
2 # make a release of Samba or a library
4 LC_ALL=C
5 export LC_ALL
6 LANG=C
7 export LANG
8 LANGUAGE=C
9 export LANGUAGE
11 set -u
12 set -e
13 umask 0022
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"
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
26 usage()
28 echo "Usage: script/release.sh <PRODUCT> <COMMAND>"
29 echo ""
30 echo "PRODUCT: ldb, talloc, tevent, tdb, samba-rc, samba-stable"
31 echo "COMMAND: fullrelease, create, push, upload, announce"
32 echo ""
33 return 0
36 test -x "script/release.sh" || {
37 usage
38 echo "Run this script from the top-level directory in the"
39 echo "repository: as 'script/release.sh'"
40 exit 1
43 check_args()
45 local cmd="$1"
46 local got_args="$2"
47 local take_args="$3"
49 test x"${got_args}" = x"${take_args}" || {
50 usage
51 echo "cmd[${cmd}] takes ${take_args} instead of ${got_args}"
52 return 1
55 return 0
58 min_args()
60 local cmd="$1"
61 local got_args="$2"
62 local min_args="$3"
64 test "${got_args}" -ge "${min_args}" || {
65 usage
66 echo "cmd[${cmd}] takes at least ${min_args} instead of ${got_args}"
67 return 1
70 return 0
73 min_args "$0" "$#" "2"
75 product="$1"
76 globalcmd="$2"
77 shift 2
78 oldtagname=""
79 tagname=""
80 patchfile=""
81 cmds=""
82 next_cmd=""
84 require_tagname()
86 min_args "${FUNCNAME}" "$#" "1" || return 1
87 local cmd="$1"
89 test -n "${tagname}" || {
90 echo "cmd[${cmd}] requires '\${tagname}' variable to be set"
91 return 1
94 local name=$(echo "${tagname}" | cut -d '-' -f1)
95 test x"${name}" = x"${productbase}" || {
96 echo "Invalid tagname[${tgzname}]"
97 return 1
100 return 0
103 cmd_allowed()
105 min_args "${FUNCNAME}" "$#" "2" || return 1
106 local cmd="$1"
107 shift 1
109 echo "$@" | grep -q "\<${cmd}\>" || {
110 return 1
113 return 0
116 verify_samba_rc()
118 check_args "${FUNCNAME}" "$#" "0" || return 1
120 test -f VERSION || {
121 echo "VERSION doesn't exist"
122 return 1
125 grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
126 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
127 return 1
130 grep -q '^SAMBA_VERSION_RC_RELEASE=' VERSION || {
131 echo "SAMBA_VERSION_RC_RELEASE= missing"
132 return 1
135 grep -q '^SAMBA_VERSION_RC_RELEASE=$' VERSION && {
136 echo "SAMBA_VERSION_RC_RELEASE= missing the rc version"
137 return 1
140 return 0
143 load_samba_stable_versions()
145 check_args "${FUNCNAME}" "$#" "0" || return 1
147 test -n "${version-}" && {
148 return 0
151 local SAMBA_VERSION_MAJOR=$(grep '^SAMBA_VERSION_MAJOR=' VERSION | cut -d '=' -f2 | xargs)
152 local SAMBA_VERSION_MINOR=$(grep '^SAMBA_VERSION_MINOR=' VERSION | cut -d '=' -f2 | xargs)
153 local SAMBA_VERSION_RELEASE=$(grep '^SAMBA_VERSION_RELEASE=' VERSION | cut -d '=' -f2 | xargs)
155 version="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.${SAMBA_VERSION_RELEASE}"
156 tagname="${productbase}-${version}"
158 test ${SAMBA_VERSION_RELEASE} -gt 0 || {
159 return 0
162 oldversion="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.$(expr ${SAMBA_VERSION_RELEASE} - 1)"
163 oldtagname="${productbase}-${oldversion}"
164 patchfile="${productbase}-${oldversion}-${version}.diffs"
166 return 0
169 verify_samba_stable()
171 check_args "${FUNCNAME}" "$#" "0" || return 1
173 test -f VERSION || {
174 echo "VERSION doesn't exist"
175 return 1
178 grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
179 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
180 return 1
183 local VARS=""
184 VARS="${VARS} SAMBA_VERSION_REVISION"
185 VARS="${VARS} SAMBA_VERSION_TP_RELEASE"
186 VARS="${VARS} SAMBA_VERSION_ALPHA_RELEASE"
187 VARS="${VARS} SAMBA_VERSION_BETA_RELEASE"
188 VARS="${VARS} SAMBA_VERSION_PRE_RELEASE"
189 VARS="${VARS} SAMBA_VERSION_RC_RELEASE"
190 VARS="${VARS} SAMBA_VERSION_RELEASE_NICKNAME"
191 VARS="${VARS} SAMBA_VERSION_VENDOR_SUFFIX"
192 VARS="${VARS} SAMBA_VERSION_VENDOR_PATCH"
193 for var in ${VARS}; do
194 grep -q "^${var}" VERSION && {
195 grep -q "^${var}=$" VERSION || {
196 echo "${var} found in stable version"
197 return 1
200 done
202 load_samba_stable_versions
204 test -n "${oldtagname}" || {
205 return 0
208 local verify_out="${TMPDIR}/verify-${oldtagname}.out"
210 echo "Verifying oldtagname: ${oldtagname}"
212 git tag -v "${oldtagname}" >${verify_out} 2>&1 || {
213 echo "failed to verify old tag[${oldtagname}]"
214 echo ""
215 cat "${verify_out}"
216 return 1
219 grep -q "${GPG_KEYID}" "${verify_out}" || {
220 echo "oldtagname[${oldtagname}] was not generated with GPG_KEYID[${GPG_KEYID}]!"
221 echo ""
222 cat "${verify_out}"
223 return 1
226 echo "Verifying ${oldtagname}.tar.gz and ${oldtagname}.tar.asc"
228 test -f "${oldtagname}.tar.gz" || {
229 echo "${oldtagname}.tar.gz does not exist"
230 return 1
233 test -f "${oldtagname}.tar.asc" || {
234 echo "${oldtagname}.tar.asc does not exist"
235 return 1
238 zcat "${oldtagname}.tar.gz" | gpg --verify "${oldtagname}.tar.asc" - 2>${verify_out} || {
239 echo "Failed to verify ${oldtagname}.tar.asc"
240 return 1
243 grep -q "${GPG_KEYID}" "${verify_out}" || {
244 echo "${oldtagname}.tar.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
245 echo ""
246 cat "${verify_out}"
247 return 1
250 return 0
253 verify_release()
255 check_args "${FUNCNAME}" "$#" "0" || return 1
257 test -n "${verify_fn}" || {
258 echo "verify_fn variable empty"
259 return 1
262 echo "Running ${verify_fn}"
263 ${verify_fn}
266 create_release()
268 check_args "${FUNCNAME}" "$#" "0" || return 1
270 echo "Releasing product ${product}"
272 test -n "${tagname}" && {
273 git tag -l "${tagname}" | grep -q "${tagname}" && {
274 echo "tagname[${tagname}] already exist"
275 return 1
278 local _tgzname="${tagname}.tar.gz"
279 test -e "${_tgzname}" && {
280 echo "_tgzname[${_tgzname}] already exist"
281 return 1
285 echo "Building release tarball"
286 local tgzname=$(make dist 2>&1 | grep ^Created | cut -d' ' -f2)
287 test -f "${tgzname}" || {
288 echo "Failed to create tarball"
289 return 1
291 CLEANUP_FILES="${CLEANUP_FILES} ${tgzname}"
293 local name=$(echo "${tgzname}" | cut -d '-' -f1)
294 test x"${name}" = x"${productbase}" || {
295 echo "Invalid tgzname[${tgzname}]"
296 return 1
299 local _tagname=$(basename ${tgzname} .tar.gz)
300 test -n "${tagname}" && {
301 test x"${_tagname}" = x"${tagname}" || {
302 echo "Invalid tgzname[${tgzname}]"
303 return 1
306 tagname="${_tagname}"
308 local tarname=$(basename ${tgzname} .gz)
309 echo "Tarball: ${tarname}"
310 gunzip -f ${tgzname} || {
311 echo "Failed to decompress tarball ${tarname}"
312 return 1
314 test -f "${tarname}" || {
315 echo "Failed to decompress tarball ${tarname}"
316 return 1
318 CLEANUP_FILES="${CLEANUP_FILES} ${tarname}"
320 # tagname is global
321 echo "Tagging as ${tagname}"
322 git tag -u ${GPG_KEYID} -s "${tagname}" -m "${productbase}: tag release ${tagname}" || {
323 return 1
325 CLEANUP_TAGS="${CLEANUP_TAGS} ${tagname}"
327 echo "Signing ${tarname} => ${tarname}.asc"
328 rm -f "${tarname}.asc"
329 gpg --default-key "${GPG_KEYID}" --detach-sign --armor ${tarname} || {
330 return 1
332 test -f "${tarname}.asc" || {
333 echo "Failed to create signature ${tarname}.asc"
334 return 1
336 CLEANUP_FILES="${CLEANUP_FILES} ${tarname}.asc"
337 echo "Compressing ${tarname} => ${tgzname}"
338 gzip -f -9 ${tarname}
339 test -f "${tgzname}" || {
340 echo "Failed to compress ${tgzname}"
341 return 1
344 return 0
347 patch_release()
349 check_args "${FUNCNAME}" "$#" "0" || return 1
350 require_tagname "${FUNCNAME}"
352 test -n "${patchfile}" || {
353 return 0
356 local oldpwd=$(pwd)
357 echo "Generating ${patchfile}"
359 set -e
360 set -u
361 pushd "${TMPDIR}"
362 tar xfz "${oldpwd}/${oldtagname}.tar.gz"
363 tar xfz "${oldpwd}/${tagname}.tar.gz"
364 diff -Npur "${oldtagname}/" "${tagname}/" >"${patchfile}"
365 popd
367 CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}"
368 mv "${TMPDIR}/${patchfile}" "${patchfile}" || {
369 echo "failed cmd[mv ${TMPDIR}/${patchfile} ${patchfile}]"
370 return 1
373 echo "Signing ${patchfile} => ${patchfile}.asc"
374 rm -f "${patchfile}.asc"
375 CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.asc"
376 gpg --default-key "${GPG_KEYID}" --detach-sign --armor ${patchfile} || {
377 return 1
379 test -f "${patchfile}.asc" || {
380 echo "Failed to create signature ${patchfile}.asc"
381 return 1
383 echo "Compressing ${patchfile} => ${patchfile}.gz"
384 CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.gz"
385 gzip -f -9 ${patchfile}
386 test -f "${patchfile}.gz" || {
387 echo "Failed to compress ${patchfile}.gz"
388 return 1
391 return 0
394 whatsnew_release()
396 check_args "${FUNCNAME}" "$#" "0" || return 1
397 require_tagname "${FUNCNAME}"
399 echo "extract ${tagname}.WHATSNEW.txt"
400 tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt >${tagname}.WHATSNEW.txt
401 CLEANUP_FILES="${CLEANUP_FILES} ${tagname}.WHATSNEW.txt"
403 return 0
406 check_nopatch()
408 check_args "${FUNCNAME}" "$#" "0" || return 1
409 require_tagname "${FUNCNAME}"
411 local verify_out="${TMPDIR}/verify-${oldtagname}.out"
413 echo "Verifying tagname: ${tagname}"
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
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
428 echo "Verifying ${tagname}.tar.gz and ${tagname}.tar.asc"
430 test -f "${tagname}.tar.gz" || {
431 echo "${tagname}.tar.gz does not exist"
432 return 1
435 test -f "${tagname}.tar.asc" || {
436 echo "${tagname}.tar.asc does not exist"
437 return 1
440 zcat "${tagname}.tar.gz" | gpg --verify "${tagname}.tar.asc" - 2>${verify_out} || {
441 echo "Failed to verify ${tagname}.tar.asc"
442 return 1
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
451 ls -la ${tagname}.*
453 return 0
456 check_samba_stable()
458 check_args "${FUNCNAME}" "$#" "0" || return 1
459 require_tagname "${FUNCNAME}"
461 load_samba_stable_versions
463 local verify_out="${TMPDIR}/verify-${oldtagname}.out"
465 echo "Verifying tagname: ${tagname}"
467 git tag -v "${tagname}" >${verify_out} 2>&1 || {
468 echo "failed to verify tag[${tagname}]"
469 echo ""
470 cat "${verify_out}"
471 return 1
473 grep -q "${GPG_KEYID}" "${verify_out}" || {
474 echo "tagname[${tagname}] was not generated with GPG_KEYID[${GPG_KEYID}]!"
475 echo ""
476 cat "${verify_out}"
477 return 1
480 echo "Verifying ${tagname}.tar.gz and ${tagname}.tar.asc"
482 test -f "${tagname}.tar.gz" || {
483 echo "${tagname}.tar.gz does not exist"
484 return 1
487 test -f "${tagname}.tar.asc" || {
488 echo "${tagname}.tar.asc does not exist"
489 return 1
492 zcat "${tagname}.tar.gz" | gpg --verify "${tagname}.tar.asc" - 2>${verify_out} || {
493 echo "Failed to verify ${tagname}.tar.asc"
494 return 1
496 grep -q "${GPG_KEYID}" "${verify_out}" || {
497 echo "${tagname}.tar.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
498 echo ""
499 cat "${verify_out}"
500 return 1
503 test -n "${patchfile}" || {
504 ls -lart ${tagname}.*
505 return 0
508 echo "Verifying ${patchfile}.gz and ${patchfile}.asc"
510 test -f "${patchfile}.gz" || {
511 echo "${patchfile}.gz does not exist"
512 return 1
515 test -f "${patchfile}.asc" || {
516 echo "${patchfile}.asc does not exist"
517 return 1
520 zcat "${patchfile}.gz" | gpg --verify "${patchfile}.asc" - 2>${verify_out} || {
521 echo "Failed to verify ${patchfile}.asc"
522 return 1
524 grep -q "${GPG_KEYID}" "${verify_out}" || {
525 echo "${patchfile}.asc was not generated with GPG_KEYID[${GPG_KEYID}]!"
526 echo ""
527 cat "${verify_out}"
528 return 1
531 ls -lart ${tagname}.* ${patchfile}.*
532 return 0
535 check_release()
537 check_args "${FUNCNAME}" "$#" "0" || return 1
539 test -n "${check_fn}" || {
540 echo "check_fn variable empty"
541 return 1
544 echo "Running ${check_fn}"
545 ${check_fn}
548 push_release()
550 check_args "${FUNCNAME}" "$#" "0" || return 1
551 require_tagname "${FUNCNAME}"
553 echo "Push git tag ${tagname} to '${repo_url}'"
554 git push "${repo_url}" "refs/tags/${tagname}:refs/tags/${tagname}" || {
555 return 1
558 return 0
561 upload_nopatch()
563 check_args "${FUNCNAME}" "$#" "0" || return 1
564 require_tagname "${FUNCNAME}"
566 echo "Upload ${tagname}.* to '${upload_url}'"
567 rsync -Pav --delay-updates ${tagname}.* "${upload_url}/" || {
568 return 1
570 rsync ${upload_url}/${tagname}.*
572 return 0
575 upload_samba_stable()
577 check_args "${FUNCNAME}" "$#" "0" || return 1
578 require_tagname "${FUNCNAME}"
580 load_samba_stable_versions
582 local release_url="${upload_url}samba/stable/"
583 local patch_url="${upload_url}samba/patches/"
585 echo "Upload ${tagname}.tar.* to '${release_url}'"
586 ls -lart ${tagname}.tar.*
587 rsync -Pav --delay-updates ${tagname}.tar.* "${release_url}/" || {
588 return 1
590 rsync ${release_url}/${tagname}.tar.*
592 test -n "${patchfile}" || {
593 return 0
596 echo "Upload ${patchfile}.* to '${patch_url}'"
597 ls -lart ${patchfile}.*
598 rsync -Pav --delay-updates ${patchfile}.* "${patch_url}/" || {
599 return 1
601 rsync ${patch_url}/${patchfile}.*
603 return 0
606 upload_release()
608 check_args "${FUNCNAME}" "$#" "0" || return 1
610 test -n "${upload_fn}" || {
611 echo "upload_fn variable empty"
612 return 1
615 echo "Running ${upload_fn}"
616 ${upload_fn}
619 announcement_samba_rc()
621 check_args "${FUNCNAME}" "$#" "0" || return 1
622 require_tagname "${FUNCNAME}"
624 test -f "${tagname}.WHATSNEW.txt" || {
625 echo "${tagname}.WHATSNEW.txt does not exist"
626 return 1
629 local t=""
630 local version=$(echo "${tagname}" | sed -e 's!^samba-!!')
631 local href="#${version}"
632 local series=$(echo "${version}" | cut -d '.' -f1-2)
633 local rc=$(echo "${version}" | sed -e 's!.*rc\([0-9][0-9]*\)!\1!')
634 local rcname="${rc}th"
635 case "${rc}" in
637 rcname="first"
640 rcname="second"
643 rcname="third"
646 rcname="fourth"
649 rcname="fifth"
651 esac
653 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
655 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
656 } >announce.${tagname}.to.txt
658 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
660 echo "[Announce] Samba ${version} Available for Download"
661 } >announce.${tagname}.subject.txt
663 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
665 cat ${tagname}.WHATSNEW.txt
666 echo ""
667 echo "================"
668 echo "Download Details"
669 echo "================"
670 echo ""
671 echo "The uncompressed tarballs and patch files have been signed"
672 echo "using GnuPG (ID ${GPG_KEYID}). The source code can be downloaded"
673 echo "from:"
674 echo ""
675 echo " ${download_url}"
676 echo ""
677 echo "The release notes are available online at:"
678 echo ""
679 echo " ${download_url}${tagname}.WHATSNEW.txt"
680 echo ""
681 echo "Our Code, Our Bugs, Our Responsibility."
682 echo "(https://bugzilla.samba.org/)"
683 echo ""
684 echo " --Enjoy"
685 echo " The Samba Team"
686 } >announce.${tagname}.mail.txt
688 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
690 echo -n "-i announce.${tagname}.mail.txt "
691 echo -n "-s \"$(cat announce.${tagname}.subject.txt | xargs)\" "
692 echo -n "$(cat announce.${tagname}.to.txt | xargs)"
693 } >announce.${tagname}.mutt-arguments.txt
695 local headlinefile="posted_news/@UTCTIME@.${version}.headline.html"
696 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.headline.html"
698 echo "<!-- BEGIN: ${headlinefile} -->"
699 echo "<li> @UTCDATE@ <a href=\"${href}\">Samba ${version} Available for Download</a></li>"
700 echo "<!-- END: ${headlinefile} -->"
701 } >announce.${tagname}.headline.html
703 local bodyfile="posted_news/@UTCTIME@.${version}.body.html"
704 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.body.html"
706 echo "<!-- BEGIN: ${bodyfile} -->"
707 echo "<h5><a name=\"${version}\">@UTCDATE@</a></h5>"
708 echo "<p class="headline">Samba ${version} Available for Download</p>"
709 echo "<p>"
710 echo "This is the ${rcname} release candidate of the upcoming Samba ${series} release series."
711 echo "</p>"
712 echo "<p>"
713 echo "The uncompressed tarball has been signed using GnuPG (ID ${GPG_KEYID})."
714 echo "The source code can be <a href=\"${download_url}${tagname}.tar.gz\">downloaded now</a>."
715 echo "See <a href=\"${download_url}${tagname}.WHATSNEW.txt\">the release notes for more info</a>."
716 echo "</p>"
717 echo "<!-- END: ${bodyfile} -->"
718 } >announce.${tagname}.body.html
720 local webrepo="${TMPDIR}/webrepo"
722 mkdir "${webrepo}" || {
723 return 1
725 git -C "${webrepo}" init || {
726 return 1
729 mkdir -p "$(dirname ${webrepo}/${headlinefile})" || {
730 return 1
732 cp -a "announce.${tagname}.headline.html" "${webrepo}/${headlinefile}" || {
733 return 1
736 mkdir -p "$(dirname ${webrepo}/${bodyfile})" || {
737 return 1
739 cp -a "announce.${tagname}.body.html" "${webrepo}/${bodyfile}" || {
740 return 1
743 git -C "${webrepo}" add "${headlinefile}" "${bodyfile}" || {
744 return 1
746 git -C "${webrepo}" commit --signoff --message "NEWS[${version}]: Samba ${version} Available for Download" || {
747 return 1
749 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.patch.txt"
750 git -C "${webrepo}" format-patch --stdout -1 HEAD >announce.${tagname}.patch.txt || {
751 return 1
754 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
756 ls -lart announce.${tagname}.*
757 echo ""
758 echo "NOTICE:"
759 echo "You need to do the following manual steps in order"
760 echo "to finish the announcement of ${tagname}!"
761 echo ""
762 echo "Change to a samba-web checkout and run"
763 echo " ./announce_samba_release.sh ${version} $(pwd)/announce.${tagname}.patch.txt"
764 echo ""
765 echo "Once the resulting commit is pushed a cron job will update "
766 echo "the content exported by the webserver every 5-10 mins."
767 echo "Check https://www.samba.org"
768 echo ""
769 echo "If the web content is updated, you need to send the announce mail (gpg signed)."
770 echo "- announce.${tagname}.to.txt contains the mail's recipients for the To: header."
771 echo "- announce.${tagname}.subject.txt contains the mail's subject line."
772 echo "- announce.${tagname}.mail.txt contains the content of the mail body."
773 echo "In case your're using mutt, you can use the following shortcut:"
774 echo " eval mutt \$(cat announce.${tagname}.mutt-arguments.txt)"
775 echo ""
776 echo "NOTICE: you're not done yet! Read the above instructions carefully!"
777 echo "See: announce.${tagname}.todo.txt"
778 echo ""
779 } >announce.${tagname}.todo.txt
781 ls -lart announce.${tagname}.*
782 return 0
785 announcement_samba_stable()
787 check_args "${FUNCNAME}" "$#" "0" || return 1
788 require_tagname "${FUNCNAME}"
790 load_samba_stable_versions
792 test -f "${tagname}.tar.gz" || {
793 echo "${tagname}.tar.gz does not exist"
794 return 1
797 local release_url="${download_url}samba/stable/"
798 local patch_url="${download_url}samba/patches/"
800 echo "extract WHATSNEW.txt"
801 tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt >${TMPDIR}/WHATSNEW.txt
803 local t=""
804 local oldversion=$(echo "${oldtagname}" | sed -e 's!^samba-!!')
805 local version=$(echo "${tagname}" | sed -e 's!^samba-!!')
806 local href="#${version}"
807 local series=$(echo "${version}" | cut -d '.' -f1-2)
808 local release=$(echo "${version}" | cut -d '.' -f3)
809 local releasename="latest"
810 case "${release}" in
812 releasename="first"
815 releasename="latest"
817 esac
819 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
821 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
822 } >announce.${tagname}.to.txt
824 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
826 echo "[Announce] Samba ${version} Available for Download"
827 } >announce.${tagname}.subject.txt
829 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
831 local top=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^Release notes for older releases follow:' | head -1 | cut -d ':' -f1)
832 test -n "${top}" || {
833 top=$(cat ${TMPDIR}/WHATSNEW.txt | wc -l)
835 local skip=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^[^ ]' | head -1 | cut -d ':' -f1)
836 local headlimit=$(expr ${top} - 1)
837 local taillimit=$(expr ${headlimit} - \( ${skip} - 1 \))
839 echo ""
840 echo ""
841 echo "Release Announcements"
842 echo "---------------------"
843 echo ""
844 head -${headlimit} ${TMPDIR}/WHATSNEW.txt | tail -${taillimit}
845 echo ""
846 echo "================"
847 echo "Download Details"
848 echo "================"
849 echo ""
850 echo "The uncompressed tarballs and patch files have been signed"
851 echo "using GnuPG (ID ${GPG_KEYID}). The source code can be downloaded"
852 echo "from:"
853 echo ""
854 echo " ${release_url}"
855 echo ""
856 echo "The release notes are available online at:"
857 echo ""
858 echo " ${history_url}${tagname}.html"
859 echo ""
860 echo "Our Code, Our Bugs, Our Responsibility."
861 echo "(https://bugzilla.samba.org/)"
862 echo ""
863 echo " --Enjoy"
864 echo " The Samba Team"
865 } >announce.${tagname}.mail.txt
867 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
869 echo -n "-i announce.${tagname}.mail.txt "
870 echo -n "-s \"$(cat announce.${tagname}.subject.txt | xargs)\" "
871 echo -n "$(cat announce.${tagname}.to.txt | xargs)"
872 } >announce.${tagname}.mutt-arguments.txt
874 local htmlfile="history/${tagname}.html"
875 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.html"
877 local tmp=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^Reporting bugs & Development Discussion' | head -1 | cut -d ':' -f1)
878 local lines=$(expr ${tmp} - 2)
880 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
881 echo ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
882 echo '<html xmlns="http://www.w3.org/1999/xhtml">'
884 echo "<head>"
885 echo "<title>Samba ${version} - Release Notes</title>"
886 echo "</head>"
888 echo "<body>"
889 echo "<H2>Samba ${version} Available for Download</H2>"
891 echo "<p>"
892 echo "<a href=\"${release_url}${tagname}.tar.gz\">Samba ${version} (gzipped)</a><br>"
893 echo "<a href=\"${release_url}${tagname}.tar.asc\">Signature</a>"
894 echo "</p>"
896 test -n "${patchfile}" && {
897 echo "<p>"
898 echo "<a href=\"${patch_url}${patchfile}.gz\">Patch (gzipped) against Samba ${oldversion}</a><br>"
899 echo "<a href=\"${patch_url}${patchfile}.asc\">Signature</a>"
900 echo "</p>"
903 echo "<p>"
904 echo "<pre>"
905 head -${lines} ${TMPDIR}/WHATSNEW.txt | sed \
906 -e 's!&!\&amp;!g' | sed \
907 -e 's!<!\&lt;!g' \
908 -e 's!>!\&gt;!g' \
909 -e 's!ä!\&auml;!g' \
910 -e 's!Ä!\&Auml;!g' \
911 -e 's!ö!\&ouml;!g' \
912 -e 's!Ö!\&Ouml;!g' \
913 -e 's!ü!\&uuml;!g' \
914 -e 's!Ü!\&Uuml;!g' \
915 -e 's!ß!\&szlig;!g' \
916 -e 's!"!\&quot;!g' \
917 -e "s!'!\&apos;!g" |
919 echo "</pre>"
920 echo "</p>"
922 echo "</body>"
923 echo "</html>"
924 } >announce.${tagname}.html
926 local headlinefile="posted_news/@UTCTIME@.${version}.headline.html"
927 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.headline.html"
929 echo "<!-- BEGIN: ${headlinefile} -->"
930 echo "<li> @UTCDATE@ <a href=\"${href}\">Samba ${version} Available for Download</a></li>"
931 echo "<!-- END: ${headlinefile} -->"
932 } >announce.${tagname}.headline.html
934 local bodyfile="posted_news/@UTCTIME@.${version}.body.html"
935 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.body.html"
937 echo "<!-- BEGIN: ${bodyfile} -->"
938 echo "<h5><a name=\"${version}\">@UTCDATE@</a></h5>"
939 echo "<p class="headline">Samba ${version} Available for Download</p>"
940 echo "<p>"
941 echo "This is the ${releasename} stable release of the Samba ${series} release series."
942 echo "</p>"
943 echo "<p>"
944 echo "The uncompressed tarball has been signed using GnuPG (ID ${GPG_KEYID})."
945 echo "The source code can be <a href=\"${release_url}${tagname}.tar.gz\">downloaded now</a>."
946 test -n "${patchfile}" && {
947 echo "A <a href=\"${patch_url}${patchfile}.gz\">patch against Samba ${oldversion}</a> is also available."
949 echo "See <a href=\"${history_url}${tagname}.html\">the release notes for more info</a>."
950 echo "</p>"
951 echo "<!-- END: ${bodyfile} -->"
952 } >announce.${tagname}.body.html
954 local webrepo="${TMPDIR}/webrepo"
956 mkdir "${webrepo}" || {
957 return 1
959 git -C "${webrepo}" init || {
960 return 1
963 mkdir -p "$(dirname ${webrepo}/${htmlfile})" || {
964 return 1
966 cp -a "announce.${tagname}.html" "${webrepo}/${htmlfile}" || {
967 return 1
970 mkdir -p "$(dirname ${webrepo}/${headlinefile})" || {
971 return 1
973 cp -a "announce.${tagname}.headline.html" "${webrepo}/${headlinefile}" || {
974 return 1
977 mkdir -p "$(dirname ${webrepo}/${bodyfile})" || {
978 return 1
980 cp -a "announce.${tagname}.body.html" "${webrepo}/${bodyfile}" || {
981 return 1
984 git -C "${webrepo}" add "${htmlfile}" "${headlinefile}" "${bodyfile}" || {
985 return 1
987 git -C "${webrepo}" commit --signoff --message "NEWS[${version}]: Samba ${version} Available for Download" || {
988 return 1
990 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.patch.txt"
991 git -C "${webrepo}" format-patch --stdout -1 HEAD >announce.${tagname}.patch.txt || {
992 return 1
995 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
997 ls -lart announce.${tagname}.*
998 echo ""
999 echo "NOTICE:"
1000 echo "You need to do the following manual steps in order"
1001 echo "to finish the announcement of ${tagname}!"
1002 echo ""
1003 echo "Change to a samba-web checkout and run"
1004 echo " ./announce_samba_release.sh ${version} $(pwd)/announce.${tagname}.patch.txt"
1005 echo ""
1006 echo "Once the resulting commit is pushed a cron job will update "
1007 echo "the content exported by the webserver every 5-10 mins."
1008 echo "Check https://www.samba.org"
1009 echo ""
1010 echo "If the web content is updated, you need to send the announce mail (gpg signed)."
1011 echo "- announce.${tagname}.to.txt contains the mail's recipients for the To: header."
1012 echo "- announce.${tagname}.subject.txt contains the mail's subject line."
1013 echo "- announce.${tagname}.mail.txt contains the content of the mail body."
1014 echo "In case your're using mutt, you can use the following shortcut:"
1015 echo " eval mutt \$(cat announce.${tagname}.mutt-arguments.txt)"
1016 echo ""
1017 echo "NOTICE: you're not done yet! Read the above instructions carefully!"
1018 echo "See: announce.${tagname}.todo.txt"
1019 echo ""
1020 } >announce.${tagname}.todo.txt
1022 ls -lart announce.${tagname}.*
1023 return 0
1026 announcement_release()
1028 check_args "${FUNCNAME}" "$#" "0" || return 1
1030 test -n "${announcement_fn}" || {
1031 echo "announcement_fn variable empty"
1032 return 1
1035 echo "Running ${announcement_fn}"
1036 ${announcement_fn}
1039 announce_release()
1041 check_args "${FUNCNAME}" "$#" "0" || return 1
1042 require_tagname "${FUNCNAME}"
1044 test -f "announce.${tagname}.todo.txt" || {
1045 echo "announce.${tagname}.todo.txt does not exist"
1046 return 1
1049 cat announce.${tagname}.todo.txt
1050 return 0
1053 case "${product}" in
1054 talloc | tdb | tevent | ldb)
1055 test -z "${GPG_USER-}" && {
1056 GPG_USER='Samba Library Distribution Key <samba-bugs@samba.org>'
1059 test -z "${GPG_KEYID-}" && {
1060 GPG_KEYID='4793916113084025'
1063 productbase="${product}"
1064 srcdir="lib/${product}"
1065 repo_url="${CONF_REPO_URL}"
1066 upload_url="${CONF_UPLOAD_URL}/${product}/"
1067 download_url="${CONF_DOWNLOAD_URL}/${product}/"
1069 check_fn="check_nopatch"
1070 upload_fn="upload_nopatch"
1071 fullcmds="create check push upload"
1073 samba-rc)
1074 test -z "${GPG_USER-}" && {
1075 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1078 test -z "${GPG_KEYID-}" && {
1079 GPG_KEYID='AA99442FB680B620'
1082 productbase="samba"
1083 srcdir="."
1084 repo_url="${CONF_REPO_URL}"
1085 upload_url="${CONF_UPLOAD_URL}/samba/rc/"
1086 download_url="${CONF_DOWNLOAD_URL}/samba/rc/"
1088 verify_fn="verify_samba_rc"
1089 check_fn="check_nopatch"
1090 upload_fn="upload_nopatch"
1091 announcement_fn="announcement_samba_rc"
1092 fullcmds="verify create check whatsnew announcement push upload announce"
1094 samba-stable)
1095 test -z "${GPG_USER-}" && {
1096 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1099 test -z "${GPG_KEYID-}" && {
1100 GPG_KEYID='AA99442FB680B620'
1103 productbase="samba"
1104 srcdir="."
1105 repo_url="${CONF_REPO_URL}"
1106 upload_url="${CONF_UPLOAD_URL}/"
1107 download_url="${CONF_DOWNLOAD_URL}/"
1108 history_url="${CONF_HISTORY_URL}/samba/history/"
1110 verify_fn="verify_samba_stable"
1111 check_fn="check_samba_stable"
1112 upload_fn="upload_samba_stable"
1113 announcement_fn="announcement_samba_stable"
1114 fullcmds="verify create patch check announcement push upload announce"
1116 TODO-samba-security)
1117 test -z "${GPG_USER-}" && {
1118 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1121 test -z "${GPG_KEYID-}" && {
1122 GPG_KEYID='AA99442FB680B620'
1125 productbase="samba"
1126 srcdir="."
1127 repo_url="${CONF_REPO_URL}"
1128 upload_url="${CONF_UPLOAD_URL}/"
1129 download_url="${CONF_DOWNLOAD_URL}/"
1130 history_url="${CONF_HISTORY_URL}/samba/history/"
1132 verify_fn="verify_samba_stable"
1133 check_fn="check_samba_stable"
1134 upload_fn="upload_samba_stable"
1135 announcement_fn="announcement_samba_security"
1136 fullcmds="verify create patch check announcement"
1137 next_cmd="push"
1140 usage
1141 echo "Unknown product ${product}"
1142 exit 1
1144 esac
1146 pushd ${srcdir} || {
1147 echo "srcdir[${srcdir}] does not exist"
1148 exit 1
1151 trap_handler()
1153 echo ""
1154 echo "ERROR: cleaning up"
1155 echo ""
1157 for t in ${CLEANUP_TAGS}; do
1158 echo "Removing tag[${t}]"
1159 git tag -v "${t}" && {
1160 git tag -d "${t}" || {
1161 echo "failed to remove tag ${t}"
1164 done
1166 for f in ${CLEANUP_FILES}; do
1167 echo "Removing file[${f}]"
1168 test -f "${f}" && {
1169 rm "${f}" || {
1170 echo "failed to remove ${f}"
1173 done
1175 for d in ${CLEANUP_DIRS}; do
1176 echo "Removing dir[${d}]"
1177 test -d "${d}" && {
1178 rm -rf "${d}" || {
1179 echo "failed to remove ${d}"
1182 done
1185 CLEANUP_TAGS=""
1186 CLEANUP_FILES=""
1187 CLEANUP_DIRS=""
1188 trap trap_handler INT QUIT TERM EXIT
1190 cmd_allowed "${globalcmd}" fullrelease ${fullcmds} || {
1191 usage
1192 echo "command[${globalcmd}] not supported for product[${product}]"
1193 exit 1
1196 case "${globalcmd}" in
1197 fullrelease)
1198 check_args "${globalcmd}" "$#" "0" || exit 1
1199 cmds="${fullcmds}"
1201 create)
1202 check_args "${globalcmd}" "$#" "0" || exit 1
1203 check_args "create" "$#" "0" || exit 1
1205 cmds=""
1206 cmd_allowed "verify" ${fullcmds} && {
1207 cmds="${cmds} verify"
1209 cmds="${cmds} create"
1210 cmd_allowed "whatsnew" ${fullcmds} && {
1211 cmds="${cmds} whatsnew"
1213 cmd_allowed "patch" ${fullcmds} && {
1214 cmds="${cmds} patch"
1216 cmds="${cmds} check"
1217 cmd_allowed "announcement" ${fullcmds} && {
1218 cmds="${cmds} announcement"
1220 next_cmd="push"
1222 push)
1223 check_args "${globalcmd}" "$#" "1" || exit 1
1224 tagname="$1"
1225 cmds="check push"
1226 next_cmd="upload"
1228 upload)
1229 check_args "${globalcmd}" "$#" "1" || exit 1
1230 tagname="$1"
1231 cmds="check upload"
1232 cmd_allowed "announce" ${fullcmds} && {
1233 next_cmd="announce"
1236 announce)
1237 check_args "${globalcmd}" "$#" "1" || exit 1
1238 tagname="$1"
1239 cmds="check announce"
1242 usage
1243 echo "Unknown command ${globalcmd}"
1244 exit 1
1246 esac
1248 TMPDIR="release.$$"
1249 CLEANUP_DIRS="${CLEANUP_DIRS} ${TMPDIR}"
1250 umask 0077
1251 mkdir "${TMPDIR}"
1252 umask 0022
1254 for cmd in ${cmds}; do
1255 echo "Starting subcommand[${cmd}]"
1256 ${cmd}_release || {
1257 echo "Failed subcommand[${cmd}]"
1258 exit 1
1260 echo "Finished subcommand[${cmd}]"
1261 done
1263 test -d "${TMPDIR}" && {
1264 rm -rf "${TMPDIR}" || {
1265 echo "failed to remove ${TMPDIR}"
1269 test -n "${next_cmd}" && {
1270 echo "Continue with '$0 ${product} ${next_cmd} ${tagname}'."
1273 trap - INT QUIT TERM EXIT
1275 exit 0