When checking for make update changes, only check tracked files
[tools.git] / release-tools / 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: 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 --reviewer=<id> The reviewer of the commits.
32 --local-user=<keyid>
33                 For the purpose of signing tags and tar files, use this
34                 key (default: use the default e-mail address’ key).
35
36 --upload-address=<address>
37                 The location to upload release files to (default:
38                 upload@dev.openssl.org)
39 --no-upload     Don't upload the release files.
40 --no-update     Don't perform 'make update' and 'make update-fips-checksums'.
41 --verbose       Verbose output.
42 --debug         Include debug output.  Implies --no-upload.
43
44 --force         Force execution
45
46 --help          This text
47 --manual        The manual
48
49 If none of --alpha, --beta, or --final are given, this script tries to
50 figure out the next step.
51 EOF
52     exit 0
53 }
54
55 # Set to one of 'major', 'minor', 'alpha', 'beta' or 'final'
56 next_method=
57 next_method2=
58
59 do_branch=false
60 warn_branch=false
61
62 do_clean=true
63 do_upload=true
64 do_update=true
65 DEBUG=:
66 VERBOSE=:
67 git_quiet=-q
68
69 force=false
70
71 do_help=false
72 do_manual=false
73
74 tagkey=' -s'
75 gpgkey=
76 reviewers=
77
78 upload_address=upload@dev.openssl.org
79
80 TEMP=$(getopt -l 'alpha,next-beta,beta,final' \
81               -l 'branch' \
82               -l 'upload-address:' \
83               -l 'no-upload,no-update' \
84               -l 'verbose,debug' \
85               -l 'local-user:' \
86               -l 'reviewer:' \
87               -l 'force' \
88               -l 'help,manual' \
89               -n release.sh -- - "$@")
90 eval set -- "$TEMP"
91 while true; do
92     case $1 in
93     --alpha | --beta | --final )
94         next_method=$(echo "x$1" | sed -e 's|^x--||')
95         if [ -z "$next_method2" ]; then
96             next_method2=$next_method
97         fi
98         shift
99         if [ "$next_method" = 'final' ]; then
100             do_branch=true
101         fi
102         ;;
103     --next-beta )
104         next_method2=$(echo "x$1" | sed -e 's|^x--next-||')
105         shift
106         ;;
107     --branch )
108         do_branch=true
109         warn_branch=true
110         shift
111         ;;
112     --upload-address )
113         shift
114         upload_address="$1"
115         shift
116         ;;
117     --no-upload )
118         do_upload=false
119         shift
120         ;;
121     --no-update )
122         do_update=false
123         shift
124         ;;
125     --verbose )
126         VERBOSE=echo
127         git_quiet=
128         shift
129         ;;
130     --debug )
131         DEBUG=echo
132         do_upload=false
133         shift
134         ;;
135     --local-user )
136         shift
137         tagkey=" -u $1"
138         gpgkey=" -u $1"
139         shift
140         ;;
141     --reviewer )
142         reviewers="$reviewers $1=$2"
143         shift
144         shift
145         ;;
146     --force )
147         force=true
148         shift
149         ;;
150     --help )
151         usage
152         exit 0
153         ;;
154     --manual )
155         sed -e '1,/^### BEGIN MANUAL/d' \
156             -e '/^### END MANUAL/,$d' \
157             < "$0" \
158             | pod2man \
159             | man -l -
160         exit 0
161         ;;
162     -- )
163         shift
164         break
165         ;;
166     * )
167         echo >&2 "Unknown option $1"
168         shift
169         exit 1
170         ;;
171     esac
172 done
173
174 $DEBUG >&2 "DEBUG: \$next_method=$next_method"
175 $DEBUG >&2 "DEBUG: \$next_method2=$next_method2"
176
177 $DEBUG >&2 "DEBUG: \$do_branch=$do_branch"
178
179 $DEBUG >&2 "DEBUG: \$do_upload=$do_upload"
180 $DEBUG >&2 "DEBUG: \$do_update=$do_update"
181 $DEBUG >&2 "DEBUG: \$DEBUG=$DEBUG"
182 $DEBUG >&2 "DEBUG: \$VERBOSE=$VERBOSE"
183 $DEBUG >&2 "DEBUG: \$git_quiet=$git_quiet"
184
185 case "$next_method+$next_method2" in
186     major+major | minor+minor )
187         # These are expected
188         ;;
189     alpha+alpha | alpha+beta | beta+beta | final+final | + | +beta )
190         # These are expected
191         ;;
192     * )
193         echo >&2 "Internal option error ($next_method, $next_method2)"
194         exit 1
195         ;;
196 esac
197
198 # Verbosity feed for certain commands
199 VERBOSITY_FIFO=/tmp/openssl-$$.fifo
200 mkfifo -m 600 $VERBOSITY_FIFO
201 ( cat $VERBOSITY_FIFO | while read L; do $VERBOSE "> $L"; done ) &
202 exec 42>$VERBOSITY_FIFO
203 trap "exec 42>&-; rm $VERBOSITY_FIFO" 0 2
204
205 # Setup ##############################################################
206
207 # Check that we have the scripts that define functions we use
208 RELEASE_AUX=$(cd $(dirname $0)/release-aux; pwd)
209 found=true
210 for fn in "$RELEASE_AUX/release-version-fn.sh" \
211           "$RELEASE_AUX/release-state-fn.sh" \
212           "$RELEASE_AUX/upload-fn.sh"; do
213     if ! [ -f "$fn" ]; then
214         echo >&2 "'$fn' is missing"
215         found=false
216     fi
217 done
218 if ! $found; then
219     exit 1
220 fi
221
222 # Load version functions
223 . $RELEASE_AUX/release-version-fn.sh
224 . $RELEASE_AUX/release-state-fn.sh
225 # Load upload backend functions
226 . $RELEASE_AUX/upload-fn.sh
227
228 # Make sure we're in the work directory, and remember it
229 if HERE=$(git rev-parse --show-toplevel); then
230     :
231 else
232     echo >&2 "Not in a git worktree"
233     exit 1
234 fi
235
236 # Make sure that it's a plausible OpenSSL work tree, by checking
237 # that a version file is found
238 get_version
239
240 if [ -z "$VERSION_FILE" ]; then
241     echo >&2 "Couldn't find OpenSSL version data"
242     exit 1
243 fi
244
245 # Make sure it's a branch we recognise
246 orig_branch=$(git rev-parse --abbrev-ref HEAD)
247 if (echo "$orig_branch" \
248         | grep -E -q \
249                -e '^master$' \
250                -e '^OpenSSL_[0-9]+_[0-9]+_[0-9]+[a-z]*-stable$' \
251                -e '^openssl-[0-9]+\.[0-9]+$'); then
252     :
253 elif $force; then
254     :
255 else
256     echo >&2 "Not in master or any recognised release branch"
257     echo >&2 "Please 'git checkout' an appropriate branch"
258     exit 1
259 fi
260 orig_HEAD=$(git rev-parse HEAD)
261
262 # Make sure that we have fixup scripts for all the files that need
263 # to be modified for a release.  We trust this, because we're not
264 # going to change versioning scheme in the middle of a release.
265 save_IFS=$IFS
266 IFS=';'
267 found=true
268 for fn in $RELEASE_FILES; do
269     for file in "$RELEASE_AUX/fixup-$fn-release.pl" \
270                 "$RELEASE_AUX/fixup-$fn-postrelease.pl"; do
271         if ! [ -f "$file" ]; then
272             echo >&2 "'$file' is missing"
273             found=false
274         fi
275     done
276 done
277 IFS=$save_IFS
278 if ! $found; then
279     exit 1
280 fi
281
282 # We turn upload_address into a few variables, which can be used
283 # by backends that must understand a subset of the SFTP commands
284 upload_directory=
285 upload_backend=
286 case "$upload_address" in
287     *:* )
288         # Something with a colon is interpreted as the typical SCP
289         # location.  We reinterpret that in our terms
290         upload_directory="${upload_address#*:}"
291         upload_address="${upload_address%%:*}"
292         upload_backend=sftp
293         ;;
294     *@* )
295         upload_backend=sftp
296         ;;
297     sftp://?*/* | sftp://?* )
298         # First, remove the URI scheme
299         upload_address="${upload_address#sftp://}"
300         # Now we know that we have a host, followed by a slash, followed by
301         # a directory spec.  If there is no slash, there's no directory.
302         upload_directory="${upload_address#*/}"
303         if [ "$upload_directory" = "$upload_address" ]; then
304             # There was nothing with a slash to remove, so no directory.
305             upload_directory=
306         fi
307         upload_address="${upload_address%%/*}"
308         upload_backend=sftp
309         ;;
310     sftp:* )
311         echo >&2 "Invalid upload address $upload_address"
312         exit 1
313         ;;
314     * )
315         if $do_upload && ! [ -d "$upload_address" ]; then
316            echo >&2 "Not an existing directory: $upload_address"
317            exit 1
318         fi
319         upload_backend=file
320         ;;
321 esac
322
323 # Initialize #########################################################
324
325 echo "== Initializing work tree"
326
327 # Generate a cloned directory name
328 release_clone="$orig_branch-release-tmp"
329
330 echo "== Work tree will be in $release_clone"
331
332 # Make a clone in a subdirectory and move there
333 if ! [ -d "$release_clone" ]; then
334     $VERBOSE "== Cloning to $release_clone"
335     git clone $git_quiet -b "$orig_branch" -o parent . "$release_clone"
336 fi
337 cd "$release_clone"
338
339 get_version
340
341 # Branches we will work with.  The release branch is where we make the
342 # changes for the release, the update branch is where we make the post-
343 # release changes
344 update_branch="$orig_branch"
345 release_branch="$(std_branch_name)"
346
347 # among others, we only create a release branch if the patch number is zero
348 if [ "$update_branch" = "$release_branch" ] \
349        || [ -z "$PATCH" ] \
350        || [ $PATCH -ne 0 ]; then
351     if $do_branch && $warn_branch; then
352         echo >&2 "Warning! We're already in a release branch; --branch ignored"
353     fi
354     do_branch=false
355 fi
356
357 if ! $do_branch; then
358     release_branch="$update_branch"
359 fi
360
361 # Branches we create for PRs
362 branch_version="$VERSION${PRE_LABEL:+-$PRE_LABEL$PRE_NUM}"
363 tmp_update_branch="OSSL--$update_branch--$branch_version"
364 tmp_release_branch="OSSL--$release_branch--$branch_version"
365
366 # Check that we're still on the same branch as our parent repo, or on a
367 # release branch
368 current_branch=$(git rev-parse --abbrev-ref HEAD)
369 if [ "$current_branch" = "$update_branch" ]; then
370     :
371 elif [ "$current_branch" = "$release_branch" ]; then
372     :
373 else
374     echo >&2 "The cloned sub-directory '$release_clone' is on a branch"
375     if [ "$update_branch" = "$release_branch" ]; then
376         echo >&2 "other than '$update_branch'."
377     else
378         echo >&2 "other than '$update_branch' or '$release_branch'."
379     fi
380     echo >&2 "Please 'cd \"$(pwd)\"; git checkout $update_branch'"
381     exit 1
382 fi
383
384 SOURCEDIR=$(pwd)
385 $DEBUG >&2 "DEBUG: Source directory is $SOURCEDIR"
386
387 # Release ############################################################
388
389 # We always expect to start from a state of development
390 if [ "$TYPE" != 'dev' ]; then
391     echo >&2 "Not in a development branch"
392     echo >&2 "Have a look at the git log in $release_clone, it may be that"
393     echo >&2 "a previous crash left it in an intermediate state and that"
394     echo >&2 "need to drop the top commit:"
395     echo >&2 ""
396     echo >&2 "(cd $release_clone; git reset --hard HEAD^)"
397     echo >&2 "# WARNING! LOOK BEFORE YOU ACT"
398     exit 1
399 fi
400
401 # Update the version information.  This won't save anything anywhere, yet,
402 # but does check for possible next_method errors before we do bigger work.
403 next_release_state "$next_method"
404
405 # Create our temporary release branch
406 $VERBOSE "== Creating a local release branch: $tmp_release_branch"
407 git checkout $git_quiet -b "$tmp_release_branch"
408
409 echo "== Configuring OpenSSL for update and release.  This may take a bit of time"
410
411 ./Configure cc >&42
412
413 $VERBOSE "== Checking source file updates and fips checksums"
414
415 make update >&42
416 # As long as we're doing an alpha release, we can have symbols without specific
417 # numbers assigned. In a beta or final release, all symbols MUST have an
418 # assigned number.
419 if [ "$next_method" != 'alpha' ] && grep -q '^renumber *:' Makefile; then
420     make renumber >&42
421 fi
422 if grep -q '^update-fips-checksums *:' Makefile; then
423     make update-fips-checksums >&42
424 fi
425
426 if [ -n "$(git status --porcelain --untracked-files=no --ignore-submodules=all)" ]; then
427     $VERBOSE "== Committing updates"
428     git add -u
429     git commit $git_quiet -m $'make update\n\nRelease: yes'
430     if [ -n "$reviewers" ]; then
431         addrev --release --nopr $reviewers
432     fi
433 fi
434
435 # Create our temporary update branch, if it's not the release branch.
436 # This is used in post-release below
437 if $do_branch; then
438     $VERBOSE "== Creating a local update branch: $tmp_update_branch"
439     git branch $git_quiet "$tmp_update_branch"
440 fi
441
442 # Write the version information we updated
443 set_version
444
445 release="$FULL_VERSION"
446 if [ -n "$PRE_LABEL" ]; then
447     release_text="$SERIES$_BUILD_METADATA $PRE_LABEL $PRE_NUM"
448     announce_template=openssl-announce-pre-release.tmpl
449 else
450     release_text="$release"
451     announce_template=openssl-announce-release.tmpl
452 fi
453 tag="$(std_tag_name)"
454 $VERBOSE "== Updated version information to $release"
455
456 $VERBOSE "== Updating files with release date for $release : $RELEASE_DATE"
457 (
458     IFS=';'
459     for file in $RELEASE_FILES; do
460         fixup="$RELEASE_AUX/fixup-$(basename "$file")-release.pl"
461         $VERBOSE "> $file"
462         RELEASE="$release" RELEASE_TEXT="$release_text" RELEASE_DATE="$RELEASE_DATE" \
463                perl -pi $fixup $file
464     done
465 )
466
467 $VERBOSE "== Committing updates and tagging"
468 git add -u
469 git commit $git_quiet -m "Prepare for release of $release_text"$'\n\nRelease: yes'
470 if [ -n "$reviewers" ]; then
471     addrev --release --nopr $reviewers
472 fi
473 echo "Tagging release with tag $tag.  You may need to enter a pass phrase"
474 git tag$tagkey "$tag" -m "OpenSSL $release release tag"
475
476 tarfile=openssl-$release.tar
477 tgzfile=$tarfile.gz
478 announce=openssl-$release.txt
479
480 echo "== Generating tar, hash and announcement files.  This make take a bit of time"
481
482 $VERBOSE "== Making tarfile: $tgzfile"
483
484 # Unfortunately, some tarball generators do verbose output on STDERR...  for
485 # good reason, but it means we don't display errors unless --verbose
486 (
487     if [ -f ./util/mktar.sh ]; then
488         ./util/mktar.sh --tarfile="../$tarfile" 2>&1
489     else
490         make DISTTARVARS=TARFILE="../$tarfile" dist 2>&1
491     fi
492 ) | while read L; do $VERBOSE "> $L"; done
493
494 if ! [ -f "../$tgzfile" ]; then
495     echo >&2 "Where did the tarball end up? (../$tgzfile)"
496     exit 1
497 fi
498
499 $VERBOSE "== Generating checksums: $tgzfile.sha1 $tgzfile.sha256"
500 openssl sha1 < "../$tgzfile" | \
501     (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha1"
502 openssl sha256 < "../$tgzfile" | \
503     (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha256"
504 length=$(wc -c < "../$tgzfile")
505 sha1hash=$(cat "../$tgzfile.sha1")
506 sha256hash=$(cat "../$tgzfile.sha256")
507
508 $VERBOSE "== Generating announcement text: $announce"
509 # Hack the announcement template
510 cat "$RELEASE_AUX/$announce_template" \
511     | sed -e "s|\\\$release_text|$release_text|g" \
512           -e "s|\\\$release|$release|g" \
513           -e "s|\\\$series|$SERIES|g" \
514           -e "s|\\\$label|$PRE_LABEL|g" \
515           -e "s|\\\$tarfile|$tgzfile|" \
516           -e "s|\\\$length|$length|" \
517           -e "s|\\\$sha1hash|$sha1hash|" \
518           -e "s|\\\$sha256hash|$sha256hash|" \
519     | perl -p "$RELEASE_AUX/fix-title.pl" \
520     > "../$announce"
521
522 $VERBOSE "== Generating signatures: $tgzfile.asc $announce.asc"
523 rm -f "../$tgzfile.asc" "../$announce.asc"
524 echo "Signing the release files.  You may need to enter a pass phrase"
525 gpg$gpgkey --use-agent -sba "../$tgzfile"
526 gpg$gpgkey --use-agent -sta --clearsign "../$announce"
527
528 # Push everything to the parent repo
529 $VERBOSE "== Push what we have to the parent repository"
530 git push --follow-tags parent HEAD
531
532 if $do_upload; then
533     echo "== Upload tar, hash and announcement files"
534 fi
535
536 (
537     # With sftp, the progress meter is enabled by default,
538     # so we turn it off unless --verbose was given
539     if [ "$VERBOSE" == ':' ]; then
540         echo "progress"
541     fi
542     if [ -n "$upload_directory" ]; then
543         echo "cd $upload_directory"
544     fi
545     echo "put ../$tgzfile"
546     echo "put ../$tgzfile.sha1"
547     echo "put ../$tgzfile.sha256"
548     echo "put ../$tgzfile.asc"
549     echo "put ../$announce.asc"
550 ) | upload_backend_$upload_backend "$upload_address" $do_upload
551
552 # Post-release #######################################################
553
554 # Reset the files to their pre-release contents.  This doesn't affect
555 # HEAD, but simply set all the files in a state that 'git revert -n HEAD'
556 # would have given, but without the artifacts that 'git revert' adds.
557 #
558 # This allows all the post-release fixup scripts to perform from the
559 # same point as the release fixup scripts, hopefully making them easier
560 # to write.  This also makes the same post-release fixup scripts easier
561 # to run when --branch has been used, as they will be run both on the
562 # release branch and on the update branch, essentially from the same
563 # state for affected files.
564 $VERBOSE "== Reset all files to their pre-release contents"
565 git reset $git_quiet HEAD^ -- .
566 git checkout -- .
567
568 prev_release_text="$release_text"
569 prev_release_date="$RELEASE_DATE"
570
571 next_release_state "$next_method2"
572 set_version
573
574 release="$FULL_VERSION"
575 release_text="$VERSION$_BUILD_METADATA"
576 if [ -n "$PRE_LABEL" ]; then
577     release_text="$SERIES$_BUILD_METADATA $PRE_LABEL $PRE_NUM"
578 fi
579 $VERBOSE "== Updated version information to $release"
580
581 $VERBOSE "== Updating files for $release :"
582 (
583     IFS=';'
584     for file in $RELEASE_FILES; do
585         fixup="$RELEASE_AUX/fixup-$(basename "$file")-postrelease.pl"
586         $VERBOSE "> $file"
587         RELEASE="$release" RELEASE_TEXT="$release_text" \
588                PREV_RELEASE_TEXT="$prev_release_text" \
589                PREV_RELEASE_DATE="$prev_release_date" \
590                perl -pi $fixup $file
591     done
592 )
593
594 $VERBOSE "== Committing updates"
595 git add -u
596 git commit $git_quiet -m "Prepare for $release_text"$'\n\nRelease: yes'
597 if [ -n "$reviewers" ]; then
598     addrev --release --nopr $reviewers
599 fi
600
601 # Push everything to the parent repo
602 $VERBOSE "== Push what we have to the parent repository"
603 git push parent HEAD
604
605 if $do_branch; then
606     $VERBOSE "== Going back to the update branch $tmp_update_branch"
607     git checkout $git_quiet "$tmp_update_branch"
608
609     get_version
610     next_release_state "minor"
611     set_version
612
613     release="$FULL_VERSION"
614     release_text="$SERIES$_BUILD_METADATA"
615     $VERBOSE "== Updated version information to $release"
616
617     $VERBOSE "== Updating files for $release :"
618     (
619         IFS=';'
620         for file in $RELEASE_FILES; do
621             fixup="$RELEASE_AUX/fixup-$(basename "$file")-postrelease.pl"
622             $VERBOSE "> $file"
623             RELEASE="$release" RELEASE_TEXT="$release_text" \
624                    perl -pi $fixup $file
625         done
626     )
627
628     $VERBOSE "== Committing updates"
629     git add -u
630     git commit $git_quiet -m "Prepare for $release_text"$'\n\nRelease: yes'
631     if [ -n "$reviewers" ]; then
632         addrev --release --nopr $reviewers
633     fi
634 fi
635
636 # Push everything to the parent repo
637 $VERBOSE "== Push what we have to the parent repository"
638 git push parent HEAD
639
640 # Done ###############################################################
641
642 $VERBOSE "== Done"
643
644 cd $HERE
645 cat <<EOF
646
647 ======================================================================
648 The release is done, and involves a few files and commits for you to
649 deal with.  Everything you need has been pushed to your repository,
650 please see instructions that follow.
651 ======================================================================
652
653 EOF
654
655 if $do_release; then
656     cat <<EOF
657
658 The following files were uploaded to $upload_address, please ensure they
659 are dealt with appropriately:
660
661     $tgzfile
662     $tgzfile.sha1
663     $tgzfile.sha256
664     $tgzfile.asc
665     $announce.asc
666 EOF
667 fi
668
669 cat <<EOF
670
671 ----------------------------------------------------------------------
672 EOF
673
674 if $do_branch; then
675     cat <<EOF
676 You need to prepare the main repository with a new branch, '$release_branch'.
677 That is done directly in the server's bare repository like this:
678
679     git branch $release_branch $orig_HEAD
680
681 Two additional release branches have been added to your repository.
682 Push them to github, make PRs from them and have them approved:
683
684     $tmp_update_branch
685     $tmp_release_branch
686
687 When merging them into the main repository, do it like this:
688
689     git push git@github.openssl.org:openssl/openssl.git \\
690         $tmp_release_branch:$release_branch
691     git push git@github.openssl.org:openssl/openssl.git \\
692         $tmp_update_branch:$update_branch
693     git push git@github.openssl.org:openssl/openssl.git \\
694         $tag
695 EOF
696 else
697 cat <<EOF
698 One additional release branch has been added to your repository.
699 Push it to github, make a PR from it and have it approved:
700
701     $tmp_release_branch
702
703 When merging it into the main repository, do it like this:
704
705     git push git@github.openssl.org:openssl/openssl.git \\
706         $tmp_release_branch:$release_branch
707     git push git@github.openssl.org:openssl/openssl.git \\
708         $tag
709 EOF
710 fi
711
712 cat <<EOF
713
714 ----------------------------------------------------------------------
715 EOF
716
717 cat <<EOF
718
719 When everything is done, or if something went wrong and you want to start
720 over, simply clean away temporary things left behind:
721
722 The release worktree:
723
724     rm -rf $release_clone
725 EOF
726
727 if $do_branch; then
728     cat <<EOF
729
730 The additional release branches:
731
732     git branch -D $tmp_release_branch
733     git branch -D $tmp_update_branch
734 EOF
735 else
736     cat <<EOF
737
738 The temporary release branch:
739
740     git branch -D $tmp_release_branch
741 EOF
742 fi
743
744 exit 0
745
746 # cat is inconsequential, it's only there to fend off zealous shell parsers
747 # that parse all the way here.
748 cat <<EOF
749 ### BEGIN MANUAL
750 =pod
751
752 =head1 NAME
753
754 release.sh - OpenSSL release script
755
756 =head1 SYNOPSIS
757
758 B<release.sh>
759 [
760 B<--alpha> |
761 B<--next-beta> |
762 B<--beta> |
763 B<--final> |
764 B<--branch> |
765 B<--local-user>=I<keyid> |
766 B<--reviewer>=I<id> |
767 B<--upload-address>=I<address> |
768 B<--no-upload> |
769 B<--no-update> |
770 B<--verbose> |
771 B<--debug> |
772 B<--help> |
773 B<--manual>
774 ]
775
776 =head1 DESCRIPTION
777
778 B<release.sh> creates an OpenSSL release, given current worktree conditions.
779 It will refuse to work unless the current branch is C<master> or a release
780 branch (see L</RELEASE BRANCHES AND TAGS> below for a discussion on those).
781
782 B<release.sh> tries to be smart and figure out the next release if no hints
783 are given through options, and will exit with an error in ambiguous cases.
784
785 B<release.sh> finishes off with instructions on what to do next.  When
786 finishing commands are given, they must be followed exactly.
787
788 B<release.sh> leaves behind a clone of the local workspace, as well as one
789 or two branches in the local repository.  These will be mentioned and can
790 safely be removed after all instructions have been successfully followed.
791
792 =head1 OPTIONS
793
794 =over 4
795
796 =item B<--alpha>, B<--beta>
797
798 Set the state of this branch to indicate that alpha or beta releases are
799 to be done.
800
801 B<--alpha> is only acceptable if the I<PATCH> version number is zero and
802 the current state is "in development" or that alpha releases are ongoing.
803
804 B<--beta> is only acceptable if the I<PATCH> version number is zero and
805 that alpha or beta releases are ongoing.
806
807 =item B<--next-beta>
808
809 Use together with B<--alpha> to switch to beta releases after the current
810 release is done.
811
812 =item B<--final>
813
814 Set the state of this branch to indicate that regular releases are to be
815 done.  This is only valid if alpha or beta releases are currently ongoing.
816
817 This implies B<--branch>.
818
819 =item B<--branch>
820
821 Create a branch specific for the I<SERIES> release series, if it doesn't
822 already exist, and switch to it.  The exact branch name will be
823 C<< openssl-I<SERIES> >>.
824
825 =item B<--upload-address>=I<address>
826
827 The location that the release files are to be uploaded to.  Supported values
828 are:
829
830 =over 4
831
832 =item -
833
834 an existing local directory
835
836 =item -
837
838 something that can be interpreted as an SCP/SFTP address.  In this case,
839 SFTP will always be used.  Typical SCP remote file specs will be translated
840 into something that makes sense for SFTP.
841
842 =back
843
844 The default upload address is C<upload@dev.openssl.org>.
845
846 =item B<--no-upload>
847
848 Don't upload the release files.
849
850 =item B<--no-update>
851
852 Don't run C<make update> and C<make update-fips-checksums>.
853
854 =item B<--verbose>
855
856 Verbose output.
857
858 =item B<--debug>
859
860 Display extra debug output.  Implies B<--no-upload>
861
862 =item B<--local-user>=I<keyid>
863
864 Use I<keyid> as the local user for C<git tag> and for signing with C<gpg>.
865
866 If not given, then the default e-mail address' key is used.
867
868 =item B<--reviewer>=I<id>
869
870 Add I<id> to the set of reviewers for the commits performed by this script.
871 Multiple reviewers are allowed.
872
873 If no reviewer is given, you will have to run C<addrev> manually, which
874 means retagging a release commit manually as well.
875
876 =item B<--force>
877
878 Force execution.  Precisely, the check that the current branch is C<master>
879 or a release branch is not done.
880
881 =item B<--help>
882
883 Display a quick help text and exit.
884
885 =item B<--manual>
886
887 Display this manual and exit.
888
889 =back
890
891 =head1 RELEASE BRANCHES AND TAGS
892
893 Prior to OpenSSL 3.0, the release branches were named
894 C<< OpenSSL_I<SERIES>-stable >>, and the release tags were named
895 C<< OpenSSL_I<VERSION> >> for regular releases, or
896 C<< OpenSSL_I<VERSION>-preI<n> >> for pre-releases.
897
898 From OpenSSL 3.0 ongoing, the release branches are named
899 C<< openssl-I<SERIES> >>, and the release tags are named
900 C<< openssl-I<VERSION> >> for regular releases, or
901 C<< openssl-I<VERSION>-alphaI<n> >> for alpha releases
902 and C<< openssl-I<VERSION>-betaI<n> >> for beta releases.
903
904 B<release.sh> recognises both forms.
905
906 =head1 VERSION AND STATE
907
908 With OpenSSL 3.0, all the version and state information is in the file
909 F<VERSION.dat>, where the following variables are used and changed:
910
911 =over 4
912
913 =item B<MAJOR>, B<MINOR>, B<PATCH>
914
915 The three part of the version number.
916
917 =item B<PRE_RELEASE_TAG>
918
919 The indicator of the current state of the branch.  The value may be one pf:
920
921 =over 4
922
923 =item C<dev>
924
925 This branch is "in development".  This is typical for the C<master> branch
926 unless there are ongoing alpha or beta releases.
927
928 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
929
930 This branch has alpha releases going on.  C<< alphaI<n>-dev >> is what
931 should normally be seen in the git workspace, indicating that
932 C<< alphaI<n> >> is in development.  C<< alphaI<n> >> is what should be
933 found in the alpha release tar file.
934
935 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
936
937 This branch has beta releases going on.  The details are otherwise exactly
938 as for alpha.
939
940 =item I<no value>
941
942 This is normally not seen in the git workspace, but should always be what's
943 found in the tar file of a regular release.
944
945 =back
946
947 =item B<BUILD_METADATA>
948
949 Extra build metadata to be used by anyone for their own purposes.
950
951 =item B<RELEASE_DATE>
952
953 This is normally empty in the git workspace, but should always have the
954 release date in the tar file of any release.
955
956 =back
957
958 =head1 COPYRIGHT
959
960 Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
961
962 Licensed under the Apache License 2.0 (the "License").  You may not use
963 this file except in compliance with the License.  You can obtain a copy
964 in the file LICENSE in the source distribution or at
965 L<https://www.openssl.org/source/license.html>.
966
967 =cut
968 ### END MANUAL
969 EOF