00c758a1abb039a9f533f551b8e97a8105df257e
[tools.git] / release-tools / stage-release.sh
1 #! /bin/bash -e
2 # Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 # This is the most shell agnostic way to specify that POSIX rules.
10 POSIXLY_CORRECT=1
11
12 # Force C locale because some commands (like date +%b) relies
13 # on the current locale.
14 export LC_ALL=C
15
16 usage () {
17     cat <<EOF
18 Usage: stage-release.sh [ options ... ]
19
20 --alpha         Start or increase the "alpha" pre-release tag.
21 --next-beta     Switch to the "beta" pre-release tag after alpha release.
22                 It can only be given with --alpha.
23 --beta          Start or increase the "beta" pre-release tag.
24 --final         Get out of "alpha" or "beta" and make a final release.
25                 Implies --branch.
26
27 --branch        Create a release branch 'openssl-{major}.{minor}',
28                 where '{major}' and '{minor}' are the major and minor
29                 version numbers.
30
31 --clean-worktree
32                 Expect the current worktree to be clean, and uses it directly.
33                 This implies the current branch of the worktree will be updated.
34
35 --branch-fmt=<fmt>
36                 Format for branch names.
37                 Default is "%b" for the release branch.
38 --tag-fmt=<fmt> Format for tag names.
39                 Default is "%t" for the release tag.
40
41 --reviewer=<id> The reviewer of the commits.
42 --local-user=<keyid>
43                 For the purpose of signing tags and tar files, use this
44                 key (default: use the default e-mail address’ key).
45
46 --staging-address=<address>
47                 The staging location to upload release files to (default:
48                 upload@dev.openssl.org)
49 --no-upload     Don't upload the staging release files.
50 --no-update     Don't perform 'make update' and 'make update-fips-checksums'.
51 --quiet         Really quiet, only the final output will still be output.
52 --verbose       Verbose output.
53 --debug         Include debug output.  Implies --no-upload.
54 --porcelain     Give the output in an easy-to-parse format for scripts.
55
56 --force         Force execution
57
58 --help          This text
59 --manual        The manual
60
61 If none of --alpha, --beta, or --final are given, this script tries to
62 figure out the next step.
63 EOF
64     exit 0
65 }
66
67 # Set to one of 'major', 'minor', 'alpha', 'beta' or 'final'
68 next_method=
69 next_method2=
70
71 do_branch=false
72 warn_branch=false
73
74 do_upload=true
75 do_update=true
76
77 clean_worktree=false
78
79 default_branch_fmt='OSSL--%b--%v'
80 default_tag_fmt='%t'
81
82 ECHO=echo
83 DEBUG=:
84 VERBOSE=:
85 git_quiet=-q
86 do_porcelain=false
87
88 force=false
89
90 do_help=false
91 do_manual=false
92
93 tagkey=' -s'
94 gpgkey=
95 reviewers=
96
97 staging_address=upload@dev.openssl.org
98
99 TEMP=$(getopt -l 'alpha,next-beta,beta,final' \
100               -l 'branch' \
101               -l 'clean-worktree' \
102               -l 'branch-fmt:,tag-fmt:' \
103               -l 'reviewer:' \
104               -l 'local-user:' \
105               -l 'staging-address:' \
106               -l 'no-upload,no-update' \
107               -l 'quiet,verbose,debug' \
108               -l 'porcelain' \
109               -l 'force' \
110               -l 'help,manual' \
111               -n stage-release.sh -- - "$@")
112 eval set -- "$TEMP"
113 while true; do
114     case $1 in
115     --alpha | --beta | --final )
116         next_method=$(echo "x$1" | sed -e 's|^x--||')
117         if [ -z "$next_method2" ]; then
118             next_method2=$next_method
119         fi
120         shift
121         if [ "$next_method" = 'final' ]; then
122             do_branch=true
123         fi
124         ;;
125     --next-beta )
126         next_method2=$(echo "x$1" | sed -e 's|^x--next-||')
127         shift
128         ;;
129     --branch )
130         do_branch=true
131         warn_branch=true
132         shift
133         ;;
134     --clean-worktree )
135         clean_worktree=true
136         default_branch_fmt='%b'
137         default_tag_fmt='%t'
138         shift
139         ;;
140     --branch-fmt )
141         shift
142         branch_fmt="$1"
143         shift
144         ;;
145     --tag-fmt )
146         shift
147         tag_fmt="$1"
148         shift
149         ;;
150     --reviewer )
151         reviewers="$reviewers $1=$2"
152         shift
153         shift
154         ;;
155     --local-user )
156         shift
157         tagkey=" -u $1"
158         gpgkey=" -u $1"
159         shift
160         ;;
161     --staging-address )
162         shift
163         staging_address="$1"
164         shift
165         ;;
166     --no-upload )
167         do_upload=false
168         shift
169         ;;
170     --no-update )
171         do_update=false
172         shift
173         ;;
174     --quiet )
175         ECHO=:
176         VERBOSE=:
177         shift
178         ;;
179     --verbose )
180         ECHO=echo
181         VERBOSE=echo
182         git_quiet=
183         shift
184         ;;
185     --debug )
186         DEBUG=echo
187         do_upload=false
188         shift
189         ;;
190     --porcelain )
191         do_porcelain=true
192         shift
193         ;;
194     --force )
195         force=true
196         shift
197         ;;
198     --help )
199         usage
200         exit 0
201         ;;
202     --manual )
203         sed -e '1,/^### BEGIN MANUAL/d' \
204             -e '/^### END MANUAL/,$d' \
205             < "$0" \
206             | pod2man \
207             | man -l -
208         exit 0
209         ;;
210     -- )
211         shift
212         break
213         ;;
214     * )
215         echo >&2 "Unknown option $1"
216         shift
217         exit 1
218         ;;
219     esac
220 done
221
222 if [ -z "$branch_fmt" ]; then branch_fmt="$default_branch_fmt"; fi
223 if [ -z "$tag_fmt" ]; then tag_fmt="$default_tag_fmt"; fi
224
225 $DEBUG >&2 "DEBUG: \$next_method=$next_method"
226 $DEBUG >&2 "DEBUG: \$next_method2=$next_method2"
227
228 $DEBUG >&2 "DEBUG: \$do_branch=$do_branch"
229
230 $DEBUG >&2 "DEBUG: \$do_upload=$do_upload"
231 $DEBUG >&2 "DEBUG: \$do_update=$do_update"
232 $DEBUG >&2 "DEBUG: \$DEBUG=$DEBUG"
233 $DEBUG >&2 "DEBUG: \$VERBOSE=$VERBOSE"
234 $DEBUG >&2 "DEBUG: \$git_quiet=$git_quiet"
235
236 case "$next_method+$next_method2" in
237     major+major | minor+minor )
238         # These are expected
239         ;;
240     alpha+alpha | alpha+beta | beta+beta | final+final | + | +beta )
241         # These are expected
242         ;;
243     * )
244         echo >&2 "Internal option error ($next_method, $next_method2)"
245         exit 1
246         ;;
247 esac
248
249 # Verbosity feed for certain commands
250 VERBOSITY_FIFO=/tmp/openssl-$$.fifo
251 mkfifo -m 600 $VERBOSITY_FIFO
252 ( cat $VERBOSITY_FIFO | while read L; do $VERBOSE "> $L"; done ) &
253 exec 42>$VERBOSITY_FIFO
254 trap "exec 42>&-; rm $VERBOSITY_FIFO" 0 2
255
256 # Setup ##############################################################
257
258 # Check that we have the scripts that define functions we use
259 RELEASE_AUX=$(cd $(dirname $0)/release-aux; pwd)
260 found=true
261 for fn in "$RELEASE_AUX/release-version-fn.sh" \
262           "$RELEASE_AUX/release-state-fn.sh" \
263           "$RELEASE_AUX/string-fn.sh" \
264           "$RELEASE_AUX/upload-fn.sh"; do
265     if ! [ -f "$fn" ]; then
266         echo >&2 "'$fn' is missing"
267         found=false
268     fi
269 done
270 if ! $found; then
271     exit 1
272 fi
273
274 # Load version functions
275 . $RELEASE_AUX/release-version-fn.sh
276 . $RELEASE_AUX/release-state-fn.sh
277 # Load string manipulation functions
278 . $RELEASE_AUX/string-fn.sh
279 # Load upload backend functions
280 . $RELEASE_AUX/upload-fn.sh
281
282 # Make sure we're in the work directory, and remember it
283 if HERE=$(git rev-parse --show-toplevel); then
284     :
285 else
286     echo >&2 "Not in a git worktree"
287     exit 1
288 fi
289
290 # Make sure that it's a plausible OpenSSL work tree, by checking
291 # that a version file is found
292 get_version
293
294 if [ -z "$VERSION_FILE" ]; then
295     echo >&2 "Couldn't find OpenSSL version data"
296     exit 1
297 fi
298
299 # Make sure it's a branch we recognise
300 orig_branch=$(git rev-parse --abbrev-ref HEAD)
301 if (echo "$orig_branch" \
302         | grep -E -q \
303                -e '^master$' \
304                -e '^OpenSSL_[0-9]+_[0-9]+_[0-9]+[a-z]*-stable$' \
305                -e '^openssl-[0-9]+\.[0-9]+$'); then
306     :
307 elif $force; then
308     :
309 else
310     echo >&2 "Not in master or any recognised release branch"
311     echo >&2 "Please 'git checkout' an appropriate branch"
312     exit 1
313 fi
314 orig_HEAD=$(git rev-parse HEAD)
315
316 # Make sure that we have fixup scripts for all the files that need
317 # to be modified for a release.  We trust this, because we're not
318 # going to change versioning scheme in the middle of a release.
319 save_IFS=$IFS
320 IFS=';'
321 found=true
322 for fn in $RELEASE_FILES; do
323     for file in "$RELEASE_AUX/fixup-$fn-release.pl" \
324                 "$RELEASE_AUX/fixup-$fn-postrelease.pl"; do
325         if ! [ -f "$file" ]; then
326             echo >&2 "'$file' is missing"
327             found=false
328         fi
329     done
330 done
331 IFS=$save_IFS
332 if ! $found; then
333     exit 1
334 fi
335
336 # We turn staging_address into a few variables, which can be used
337 # by backends that must understand a subset of the SFTP commands
338 staging_directory=
339 staging_backend=
340 case "$staging_address" in
341     *:* )
342         # Something with a colon is interpreted as the typical SCP
343         # location.  We reinterpret that in our terms
344         staging_directory="${staging_address#*:}"
345         staging_address="${staging_address%%:*}"
346         staging_backend=sftp
347         ;;
348     *@* )
349         staging_backend=sftp
350         ;;
351     sftp://?*/* | sftp://?* )
352         # First, remove the URI scheme
353         staging_address="${staging_address#sftp://}"
354         # Now we know that we have a host, followed by a slash, followed by
355         # a directory spec.  If there is no slash, there's no directory.
356         staging_directory="${staging_address#*/}"
357         if [ "$staging_directory" = "$staging_address" ]; then
358             # There was nothing with a slash to remove, so no directory.
359             staging_directory=
360         fi
361         staging_address="${staging_address%%/*}"
362         staging_backend=sftp
363         ;;
364     sftp:* )
365         echo >&2 "Invalid staging address $staging_address"
366         exit 1
367         ;;
368     * )
369         if $do_upload && ! [ -d "$staging_address" ]; then
370            echo >&2 "Not an existing directory: $staging_address"
371            exit 1
372         fi
373         staging_backend=file
374         ;;
375 esac
376
377 # Initialize #########################################################
378
379 $ECHO "== Initializing work tree"
380
381 release_clone=
382 if $clean_worktree; then
383     if [ -n "$(git status -s)" ]; then
384         echo >&2 "You've specified --clean-worktree, but your worktree is unclean"
385         exit 1
386     fi
387 else
388     # Generate a cloned directory name
389     release_clone="$orig_branch-release-tmp"
390
391     $ECHO "== Work tree will be in $release_clone"
392
393     # Make a clone in a subdirectory and move there
394     if ! [ -d "$release_clone" ]; then
395         $VERBOSE "== Cloning to $release_clone"
396         git clone $git_quiet -b "$orig_branch" -o parent . "$release_clone"
397     fi
398     cd "$release_clone"
399 fi
400
401 get_version
402
403 # Branches to start from.  The release branch is where the changes for the
404 # release are made, and the update branch is where the post-release changes are
405 # made.  If --branch was given and is relevant, they should be different (and
406 # the update branch should be 'master'), otherwise they should be the same.
407 orig_update_branch="$orig_branch"
408 orig_release_branch="$(std_branch_name)"
409
410 # among others, we only create a release branch if the patch number is zero
411 if [ "$orig_update_branch" = "$orig_release_branch" ] \
412        || [ -n "$PATCH" -a "$PATCH" != 0 ]; then
413     if $do_branch && $warn_branch; then
414         echo >&2 "Warning! We're already in a release branch; --branch ignored"
415     fi
416     do_branch=false
417 fi
418
419 if $do_branch; then
420     if [ "$orig_update_branch" != "master" ]; then
421         echo >&2 "--branch is invalid unless the current branch is 'master'"
422         exit 1
423     fi
424     # No need to check if $orig_update_branch and $orig_release_branch differ,
425     # 'cause the code a few lines up guarantee that if they are the same,
426     # $do_branch becomes false
427 else
428     # In this case, the computed release branch may differ from the update branch,
429     # even if it shouldn't...  this is the case when alpha or beta releases are
430     # made in the master branch, which is perfectly ok.  Therefore, simply reset
431     # the release branch to be the same as the update branch and carry on.
432     orig_release_branch="$orig_update_branch"
433 fi
434
435 # Check that the current branch is still on the same branch as our parent repo,
436 # or on a release branch
437 current_branch=$(git rev-parse --abbrev-ref HEAD)
438 if [ "$current_branch" = "$orig_update_branch" ]; then
439     :
440 elif [ "$current_branch" = "$orig_release_branch" ]; then
441     :
442 else
443     # It is an error to end up here.  Let's try to figure out what went wrong
444
445     if $clean_worktree; then
446         # We should never get here.  If we do, something is incorrect in
447         # the code above.
448         echo >&2 "Unexpected current branch: $current_branch"
449     else
450         echo >&2 "The cloned sub-directory '$release_clone' is on a branch"
451         if [ "$orig_update_branch" = "$orig_release_branch" ]; then
452             echo >&2 "other than '$orig_update_branch'."
453         else
454             echo >&2 "other than '$orig_update_branch' or '$orig_release_branch'."
455         fi
456         echo >&2 "Please 'cd \"$(pwd)\"; git checkout $orig_update_branch'"
457     fi
458     exit 1
459 fi
460
461 SOURCEDIR=$(pwd)
462 $DEBUG >&2 "DEBUG: Source directory is $SOURCEDIR"
463
464 # Release ############################################################
465
466 # We always expect to start from a state of development
467 if [ "$TYPE" != 'dev' ]; then
468     upstream=$(git rev-parse --abbrev-ref '@{u}' 2>/dev/null || echo 'HEAD^')
469     if $clean_worktree; then
470         cat >&2 <<EOF
471 Not in a development branch.
472
473 Have a look at the git log, it may be that a previous crash left it in
474 an intermediate state and that need to drop the top commit:
475
476 git reset --hard $upstream
477 # WARNING! LOOK BEFORE YOU ACT, KNOW WHAT YOU DO
478 EOF
479     else
480         cat >&2 <<EOF
481 Not in a development branch.
482
483 Have a look at the git log in $release_clone, it may be that
484 a previous crash left it in an intermediate state and that need to drop
485 the top commit:
486
487 (cd $release_clone; git reset --hard $upstream)
488 # WARNING! LOOK BEFORE YOU ACT, KNOW WHAT YOU DO
489 EOF
490     fi
491     exit 1
492 fi
493
494 # Make the update branch name according to our current data
495 update_branch=$(format_string "$branch_fmt" \
496                               "b=$orig_update_branch" \
497                               "t=" \
498                               "v=$FULL_VERSION")
499     
500 # Update the version information.  This won't save anything anywhere, yet,
501 # but does check for possible next_method errors before we do bigger work.
502 next_release_state "$next_method"
503
504 # Make the release tag and branch name according to our current data
505 tag=$(format_string "$tag_fmt" \
506                     "b=$orig_release_branch" \
507                     "t=$(std_tag_name)" \
508                     "v=$FULL_VERSION")
509 release_branch=$(format_string "$branch_fmt" \
510                                "b=$orig_release_branch" \
511                                "t=$(std_tag_name)" \
512                                "v=$FULL_VERSION")
513     
514 # Create a update branch, unless it's the same as our current branch
515 if [ "$update_branch" != "$orig_update_branch" ]; then
516     $VERBOSE "== Creating a local update branch and switch to it: $update_branch"
517     git checkout $git_quiet -b "$update_branch"
518 fi
519
520 $ECHO "== Configuring OpenSSL for update and release.  This may take a bit of time"
521
522 ./Configure cc >&42
523
524 $VERBOSE "== Checking source file updates and fips checksums"
525
526 make update >&42
527 # As long as we're doing an alpha release, we can have symbols without specific
528 # numbers assigned. In a beta or final release, all symbols MUST have an
529 # assigned number.
530 if [ "$next_method" != 'alpha' ] && grep -q '^renumber *:' Makefile; then
531     make renumber >&42
532 fi
533 if grep -q '^update-fips-checksums *:' Makefile; then
534     make update-fips-checksums >&42
535 fi
536
537 if [ -n "$(git status --porcelain --untracked-files=no --ignore-submodules=all)" ]; then
538     $VERBOSE "== Committing updates"
539     git add -u
540     git commit $git_quiet -m $'make update\n\nRelease: yes'
541     if [ -n "$reviewers" ]; then
542         addrev --release --nopr $reviewers
543     fi
544 fi
545
546 # Create a update branch, unless it's the same as the update branch
547 if [ "$release_branch" != "$update_branch" ]; then
548     $VERBOSE "== Creating a local release branch and switch to it: $release_branch"
549     git checkout $git_quiet -b "$release_branch"
550 fi
551
552 # Write the version information we updated
553 set_version
554
555 release="$FULL_VERSION"
556 if [ -n "$PRE_LABEL" ]; then
557     release_text="$SERIES$_BUILD_METADATA $PRE_LABEL $PRE_NUM"
558     announce_template=openssl-announce-pre-release.tmpl
559 else
560     release_text="$release"
561     announce_template=openssl-announce-release.tmpl
562 fi
563 $VERBOSE "== Updated version information to $release"
564
565 $VERBOSE "== Updating files with release date for $release : $RELEASE_DATE"
566 (
567     IFS=';'
568     for file in $RELEASE_FILES; do
569         fixup="$RELEASE_AUX/fixup-$(basename "$file")-release.pl"
570         $VERBOSE "> $file"
571         RELEASE="$release" RELEASE_TEXT="$release_text" RELEASE_DATE="$RELEASE_DATE" \
572                perl -pi $fixup $file
573     done
574 )
575
576 $VERBOSE "== Committing updates and tagging"
577 git add -u
578 git commit $git_quiet -m "Prepare for release of $release_text"$'\n\nRelease: yes'
579 if [ -n "$reviewers" ]; then
580     addrev --release --nopr $reviewers
581 fi
582 $ECHO "Tagging release with tag $tag.  You may need to enter a pass phrase"
583 git tag$tagkey "$tag" -m "OpenSSL $release release tag"
584
585 tarfile=openssl-$release.tar
586 tgzfile=$tarfile.gz
587 announce=openssl-$release.txt
588
589 $ECHO "== Generating tar, hash and announcement files.  This make take a bit of time"
590
591 $VERBOSE "== Making tarfile: $tgzfile"
592
593 # Unfortunately, some tarball generators do verbose output on STDERR...  for
594 # good reason, but it means we don't display errors unless --verbose
595 (
596     if [ -f ./util/mktar.sh ]; then
597         ./util/mktar.sh --tarfile="../$tarfile" 2>&1
598     else
599         make DISTTARVARS=TARFILE="../$tarfile" dist 2>&1
600     fi
601 ) | while read L; do $VERBOSE "> $L"; done
602
603 if ! [ -f "../$tgzfile" ]; then
604     echo >&2 "Where did the tarball end up? (../$tgzfile)"
605     exit 1
606 fi
607
608 $VERBOSE "== Generating checksums: $tgzfile.sha1 $tgzfile.sha256"
609 openssl sha1 < "../$tgzfile" | \
610     (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha1"
611 openssl sha256 < "../$tgzfile" | \
612     (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha256"
613 length=$(wc -c < "../$tgzfile")
614 sha1hash=$(cat "../$tgzfile.sha1")
615 sha256hash=$(cat "../$tgzfile.sha256")
616
617 $VERBOSE "== Generating announcement text: $announce"
618 # Hack the announcement template
619 cat "$RELEASE_AUX/$announce_template" \
620     | sed -e "s|\\\$release_text|$release_text|g" \
621           -e "s|\\\$release|$release|g" \
622           -e "s|\\\$series|$SERIES|g" \
623           -e "s|\\\$label|$PRE_LABEL|g" \
624           -e "s|\\\$tarfile|$tgzfile|" \
625           -e "s|\\\$length|$length|" \
626           -e "s|\\\$sha1hash|$sha1hash|" \
627           -e "s|\\\$sha256hash|$sha256hash|" \
628     | perl -p "$RELEASE_AUX/fix-title.pl" \
629     > "../$announce"
630
631 $VERBOSE "== Generating signatures: $tgzfile.asc $announce.asc"
632 rm -f "../$tgzfile.asc" "../$announce.asc"
633 $ECHO "Signing the release files.  You may need to enter a pass phrase"
634 gpg$gpgkey --use-agent -sba "../$tgzfile"
635 gpg$gpgkey --use-agent -sta --clearsign "../$announce"
636
637 if ! $clean_worktree; then
638     # Push everything to the parent repo
639     $VERBOSE "== Push what we have to the parent repository"
640     git push --follow-tags parent HEAD
641 fi
642
643 staging_files=( "$tgzfile" "$tgzfile.sha1" "$tgzfile.sha256"
644                 "$tgzfile.asc" "$announce.asc" )
645
646 if $do_upload; then
647     $ECHO "== Upload tar, hash and announcement files to staging location"
648 fi
649
650 (
651     # With sftp, the progress meter is enabled by default,
652     # so we turn it off unless --verbose was given
653     if [ "$VERBOSE" == ':' ]; then
654         echo "progress"
655     fi
656     if [ -n "$staging_directory" ]; then
657         echo "cd $staging_directory"
658     fi
659     for uf in "${staging_files[@]}"; do
660         echo "put ../$uf"
661     done
662 ) | upload_backend_$staging_backend "$staging_address" $do_upload
663
664 # Post-release #######################################################
665
666 # Reset the files to their pre-release contents.  This doesn't affect
667 # HEAD, but simply set all the files in a state that 'git revert -n HEAD'
668 # would have given, but without the artifacts that 'git revert' adds.
669 #
670 # This allows all the post-release fixup scripts to perform from the
671 # same point as the release fixup scripts, hopefully making them easier
672 # to write.  This also makes the same post-release fixup scripts easier
673 # to run when --branch has been used, as they will be run both on the
674 # release branch and on the update branch, essentially from the same
675 # state for affected files.
676 $VERBOSE "== Reset all files to their pre-release contents"
677 git reset $git_quiet HEAD^ -- .
678 git checkout -- .
679
680 prev_release_text="$release_text"
681 prev_release_date="$RELEASE_DATE"
682
683 next_release_state "$next_method2"
684 set_version
685
686 release="$FULL_VERSION"
687 release_text="$VERSION$_BUILD_METADATA"
688 if [ -n "$PRE_LABEL" ]; then
689     release_text="$SERIES$_BUILD_METADATA $PRE_LABEL $PRE_NUM"
690 fi
691 $VERBOSE "== Updated version information to $release"
692
693 $VERBOSE "== Updating files for $release :"
694 (
695     IFS=';'
696     for file in $RELEASE_FILES; do
697         fixup="$RELEASE_AUX/fixup-$(basename "$file")-postrelease.pl"
698         $VERBOSE "> $file"
699         RELEASE="$release" RELEASE_TEXT="$release_text" \
700                PREV_RELEASE_TEXT="$prev_release_text" \
701                PREV_RELEASE_DATE="$prev_release_date" \
702                perl -pi $fixup $file
703     done
704 )
705
706 $VERBOSE "== Committing updates"
707 git add -u
708 git commit $git_quiet -m "Prepare for $release_text"$'\n\nRelease: yes'
709 if [ -n "$reviewers" ]; then
710     addrev --release --nopr $reviewers
711 fi
712
713 if ! $clean_worktree; then
714     # Push everything to the parent repo
715     $VERBOSE "== Push what we have to the parent repository"
716     git push parent HEAD
717 fi
718
719 if [ "$release_branch" != "$update_branch" ]; then
720     $VERBOSE "== Going back to the update branch $update_branch"
721     git checkout $git_quiet "$update_branch"
722
723     get_version
724     next_release_state "minor"
725     set_version
726
727     release="$FULL_VERSION"
728     release_text="$SERIES$_BUILD_METADATA"
729     $VERBOSE "== Updated version information to $release"
730
731     $VERBOSE "== Updating files for $release :"
732     (
733         IFS=';'
734         for file in $RELEASE_FILES; do
735             fixup="$RELEASE_AUX/fixup-$(basename "$file")-postrelease.pl"
736             $VERBOSE "> $file"
737             RELEASE="$release" RELEASE_TEXT="$release_text" \
738                    perl -pi $fixup $file
739         done
740     )
741
742     $VERBOSE "== Committing updates"
743     git add -u
744     git commit $git_quiet -m "Prepare for $release_text"$'\n\nRelease: yes'
745     if [ -n "$reviewers" ]; then
746         addrev --release --nopr $reviewers
747     fi
748 fi
749
750 if ! $clean_worktree; then
751     # Push everything to the parent repo
752     $VERBOSE "== Push what we have to the parent repository"
753     git push parent HEAD
754 fi
755
756 # Done ###############################################################
757
758 $VERBOSE "== Done"
759
760 cd $HERE
761 if $do_porcelain; then
762     if [ -n "$release_clone" ]; then
763         echo "clone_directory='$release_clone'"
764     fi
765     echo "update_branch='$update_branch'"
766     if [ "$update_branch" != "$orig_update_branch" ]; then
767         echo "final_update_branch='$orig_update_branch'"
768     fi
769     if [ "$release_branch" != "$update_branch" ]; then
770         echo "release_branch='$release_branch'"
771         if [ "$release_branch" != "$orig_release_branch" ]; then
772             echo "final_release_branch='$orig_release_branch'"
773         fi
774     fi
775     echo "release_tag='$tag'"
776     echo "upload_files='${staging_files[@]}'"
777 else
778     cat <<EOF
779
780 ======================================================================
781 The release is done, and involves a few files and commits for you to
782 deal with.  Everything you need has been pushed to your repository,
783 please see instructions that follow.
784 ======================================================================
785
786 EOF
787
788     if $do_upload; then
789         cat <<EOF
790 The following files were uploaded to $staging_address, please ensure they
791 are dealt with appropriately:
792
793 EOF
794     else
795         cat <<EOF
796 The following files were generated for upload, please deal with them
797 appropriately:
798
799 EOF
800     fi
801     for uf in "${staging_files[@]}"; do
802         echo "    $uf"
803     done
804     cat <<EOF
805
806 ----------------------------------------------------------------------
807
808 EOF
809
810     if [ "$release_branch" != "$update_branch" ]; then
811         cat <<EOF
812 You need to prepare the main repository with a new branch, '$release_branch'.
813 That is done directly in the server's bare repository like this:
814
815     git branch $release_branch $orig_HEAD
816
817 EOF
818     fi
819     if [ "$update_branch" != "$orig_update_branch" ] \
820        && [ "$release_branch" != "$update_branch" ]; then
821         # "Normal" scenario with --branch
822         cat <<EOF
823 A release tag and two branches have been added to your local repository.
824 Push them to github, make PRs from them and have them approved.
825
826     Update branch: $update_branch
827     Release branch: $release_branch
828     Tag: $tag
829
830 When merging everything into the main repository, do it like this:
831
832     git push git@github.openssl.org:openssl/openssl.git \\
833         $release_branch:$orig_release_branch
834     git push git@github.openssl.org:openssl/openssl.git \\
835         $update_branch:$orig_update_branch
836     git push git@github.openssl.org:openssl/openssl.git \\
837         $tag
838 EOF
839     elif [ "$update_branch" != "$orig_update_branch" ]; then
840         # "Normal" scenario without --branch
841         cat <<EOF
842 A release tag and a release/update branch have been added to your local
843 repository.  Push them to github, make PRs from them and have them
844 approved.
845
846     Release/update branch: $update_branch
847     Tag: $tag
848
849 When merging everything into the main repository, do it like this:
850
851     git push git@github.openssl.org:openssl/openssl.git \\
852         $update_branch:$orig_update_branch
853     git push git@github.openssl.org:openssl/openssl.git \\
854         $tag
855 EOF
856     elif [ "$release_branch" != "$update_branch" ]; then
857         # --clean-worktree and --branch scenario
858         cat <<EOF
859 A release tag and a release branch has been added to your repository,
860 and the current branch has been updated.  Push them to github, make
861 PRs from them and have them approved:
862
863     Updated branch: $update_branch
864     Release branch: $release_branch
865     Tag: $tag
866
867 When merging everything into the main repository, do it like this:
868
869     git push git@github.openssl.org:openssl/openssl.git \\
870         $release_branch:$orig_release_branch
871     git push git@github.openssl.org:openssl/openssl.git \\
872         $update_branch
873     git push git@github.openssl.org:openssl/openssl.git \\
874         $tag
875 EOF
876     else
877         # --clean-worktree without --branch scenario
878         cat <<EOF
879 A release tag has been added to your local repository, and the current
880 branch has been updated.  Push them to github, make PRs from them and
881 have them approved.
882
883     Release/update branch: $update_branch
884     Tag: $tag
885
886 When merging everything into the main repository, do it like this:
887
888     git push git@github.openssl.org:openssl/openssl.git \\
889         $update_branch
890     git push git@github.openssl.org:openssl/openssl.git \\
891         $tag
892 EOF
893     fi
894
895     cat <<EOF
896
897 ----------------------------------------------------------------------
898 EOF
899
900     cat <<EOF
901
902 When everything is done, or if something went wrong and you want to start
903 over, simply clean away temporary things left behind:
904 EOF
905     if [ -n "$release_clone" ]; then
906         cat <<EOF
907 The release worktree:
908
909     rm -rf $release_clone
910 EOF
911     fi
912     cat <<EOF
913
914 Additional branches:
915
916 EOF
917     if [ "$release_branch" != "$update_branch" ]; then
918         cat <<EOF
919     git branch -D $release_branch
920 EOF
921     fi
922     if [ "$update_branch" != "$orig_update_branch" ]; then
923         cat <<EOF
924     git branch -D $update_branch
925 EOF
926     fi
927 fi
928
929 exit 0
930
931 # cat is inconsequential, it's only there to fend off zealous shell parsers
932 # that parse all the way here.
933 cat <<EOF
934 ### BEGIN MANUAL
935 =pod
936
937 =head1 NAME
938
939 stage-release.sh - OpenSSL release staging script
940
941 =head1 SYNOPSIS
942
943 B<stage-release.sh>
944 [
945 B<--alpha> |
946 B<--next-beta> |
947 B<--beta> |
948 B<--final> |
949 B<--branch> |
950 B<--clean-worktree> |
951 B<--branch-fmt>=I<fmt> |
952 B<--tag-fmt>=I<fmt> |
953 B<--local-user>=I<keyid> |
954 B<--reviewer>=I<id> |
955 B<--staging-address>=I<address> |
956 B<--no-upload> |
957 B<--no-update> |
958 B<--quiet> |
959 B<--verbose> |
960 B<--debug> |
961 B<--porcelain> |
962 B<--help> |
963 B<--manual>
964 ]
965
966 =head1 DESCRIPTION
967
968 B<stage-release.sh> creates an OpenSSL release, given current worktree
969 conditions.  It will refuse to work unless the current branch is C<master>
970 or a release branch (see L</RELEASE BRANCHES AND TAGS> below for a
971 discussion on those).
972
973 B<stage-release.sh> tries to be smart and figure out the next release if no
974 hints are given through options, and will exit with an error in ambiguous
975 cases.
976
977 B<stage-release.sh> normally finishes off with instructions on what to do
978 next.  When B<--porcelain> is given, it finishes off with script friendly
979 data instead, see the description of that option.  When finishing commands
980 are given, they must be followed exactly.
981
982 B<stage-release.sh> normally leaves behind a clone of the local repository,
983 as a subdirectory in the current worktree, as well as an extra branch with
984 the results of running this script in the local repository.  This extra
985 branch is useful to create a pull request from, which will also be mentioned
986 at the end of the run of B<stage-release.sh>.  This local clone subdirectory
987 as well as this extra branch can safely be removed after all instructions
988 have been successfully followed.
989
990 When the option B<--clean-worktree> is given, B<stage-release.sh> has a
991 different behaviour.  In this case, it doesn't create that clone or any
992 extra branch, and it will update the current branch of the worktree
993 directly.  This is useful when it's desirable to push the changes directly
994 to a remote repository without having to go through a pull request and
995 approval process.
996
997 =head1 OPTIONS
998
999 =over 4
1000
1001 =item B<--alpha>, B<--beta>
1002
1003 Set the state of this branch to indicate that alpha or beta releases are
1004 to be done.
1005
1006 B<--alpha> is only acceptable if the I<PATCH> version number is zero and
1007 the current state is "in development" or that alpha releases are ongoing.
1008
1009 B<--beta> is only acceptable if the I<PATCH> version number is zero and
1010 that alpha or beta releases are ongoing.
1011
1012 =item B<--next-beta>
1013
1014 Use together with B<--alpha> to switch to beta releases after the current
1015 release is done.
1016
1017 =item B<--final>
1018
1019 Set the state of this branch to indicate that regular releases are to be
1020 done.  This is only valid if alpha or beta releases are currently ongoing.
1021
1022 This implies B<--branch>.
1023
1024 =item B<--branch>
1025
1026 Create a branch specific for the I<SERIES> release series, if it doesn't
1027 already exist, and switch to it when making the release files.  The exact
1028 branch name will be C<< openssl-I<SERIES> >>.
1029
1030 =item B<--clean-worktree>
1031
1032 This indicates that the current worktree is clean and can be acted on
1033 directly, instead of creating a clone of the local repository or creating
1034 any extra branch.
1035
1036 =item B<--branch-fmt>=I<fmt>
1037
1038 =item B<--tag-fmt>=I<fmt>
1039
1040 Format for branch and tag names.  This can be used to tune the names of
1041 branches and tags that are updated or added by this script.
1042
1043 I<fmt> can include printf-like formating directives:
1044
1045 =over 4
1046
1047 =item %b
1048
1049 is replaced with a branch name.  This branch name is usually the current
1050 branch of the current repository, but may also be the default release
1051 branch name that is generated when B<--branch> is given.
1052
1053 =item %t
1054
1055 is replaced with the generated release tag name.
1056
1057 =item %v
1058
1059 is replaced with the version number.  The exact version number varies
1060 through the process of this script.
1061
1062 =back
1063
1064 This script uses the following defaults:
1065
1066 =over 4
1067
1068 =item * Without B<--clean-worktree>
1069
1070 For branches: C<OSSL--%b--%v>
1071
1072 For tags: C<%t>
1073
1074 =item * With B<--clean-worktree>
1075
1076 For branches: C<%b>
1077
1078 For tags: C<%t>
1079
1080 =back
1081
1082 =item B<--reviewer>=I<id>
1083
1084 Add I<id> to the set of reviewers for the commits performed by this script.
1085 Multiple reviewers are allowed.
1086
1087 If no reviewer is given, you will have to run C<addrev> manually, which
1088 means retagging a release commit manually as well.
1089
1090 =item B<--local-user>=I<keyid>
1091
1092 Use I<keyid> as the local user for C<git tag> and for signing with C<gpg>.
1093
1094 If not given, then the default e-mail address' key is used.
1095
1096 =item B<--staging-address>=I<address>
1097
1098 The staging location that the release files are to be uploaded to.
1099 Supported values are:
1100
1101 =over 4
1102
1103 =item -
1104
1105 an existing local directory
1106
1107 =item -
1108
1109 something that can be interpreted as an SCP/SFTP address.  In this case,
1110 SFTP will always be used.  Typical SCP remote file specs will be translated
1111 into something that makes sense for SFTP.
1112
1113 =back
1114
1115 The default staging address is C<upload@dev.openssl.org>.
1116
1117 =item B<--no-upload>
1118
1119 Don't upload the release files to the staging location.
1120
1121 =item B<--no-update>
1122
1123 Don't run C<make update> and C<make update-fips-checksums>.
1124
1125 =item B<--quiet>
1126
1127 Really quiet, only bare necessity output, which is the final instructions,
1128 or should the B<--porcelain> option be used, only that output.
1129
1130 messages appearing on standard error will still be shown, but should be
1131 fairly minimal.
1132
1133 =item B<--verbose>
1134
1135 Verbose output.
1136
1137 =item B<--debug>
1138
1139 Display extra debug output.  Implies B<--no-upload>
1140
1141 =item B<--porcelain>
1142
1143 Give final output in an easy-to-parse format for scripts.  The output comes
1144 in a form reminicent of shell variable assignments.  Currently supported are:
1145
1146 =over 4
1147
1148 =item B<clone_directory>=I<dir>
1149
1150 The directory for the clone that this script creates.  This is not given when
1151 the option B<--clean-worktree> is used.
1152
1153 =item B<update_branch>=I<branch>
1154
1155 The temporary update branch.  This is always given.
1156
1157 =item B<final_update_branch>=I<branch>
1158
1159 The final update branch that the temporary update branch should end up being
1160 merged into.  This is not given when the option B<--clean-worktree> is used.
1161
1162 =item B<release_branch>=I<branch>
1163
1164 The temporary release branch, only given if it differs from the update branch
1165 (i.e. B<--branch> was given or implied).
1166
1167 =item B<final_release_branch>=I<branch>
1168
1169 The final release branch that the temporary release branch should end up being
1170 merged into.  This is only given if it differs from the final update branch
1171 (i.e. B<--branch> was given or implied).
1172
1173 =item B<release_tag>=I<tag>
1174
1175 The release tag.  This is always given.
1176
1177 =item B<upload_files>='I<files>'
1178
1179 The space separated list of files that were or would have been uploaded
1180 to the staging location (depending on the presence of B<--no-upload>).
1181
1182 =back
1183
1184 =item B<--force>
1185
1186 Force execution.  Precisely, the check that the current branch is C<master>
1187 or a release branch is not done.
1188
1189 =item B<--help>
1190
1191 Display a quick help text and exit.
1192
1193 =item B<--manual>
1194
1195 Display this manual and exit.
1196
1197 =back
1198
1199 =head1 RELEASE BRANCHES AND TAGS
1200
1201 Prior to OpenSSL 3.0, the release branches were named
1202 C<< OpenSSL_I<SERIES>-stable >>, and the release tags were named
1203 C<< OpenSSL_I<VERSION> >> for regular releases, or
1204 C<< OpenSSL_I<VERSION>-preI<n> >> for pre-releases.
1205
1206 From OpenSSL 3.0 ongoing, the release branches are named
1207 C<< openssl-I<SERIES> >>, and the release tags are named
1208 C<< openssl-I<VERSION> >> for regular releases, or
1209 C<< openssl-I<VERSION>-alphaI<n> >> for alpha releases
1210 and C<< openssl-I<VERSION>-betaI<n> >> for beta releases.
1211
1212 B<stage-release.sh> recognises both forms.
1213
1214 =head1 VERSION AND STATE
1215
1216 With OpenSSL 3.0, all the version and state information is in the file
1217 F<VERSION.dat>, where the following variables are used and changed:
1218
1219 =over 4
1220
1221 =item B<MAJOR>, B<MINOR>, B<PATCH>
1222
1223 The three part of the version number.
1224
1225 =item B<PRE_RELEASE_TAG>
1226
1227 The indicator of the current state of the branch.  The value may be one pf:
1228
1229 =over 4
1230
1231 =item C<dev>
1232
1233 This branch is "in development".  This is typical for the C<master> branch
1234 unless there are ongoing alpha or beta releases.
1235
1236 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
1237
1238 This branch has alpha releases going on.  C<< alphaI<n>-dev >> is what
1239 should normally be seen in the git workspace, indicating that
1240 C<< alphaI<n> >> is in development.  C<< alphaI<n> >> is what should be
1241 found in the alpha release tar file.
1242
1243 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
1244
1245 This branch has beta releases going on.  The details are otherwise exactly
1246 as for alpha.
1247
1248 =item I<no value>
1249
1250 This is normally not seen in the git workspace, but should always be what's
1251 found in the tar file of a regular release.
1252
1253 =back
1254
1255 =item B<BUILD_METADATA>
1256
1257 Extra build metadata to be used by anyone for their own purposes.
1258
1259 =item B<RELEASE_DATE>
1260
1261 This is normally empty in the git workspace, but should always have the
1262 release date in the tar file of any release.
1263
1264 =back
1265
1266 =head1 COPYRIGHT
1267
1268 Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
1269
1270 Licensed under the Apache License 2.0 (the "License").  You may not use
1271 this file except in compliance with the License.  You can obtain a copy
1272 in the file LICENSE in the source distribution or at
1273 L<https://www.openssl.org/source/license.html>.
1274
1275 =cut
1276 ### END MANUAL
1277 EOF