s3: smbd: Cause SMB2_OP_FLUSH to go synchronous in a compound anywhere but the last...
[Samba.git] / script / release.sh
blob45e9206005c0846f201d35e111d507f44a2f8c33
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() {
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
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
42 check_args() {
43 local cmd="$1"
44 local got_args="$2"
45 local take_args="$3"
47 test x"${got_args}" = x"${take_args}" || {
48 usage
49 echo "cmd[${cmd}] takes ${take_args} instead of ${got_args}"
50 return 1
53 return 0
56 min_args() {
57 local cmd="$1"
58 local got_args="$2"
59 local min_args="$3"
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
67 return 0
70 min_args "$0" "$#" "2"
72 product="$1"
73 globalcmd="$2"
74 shift 2
75 oldtagname=""
76 tagname=""
77 patchfile=""
78 cmds=""
79 next_cmd=""
81 require_tagname() {
82 min_args "${FUNCNAME}" "$#" "1" || return 1
83 local cmd="$1"
85 test -n "${tagname}" || {
86 echo "cmd[${cmd}] requires '\${tagname}' variable to be set"
87 return 1
90 local name=$(echo "${tagname}" | cut -d '-' -f1)
91 test x"${name}" = x"${productbase}" || {
92 echo "Invalid tagname[${tgzname}]"
93 return 1
96 return 0
99 cmd_allowed() {
100 min_args "${FUNCNAME}" "$#" "2" || return 1
101 local cmd="$1"
102 shift 1
104 echo "$@" | grep -q "\<${cmd}\>" || {
105 return 1
108 return 0
111 verify_samba_rc() {
112 check_args "${FUNCNAME}" "$#" "0" || return 1
114 test -f VERSION || {
115 echo "VERSION doesn't exist"
116 return 1
119 grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
120 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
121 return 1
124 grep -q '^SAMBA_VERSION_RC_RELEASE=' VERSION || {
125 echo "SAMBA_VERSION_RC_RELEASE= missing"
126 return 1
129 grep -q '^SAMBA_VERSION_RC_RELEASE=$' VERSION && {
130 echo "SAMBA_VERSION_RC_RELEASE= missing the rc version"
131 return 1
134 return 0
137 load_samba_stable_versions() {
138 check_args "${FUNCNAME}" "$#" "0" || return 1
140 test -n "${version-}" && {
141 return 0
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)
148 version="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.${SAMBA_VERSION_RELEASE}"
149 tagname="${productbase}-${version}"
151 test ${SAMBA_VERSION_RELEASE} -gt 0 || {
152 return 0
155 oldversion="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.$(expr ${SAMBA_VERSION_RELEASE} - 1)"
156 oldtagname="${productbase}-${oldversion}"
157 patchfile="${productbase}-${oldversion}-${version}.diffs"
159 return 0
162 verify_samba_stable() {
163 check_args "${FUNCNAME}" "$#" "0" || return 1
165 test -f VERSION || {
166 echo "VERSION doesn't exist"
167 return 1
170 grep -q 'SAMBA_VERSION_IS_GIT_SNAPSHOT=no' VERSION || {
171 echo "SAMBA_VERSION_IS_GIT_SNAPSHOT is not 'no'"
172 return 1
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
192 done
194 load_samba_stable_versions
196 test -n "${oldtagname}" || {
197 return 0
200 local verify_out="${TMPDIR}/verify-${oldtagname}.out"
202 echo "Verifying oldtagname: ${oldtagname}"
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
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
218 echo "Verifying ${oldtagname}.tar.gz and ${oldtagname}.tar.asc"
220 test -f "${oldtagname}.tar.gz" || {
221 echo "${oldtagname}.tar.gz does not exist"
222 return 1
225 test -f "${oldtagname}.tar.asc" || {
226 echo "${oldtagname}.tar.asc does not exist"
227 return 1
230 zcat "${oldtagname}.tar.gz" | gpg --verify "${oldtagname}.tar.asc" - 2>${verify_out} || {
231 echo "Failed to verify ${oldtagname}.tar.asc"
232 return 1
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
242 return 0
245 verify_release() {
246 check_args "${FUNCNAME}" "$#" "0" || return 1
248 test -n "${verify_fn}" || {
249 echo "verify_fn variable empty"
250 return 1
253 echo "Running ${verify_fn}"
254 ${verify_fn}
257 create_release() {
258 check_args "${FUNCNAME}" "$#" "0" || return 1
260 echo "Releasing product ${product}"
262 test -n "${tagname}" && {
263 git tag -l "${tagname}" | grep -q "${tagname}" && {
264 echo "tagname[${tagname}] already exist"
265 return 1
268 local _tgzname="${tagname}.tar.gz"
269 test -e "${_tgzname}" && {
270 echo "_tgzname[${_tgzname}] already exist"
271 return 1
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
281 CLEANUP_FILES="${CLEANUP_FILES} ${tgzname}"
283 local name=$(echo "${tgzname}" | cut -d '-' -f1)
284 test x"${name}" = x"${productbase}" || {
285 echo "Invalid tgzname[${tgzname}]"
286 return 1
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
296 tagname="${_tagname}"
298 local tarname=$(basename ${tgzname} .gz)
299 echo "Tarball: ${tarname}"
300 gunzip -f ${tgzname} || {
301 echo "Failed to decompress tarball ${tarname}"
302 return 1
304 test -f "${tarname}" || {
305 echo "Failed to decompress tarball ${tarname}"
306 return 1
308 CLEANUP_FILES="${CLEANUP_FILES} ${tarname}"
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
315 CLEANUP_TAGS="${CLEANUP_TAGS} ${tagname}"
317 echo "Signing ${tarname} => ${tarname}.asc"
318 rm -f "${tarname}.asc"
319 gpg --default-key "${GPG_KEYID}" --detach-sign --armor ${tarname} || {
320 return 1
322 test -f "${tarname}.asc" || {
323 echo "Failed to create signature ${tarname}.asc"
324 return 1
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
334 return 0
337 patch_release() {
338 check_args "${FUNCNAME}" "$#" "0" || return 1
339 require_tagname "${FUNCNAME}"
341 test -n "${patchfile}" || {
342 return 0
345 local oldpwd=$(pwd)
346 echo "Generating ${patchfile}"
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
356 CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}"
357 mv "${TMPDIR}/${patchfile}" "${patchfile}" || {
358 echo "failed cmd[mv ${TMPDIR}/${patchfile} ${patchfile}]"
359 return 1
362 echo "Signing ${patchfile} => ${patchfile}.asc"
363 rm -f "${patchfile}.asc"
364 CLEANUP_FILES="${CLEANUP_FILES} ${patchfile}.asc"
365 gpg --default-key "${GPG_KEYID}" --detach-sign --armor ${patchfile} || {
366 return 1
368 test -f "${patchfile}.asc" || {
369 echo "Failed to create signature ${patchfile}.asc"
370 return 1
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
380 return 0
383 whatsnew_release() {
384 check_args "${FUNCNAME}" "$#" "0" || return 1
385 require_tagname "${FUNCNAME}"
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"
391 return 0
394 check_nopatch() {
395 check_args "${FUNCNAME}" "$#" "0" || return 1
396 require_tagname "${FUNCNAME}"
398 local verify_out="${TMPDIR}/verify-${oldtagname}.out"
400 echo "Verifying tagname: ${tagname}"
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
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
415 echo "Verifying ${tagname}.tar.gz and ${tagname}.tar.asc"
417 test -f "${tagname}.tar.gz" || {
418 echo "${tagname}.tar.gz does not exist"
419 return 1
422 test -f "${tagname}.tar.asc" || {
423 echo "${tagname}.tar.asc does not exist"
424 return 1
427 zcat "${tagname}.tar.gz" | gpg --verify "${tagname}.tar.asc" - 2>${verify_out} || {
428 echo "Failed to verify ${tagname}.tar.asc"
429 return 1
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
438 ls -la ${tagname}.*
440 return 0
443 check_samba_stable() {
444 check_args "${FUNCNAME}" "$#" "0" || return 1
445 require_tagname "${FUNCNAME}"
447 load_samba_stable_versions
449 local verify_out="${TMPDIR}/verify-${oldtagname}.out"
451 echo "Verifying tagname: ${tagname}"
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
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
466 echo "Verifying ${tagname}.tar.gz and ${tagname}.tar.asc"
468 test -f "${tagname}.tar.gz" || {
469 echo "${tagname}.tar.gz does not exist"
470 return 1
473 test -f "${tagname}.tar.asc" || {
474 echo "${tagname}.tar.asc does not exist"
475 return 1
478 zcat "${tagname}.tar.gz" | gpg --verify "${tagname}.tar.asc" - 2>${verify_out} || {
479 echo "Failed to verify ${tagname}.tar.asc"
480 return 1
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
489 test -n "${patchfile}" || {
490 ls -lart ${tagname}.*
491 return 0
494 echo "Verifying ${patchfile}.gz and ${patchfile}.asc"
496 test -f "${patchfile}.gz" || {
497 echo "${patchfile}.gz does not exist"
498 return 1
501 test -f "${patchfile}.asc" || {
502 echo "${patchfile}.asc does not exist"
503 return 1
506 zcat "${patchfile}.gz" | gpg --verify "${patchfile}.asc" - 2>${verify_out} || {
507 echo "Failed to verify ${patchfile}.asc"
508 return 1
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
517 ls -lart ${tagname}.* ${patchfile}.*
518 return 0
521 check_release() {
522 check_args "${FUNCNAME}" "$#" "0" || return 1
524 test -n "${check_fn}" || {
525 echo "check_fn variable empty"
526 return 1
529 echo "Running ${check_fn}"
530 ${check_fn}
533 push_release() {
534 check_args "${FUNCNAME}" "$#" "0" || return 1
535 require_tagname "${FUNCNAME}"
537 echo "Push git tag ${tagname} to '${repo_url}'"
538 git push "${repo_url}" "refs/tags/${tagname}:refs/tags/${tagname}" || {
539 return 1
542 return 0
545 upload_nopatch() {
546 check_args "${FUNCNAME}" "$#" "0" || return 1
547 require_tagname "${FUNCNAME}"
549 echo "Upload ${tagname}.* to '${upload_url}'"
550 rsync -Pav --delay-updates ${tagname}.* "${upload_url}/" || {
551 return 1
553 rsync ${upload_url}/${tagname}.*
555 return 0
558 upload_samba_stable() {
559 check_args "${FUNCNAME}" "$#" "0" || return 1
560 require_tagname "${FUNCNAME}"
562 load_samba_stable_versions
564 local release_url="${upload_url}samba/stable/"
565 local patch_url="${upload_url}samba/patches/"
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
572 rsync ${release_url}/${tagname}.tar.*
574 test -n "${patchfile}" || {
575 return 0
578 echo "Upload ${patchfile}.* to '${patch_url}'"
579 ls -lart ${patchfile}.*
580 rsync -Pav --delay-updates ${patchfile}.* "${patch_url}/" || {
581 return 1
583 rsync ${patch_url}/${patchfile}.*
585 return 0
588 upload_release() {
589 check_args "${FUNCNAME}" "$#" "0" || return 1
591 test -n "${upload_fn}" || {
592 echo "upload_fn variable empty"
593 return 1
596 echo "Running ${upload_fn}"
597 ${upload_fn}
600 announcement_samba_rc() {
601 check_args "${FUNCNAME}" "$#" "0" || return 1
602 require_tagname "${FUNCNAME}"
604 test -f "${tagname}.WHATSNEW.txt" || {
605 echo "${tagname}.WHATSNEW.txt does not exist"
606 return 1
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
617 rcname="first"
620 rcname="second"
623 rcname="third"
626 rcname="fourth"
629 rcname="fifth"
631 esac
633 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
635 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
636 } > announce.${tagname}.to.txt
638 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
640 echo "[Announce] Samba ${version} Available for Download"
641 } > announce.${tagname}.subject.txt
643 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
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
668 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
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
675 local headlinefile="posted_news/@UTCTIME@.${version}.headline.html"
676 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.headline.html"
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
683 local bodyfile="posted_news/@UTCTIME@.${version}.body.html"
684 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.body.html"
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
700 local webrepo="${TMPDIR}/webrepo"
702 mkdir "${webrepo}" || {
703 return 1
705 git -C "${webrepo}" init || {
706 return 1
709 mkdir -p "$(dirname ${webrepo}/${headlinefile})" || {
710 return 1
712 cp -a "announce.${tagname}.headline.html" "${webrepo}/${headlinefile}" || {
713 return 1
716 mkdir -p "$(dirname ${webrepo}/${bodyfile})" || {
717 return 1
719 cp -a "announce.${tagname}.body.html" "${webrepo}/${bodyfile}" || {
720 return 1
723 git -C "${webrepo}" add "${headlinefile}" "${bodyfile}" || {
724 return 1
726 git -C "${webrepo}" commit --signoff --message "NEWS[${version}]: Samba ${version} Available for Download" || {
727 return 1
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
734 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
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
761 ls -lart announce.${tagname}.*
762 return 0
765 announcement_samba_stable() {
766 check_args "${FUNCNAME}" "$#" "0" || return 1
767 require_tagname "${FUNCNAME}"
769 load_samba_stable_versions
771 test -f "${tagname}.tar.gz" || {
772 echo "${tagname}.tar.gz does not exist"
773 return 1
776 local release_url="${download_url}samba/stable/"
777 local patch_url="${download_url}samba/patches/"
779 echo "extract WHATSNEW.txt"
780 tar xf ${tagname}.tar.gz --to-stdout ${tagname}/WHATSNEW.txt > ${TMPDIR}/WHATSNEW.txt
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
791 releasename="first"
794 releasename="latest"
796 esac
798 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.to.txt"
800 echo "samba-announce@lists.samba.org, samba@lists.samba.org, samba-technical@lists.samba.org"
801 } > announce.${tagname}.to.txt
803 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.subject.txt"
805 echo "[Announce] Samba ${version} Available for Download"
806 } > announce.${tagname}.subject.txt
808 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mail.txt"
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)
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 \))
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
846 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.mutt-arguments.txt"
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
853 local htmlfile="history/${tagname}.html"
854 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.html"
856 local tmp=$(cat ${TMPDIR}/WHATSNEW.txt | grep -n '^Reporting bugs & Development Discussion' | head -1 | cut -d ':' -f1)
857 local lines=$(expr ${tmp} - 2)
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">'
863 echo "<head>"
864 echo "<title>Samba ${version} - Release Notes</title>"
865 echo "</head>"
867 echo "<body>"
868 echo "<H2>Samba ${version} Available for Download</H2>"
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>"
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>"
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>"
901 echo "</body>"
902 echo "</html>"
903 } > announce.${tagname}.html
905 local headlinefile="posted_news/@UTCTIME@.${version}.headline.html"
906 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.headline.html"
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
913 local bodyfile="posted_news/@UTCTIME@.${version}.body.html"
914 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.body.html"
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."
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
933 local webrepo="${TMPDIR}/webrepo"
935 mkdir "${webrepo}" || {
936 return 1
938 git -C "${webrepo}" init || {
939 return 1
942 mkdir -p "$(dirname ${webrepo}/${htmlfile})" || {
943 return 1
945 cp -a "announce.${tagname}.html" "${webrepo}/${htmlfile}" || {
946 return 1
949 mkdir -p "$(dirname ${webrepo}/${headlinefile})" || {
950 return 1
952 cp -a "announce.${tagname}.headline.html" "${webrepo}/${headlinefile}" || {
953 return 1
956 mkdir -p "$(dirname ${webrepo}/${bodyfile})" || {
957 return 1
959 cp -a "announce.${tagname}.body.html" "${webrepo}/${bodyfile}" || {
960 return 1
963 git -C "${webrepo}" add "${htmlfile}" "${headlinefile}" "${bodyfile}" || {
964 return 1
966 git -C "${webrepo}" commit --signoff --message "NEWS[${version}]: Samba ${version} Available for Download" || {
967 return 1
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
974 CLEANUP_FILES="${CLEANUP_FILES} announce.${tagname}.todo.txt"
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
1001 ls -lart announce.${tagname}.*
1002 return 0
1005 announcement_release() {
1006 check_args "${FUNCNAME}" "$#" "0" || return 1
1008 test -n "${announcement_fn}" || {
1009 echo "announcement_fn variable empty"
1010 return 1
1013 echo "Running ${announcement_fn}"
1014 ${announcement_fn}
1017 announce_release() {
1018 check_args "${FUNCNAME}" "$#" "0" || return 1
1019 require_tagname "${FUNCNAME}"
1021 test -f "announce.${tagname}.todo.txt" || {
1022 echo "announce.${tagname}.todo.txt does not exist"
1023 return 1
1026 cat announce.${tagname}.todo.txt
1027 return 0
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>'
1036 test -z "${GPG_KEYID-}" && {
1037 GPG_KEYID='4793916113084025'
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}/"
1046 check_fn="check_nopatch"
1047 upload_fn="upload_nopatch"
1048 fullcmds="create check push upload"
1050 samba-rc)
1051 test -z "${GPG_USER-}" && {
1052 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1055 test -z "${GPG_KEYID-}" && {
1056 GPG_KEYID='AA99442FB680B620'
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/"
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"
1071 samba-stable)
1072 test -z "${GPG_USER-}" && {
1073 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1076 test -z "${GPG_KEYID-}" && {
1077 GPG_KEYID='AA99442FB680B620'
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/"
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"
1093 TODO-samba-security)
1094 test -z "${GPG_USER-}" && {
1095 GPG_USER='Samba Distribution Verification Key <samba-bugs@samba.org>'
1098 test -z "${GPG_KEYID-}" && {
1099 GPG_KEYID='AA99442FB680B620'
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/"
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"
1117 usage
1118 echo "Unknown product ${product}"
1119 exit 1
1120 esac
1122 pushd ${srcdir} || {
1123 echo "srcdir[${srcdir}] does not exist"
1124 exit 1
1127 trap_handler() {
1128 echo ""
1129 echo "ERROR: cleaning up"
1130 echo ""
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}"
1139 done
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}"
1148 done
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}"
1157 done
1160 CLEANUP_TAGS=""
1161 CLEANUP_FILES=""
1162 CLEANUP_DIRS=""
1163 trap trap_handler INT QUIT TERM EXIT
1165 cmd_allowed "${globalcmd}" fullrelease ${fullcmds} || {
1166 usage
1167 echo "command[${globalcmd}] not supported for product[${product}]"
1168 exit 1
1171 case "${globalcmd}" in
1172 fullrelease)
1173 check_args "${globalcmd}" "$#" "0" || exit 1
1174 cmds="${fullcmds}"
1176 create)
1177 check_args "${globalcmd}" "$#" "0" || exit 1
1178 check_args "create" "$#" "0" || exit 1
1180 cmds=""
1181 cmd_allowed "verify" ${fullcmds} && {
1182 cmds="${cmds} verify"
1184 cmds="${cmds} create"
1185 cmd_allowed "whatsnew" ${fullcmds} && {
1186 cmds="${cmds} whatsnew"
1188 cmd_allowed "patch" ${fullcmds} && {
1189 cmds="${cmds} patch"
1191 cmds="${cmds} check"
1192 cmd_allowed "announcement" ${fullcmds} && {
1193 cmds="${cmds} announcement"
1195 next_cmd="push"
1197 push)
1198 check_args "${globalcmd}" "$#" "1" || exit 1
1199 tagname="$1"
1200 cmds="check push"
1201 next_cmd="upload"
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"
1211 announce)
1212 check_args "${globalcmd}" "$#" "1" || exit 1
1213 tagname="$1"
1214 cmds="check announce"
1217 usage
1218 echo "Unknown command ${globalcmd}"
1219 exit 1
1221 esac
1223 TMPDIR="release.$$"
1224 CLEANUP_DIRS="${CLEANUP_DIRS} ${TMPDIR}"
1225 umask 0077
1226 mkdir "${TMPDIR}"
1227 umask 0022
1229 for cmd in ${cmds}; do
1230 echo "Starting subcommand[${cmd}]"
1231 ${cmd}_release || {
1232 echo "Failed subcommand[${cmd}]"
1233 exit 1
1235 echo "Finished subcommand[${cmd}]"
1236 done
1238 test -d "${TMPDIR}" && {
1239 rm -rf "${TMPDIR}" || {
1240 echo "failed to remove ${TMPDIR}"
1244 test -n "${next_cmd}" && {
1245 echo "Continue with '$0 ${product} ${next_cmd} ${tagname}'."
1248 trap - INT QUIT TERM EXIT
1250 exit 0