Improve SSL_shutdown documentation.
[openssl.git] / dev / release.sh
1 #! /bin/bash -e
2 # Copyright 2020 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 usage () {
13     cat <<EOF
14 Usage: release.sh [ options ... ]
15
16 --alpha         Start or increase the "alpha" pre-release tag.
17 --next-beta     Switch to the "beta" pre-release tag after alpha release.
18                 It can only be given with --alpha.
19 --beta          Start or increase the "beta" pre-release tag.
20 --final         Get out of "alpha" or "beta" and make a final release.
21                 Implies --branch.
22
23 --branch        Create a release branch 'openssl-{major}.{minor}.x',
24                 where '{major}' and '{minor}' are the major and minor
25                 version numbers.
26
27 --local-user=<keyid>
28                 For the purpose of signing tags and tar files, use this
29                 key (default: use the default e-mail address’ key).
30
31 --no-upload     Don't upload to upload@dev.openssl.org.
32 --no-update     Don't perform 'make update'.
33 --verbose       Verbose output.
34 --debug         Include debug output.  Implies --no-upload.
35
36 --force         Force execution
37
38 --help          This text
39 --manual        The manual
40
41 If none of --alpha, --beta, or --final are given, this script tries to
42 figure out the next step.
43 EOF
44     exit 0
45 }
46
47 # Set to one of 'major', 'minor', 'alpha', 'beta' or 'final'
48 next_method=
49 next_method2=
50
51 do_branch=false
52 warn_branch=false
53
54 do_clean=true
55 do_upload=true
56 do_update=true
57 DEBUG=:
58 VERBOSE=:
59 git_quiet=-q
60
61 force=false
62
63 do_help=false
64 do_manual=false
65
66 tagkey=' -s'
67 gpgkey=
68
69 upload_address=upload@dev.openssl.org
70
71 TEMP=$(getopt -l 'alpha,next-beta,beta,final' \
72               -l 'branch' \
73               -l 'no-upload,no-update' \
74               -l 'verbose,debug' \
75               -l 'local-user:' \
76               -l 'force' \
77               -l 'help,manual' \
78               -n release.sh -- - "$@")
79 eval set -- "$TEMP"
80 while true; do
81     case $1 in
82     --alpha | --beta | --final )
83         next_method=$(echo "x$1" | sed -e 's|^x--||')
84         if [ -z "$next_method2" ]; then
85             next_method2=$next_method
86         fi
87         shift
88         if [ "$next_method" = 'final' ]; then
89             do_branch=true
90         fi
91         ;;
92     --next-beta )
93         next_method2=$(echo "x$1" | sed -e 's|^x--next-||')
94         shift
95         ;;
96     --branch )
97         do_branch=true
98         warn_branch=true
99         shift
100         ;;
101     --no-upload )
102         do_upload=false
103         shift
104         ;;
105     --no-update )
106         do_update=false
107         shift
108         ;;
109     --verbose )
110         VERBOSE=echo
111         git_quiet=
112         shift
113         ;;
114     --debug )
115         DEBUG=echo
116         do_upload=false
117         shift
118         ;;
119     --local-user )
120         shift
121         tagley=" -u $1"
122         gpgkey=" -u $1"
123         shift
124         ;;
125     --force )
126         force=true
127         shift
128         ;;
129     --help )
130         usage
131         exit 0
132         ;;
133     --manual )
134         sed -e '1,/^### BEGIN MANUAL/d' \
135             -e '/^### END MANUAL/,$d' \
136             < "$0" \
137             | pod2man \
138             | man -l -
139         exit 0
140         ;;
141     -- )
142         shift
143         break
144         ;;
145     * )
146         echo >&2 "Unknown option $1"
147         shift
148         exit 1
149         ;;
150     esac
151 done
152
153 $DEBUG >&2 "DEBUG: \$next_method=$next_method"
154 $DEBUG >&2 "DEBUG: \$next_method2=$next_method2"
155
156 $DEBUG >&2 "DEBUG: \$do_branch=$do_branch"
157
158 $DEBUG >&2 "DEBUG: \$do_upload=$do_upload"
159 $DEBUG >&2 "DEBUG: \$do_update=$do_update"
160 $DEBUG >&2 "DEBUG: \$DEBUG=$DEBUG"
161 $DEBUG >&2 "DEBUG: \$VERBOSE=$VERBOSE"
162 $DEBUG >&2 "DEBUG: \$git_quiet=$git_quiet"
163
164 case "$next_method+$next_method2" in
165     major+major | minor+minor )
166         # These are expected
167         ;;
168     alpha+alpha | alpha+beta | beta+beta | final+final | + | +beta )
169         # These are expected
170         ;;
171     * )
172         echo >&2 "Internal option error ($next_method, $next_method2)"
173         exit 1
174         ;;
175 esac
176
177 # Verbosity feed for certain commands
178 VERBOSITY_FIFO=/tmp/openssl-$$.fifo
179 mkfifo -m 600 $VERBOSITY_FIFO
180 ( cat $VERBOSITY_FIFO | while read L; do $VERBOSE "> $L"; done ) &
181 exec 42>$VERBOSITY_FIFO
182 trap "exec 42>&-; rm $VERBOSITY_FIFO" 0 2
183
184 # Setup ##############################################################
185
186 # Make sure we're in the work directory
187 cd $(dirname $0)/..
188 HERE=$(pwd)
189
190 # Check that we have the scripts that define functions we use
191 found=true
192 for fn in "$HERE/dev/release-aux/release-version-fn.sh" \
193           "$HERE/dev/release-aux/release-state-fn.sh"; do
194     if ! [ -f "$fn" ]; then
195         echo >&2 "'$fn' is missing"
196         found=false
197     fi
198 done
199 if ! $found; then
200     exit 1
201 fi
202
203 # Load version functions
204 . $HERE/dev/release-aux/release-version-fn.sh
205 . $HERE/dev/release-aux/release-state-fn.sh
206
207 # Make sure it's a branch we recognise
208 orig_branch=$(git rev-parse --abbrev-ref HEAD)
209 if (echo "$orig_branch" \
210         | grep -E -q \
211                -e '^master$' \
212                -e '^OpenSSL_[0-9]+_[0-9]+_[0-9]+[a-z]*-stable$' \
213                -e '^openssl-[0-9]+\.[0-9]+\.x$'); then
214     :
215 elif $force; then
216     :
217 else
218     echo >&2 "Not in master or any recognised release branch"
219     echo >&2 "Please 'git checkout' an approprite branch"
220     exit 1
221 fi
222
223 # Initialize #########################################################
224
225 echo "== Initializing work tree"
226
227 get_version
228
229 # Generate a cloned directory name
230 clone_branch="openssl-$SERIES.x"
231 release_clone="$clone_branch-release-tmp"
232
233 echo "== Work tree will be in $release_clone"
234
235 # Make a clone in a subdirectory and move there
236 if ! [ -d "$release_clone" ]; then
237     $VERBOSE "== Cloning to $release_clone"
238     git clone $git_quiet -b "$orig_branch" . "$release_clone"
239 fi
240 cd "$release_clone"
241
242 get_version
243
244 current_branch="$(git rev-parse --abbrev-ref HEAD)"
245 new_branch="openssl-$SERIES.x"
246
247 # Check that we're still on the same branch, or on a release branch
248 if [ "$current_branch" = "$orig_branch" ]; then
249     :
250 elif [ "$current_branch" = "$new_branch" ]; then
251     :
252 else
253    echo >&2 "The cloned sub-directory '$release_clone' is on a branch"
254    echo >&2 "other than '$current_branch' or '$new_branch'"
255    echo >&2 "Please 'cd \"$(pwd)\"; git checkout $current_branch'"
256    exit 1
257 fi
258
259 if $do_branch; then
260     if [ "$current_branch" = "$new_branch" ]; then
261         do_branch=false
262     fi
263     if ! $do_branch && $warn_branch; then
264         echo >&2 "Warning: --branch ignored, we're already in a release branch"
265     fi
266 fi
267
268 SOURCEDIR=$(pwd)
269 $DEBUG >&2 "DEBUG: Source directory is $SOURCEDIR"
270
271 # Release ############################################################
272
273 # We always expect to start from a state of development
274 if [ "$TYPE" != 'dev' ]; then
275     echo >&2 "Not in a development branch"
276     echo >&2 "Have a look at the git log in $release_clone, it may be that"
277     echo >&2 "a previous crash left it in an intermediate state and that"
278     echo >&2 "need to drop the top commit:"
279     echo >&2 ""
280     echo >&2 "(cd $release_clone; git reset --hard HEAD^)"
281     echo >&2 "# WARNING! LOOK BEFORE YOU ACT"
282     exit 1
283 fi
284
285 # We only create a release branch if the patch number is zero
286 if [ $PATCH -ne 0 ]; then
287     if $do_branch; then
288         echo >&2 "Warning! We're already in a release branch; --branch ignored"
289     fi
290     do_branch=false
291 fi
292
293 # Update the version information.  This won't save anything anywhere, yet,
294 # but does check for possible next_method errors before we do bigger work.
295 next_release_state "$next_method"
296
297 if $do_branch; then
298     $VERBOSE "== Creating a release branch: $new_branch"
299     git checkout $git_quiet -b "$new_branch"
300 fi
301
302 echo "== Configuring OpenSSL for update and release.  This may take a bit of time"
303
304 ./Configure cc >&42
305
306 $VERBOSE "== Checking source file updates"
307
308 make update >&42
309
310 if [ -n "$(git status --porcelain)" ]; then
311     $VERBOSE "== Committing updates"
312     git add -u
313     git commit $git_quiet -m 'make update'
314 fi
315
316 # Write the version information we updated
317 set_version
318
319 if [ -n "$PRE_LABEL" ]; then
320     release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
321     release_text="$SERIES$BUILD_METADATA $PRE_LABEL $PRE_NUM"
322     announce_template=openssl-announce-pre-release.tmpl
323 else
324     release="$VERSION$BUILD_METADATA"
325     release_text="$release"
326     announce_template=openssl-announce-release.tmpl
327 fi
328 tag="openssl-$release"
329 $VERBOSE "== Updated version information to $release"
330
331 $VERBOSE "== Updating files with release date for $release : $RELEASE_DATE"
332 for fixup in "$HERE/dev/release-aux"/fixup-*-release.pl; do
333     file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-release\.pl$||')"
334     $VERBOSE "> $file"
335     RELEASE="$release" RELEASE_TEXT="$release_text" RELEASE_DATE="$RELEASE_DATE" \
336         perl -pi $fixup $file
337 done
338
339 $VERBOSE "== Comitting updates and tagging"
340 git add -u
341 git commit $git_quiet -m "Prepare for release of $release_text"
342 echo "Tagging release with tag $tag.  You may need to enter a pass phrase"
343 git tag$tagkey "$tag" -m "OpenSSL $release release tag"
344
345 tarfile=openssl-$release.tar
346 tgzfile=$tarfile.gz
347 announce=openssl-$release.txt
348
349 echo "== Generating tar, hash and announcement files.  This make take a bit of time"
350
351 $VERBOSE "== Making tarfile: $tgzfile"
352 # Unfortunately, util/mktar.sh does verbose output on STDERR...  for good
353 # reason, but it means we don't display errors unless --verbose
354 ./util/mktar.sh --tarfile="../$tarfile" 2>&1 \
355     | while read L; do $VERBOSE "> $L"; done
356
357 if ! [ -f "../$tgzfile" ]; then
358     echo >&2 "Where did the tarball end up? (../$tgzfile)"
359     exit 1
360 fi
361
362 $VERBOSE "== Generating checksums: $tgzfile.sha1 $tgzfile.sha256"
363 openssl sha1 < "../$tgzfile" | \
364     (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha1"
365 openssl sha256 < "../$tgzfile" | \
366     (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha256"
367 length=$(wc -c < "../$tgzfile")
368 sha1hash=$(cat "../$tgzfile.sha1")
369 sha256hash=$(cat "../$tgzfile.sha256")
370
371 $VERBOSE "== Generating announcement text: $announce"
372 # Hack the announcement template
373 cat "$HERE/dev/release-aux/$announce_template" \
374     | sed -e "s|\\\$release_text|$release_text|g" \
375           -e "s|\\\$release|$release|g" \
376           -e "s|\\\$series|$SERIES|g" \
377           -e "s|\\\$label|$PRE_LABEL|g" \
378           -e "s|\\\$tarfile|$tgzfile|" \
379           -e "s|\\\$length|$length|" \
380           -e "s|\\\$sha1hash|$sha1hash|" \
381           -e "s|\\\$sha256hash|$sha256hash|" \
382     | perl -p "$HERE/dev/release-aux/fix-title.pl" \
383     > "../$announce"
384               
385 $VERBOSE "== Generating signatures: $tgzfile.asc $announce.asc"
386 rm -f "../$tgzfile.asc" "../$announce.asc"
387 echo "Signing the release files.  You may need to enter a pass phrase"
388 gpg$gpgkey --use-agent -sba "../$tgzfile"
389 gpg$gpgkey --use-agent -sta --clearsign "../$announce"
390
391 # We finish off by resetting all files, so we don't have to update
392 # files with release dates again
393 $VERBOSE "== Reset all files to their pre-commit contents"
394 git reset $git_quiet HEAD^ -- .
395 git checkout -- .
396
397 if $do_upload; then
398     (
399         if [ "$VERBOSE" != ':' ]; then
400             echo "progress"
401         fi
402         echo "put ../$tgzfile"
403         echo "put ../$tgzfile.sha1"
404         echo "put ../$tgzfile.sha256"
405         echo "put ../$tgzfile.asc"
406         echo "put ../$announce.asc"
407     ) \
408     | sftp "$upload_address"
409 fi
410
411 # Post-release #######################################################
412
413 prev_release_text="$release_text"
414 prev_release_date="$RELEASE_DATE"
415
416 next_release_state "$next_method2"
417 set_version
418
419 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
420 release_text="$VERSION$BUILD_METADATA"
421 if [ -n "$PRE_LABEL" ]; then
422     release_text="$SERIES$BUILD_METADATA $PRE_LABEL $PRE_NUM"
423 fi
424 $VERBOSE "== Updated version information to $release"
425
426 $VERBOSE "== Updating files for $release :"
427 for fixup in "$HERE/dev/release-aux"/fixup-*-postrelease.pl; do
428     file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-postrelease\.pl$||')"
429     $VERBOSE "> $file"
430     RELEASE="$release" RELEASE_TEXT="$release_text" \
431         PREV_RELEASE_TEXT="$prev_release_text" \
432         PREV_RELEASE_DATE="$prev_release_date" \
433         perl -pi $fixup $file
434 done
435
436 $VERBOSE "== Comitting updates"
437 git add -u
438 git commit $git_quiet -m "Prepare for $release_text"
439
440 if $do_branch; then
441     $VERBOSE "== Going back to the main branch $current_branch"
442     git checkout $git_quiet "$current_branch"
443
444     get_version
445     next_release_state "minor"
446     set_version
447
448     release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
449     release_text="$SERIES$BUILD_METADATA"
450     $VERBOSE "== Updated version information to $release"
451
452     $VERBOSE "== Updating files for $release :"
453     for fixup in "$HERE/dev/release-aux"/fixup-*-postrelease.pl; do
454         file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-postrelease\.pl$||')"
455         $VERBOSE "> $file"
456         RELEASE="$release" RELEASE_TEXT="$release_text" \
457             perl -pi $fixup $file
458     done
459
460     $VERBOSE "== Comitting updates"
461     git add -u
462     git commit $git_quiet -m "Prepare for $release_text"
463 fi
464
465 # Done ###############################################################
466     
467 $VERBOSE "== Done"
468
469 cat <<EOF
470
471 ======================================================================
472 The release is done, and involves a few commits for you to deal with.
473 It has all been done in a clone of this workspace, see details below.
474 EOF
475 if $do_branch; then
476     cat <<EOF
477 Additionally, a release branch has been created for you, so you need
478 to look for new commits in two places.
479 EOF
480 fi
481
482 if $do_release; then
483     cat <<EOF
484
485 These files were uploaded to $upload_address:
486
487     ../$tgzfile
488     ../$tgzfile.sha1
489     ../$tgzfile.sha256
490     ../$tgzfile.asc
491     ../$announce.asc
492 EOF
493 fi
494
495 cat <<EOF
496
497 Release worktree:   $release_clone
498 EOF
499 if [ "$current_branch" != "$new_branch" ]; then
500     cat <<EOF
501 Current branch:     $current_branch
502 EOF
503 fi
504 if $do_branch; then
505     cat <<EOF
506 New release branch: $new_branch
507 EOF
508 fi
509
510 cat <<EOF
511 ======================================================================
512 EOF
513
514 cat <<EOF
515 If something went wrong and you want to start over, all you need is to
516 remove the release worktree:
517
518     rm -rf $release_clone
519
520 If a tarball was uploaded, you must also clean that away, or ask you
521 kind OpenSSL sysadmin to do so.
522 EOF
523
524 exit 0
525
526 # cat is inconsequential, it's only there to fend off zealous shell parsers
527 # that parse all the way here.
528 cat <<EOF
529 ### BEGIN MANUAL
530 =pod
531
532 =head1 NAME
533
534 release.sh - OpenSSL release script
535
536 =head1 SYNOPSIS
537
538 B<release.sh>
539 [
540 B<--alpha> |
541 B<--next-beta> |
542 B<--beta> |
543 B<--final> |
544 B<--branch> |
545 B<--local-user>=I<keyid> |
546 B<--no-upload> |
547 B<--no-update> |
548 B<--verbose> |
549 B<--debug> |
550 B<--help> |
551 B<--manual>
552 ]
553
554 =head1 DESCRIPTION
555
556 B<release.sh> creates an OpenSSL release, given current worktree conditions.
557 It will refuse to work unless the current branch is C<master> or a release
558 branch (see L</RELEASE BRANCHES AND TAGS> below for a discussion on those).
559
560 B<release.sh> tries to be smart and figure out the next release if no hints
561 are given through options, and will exit with an error in ambiguous cases.
562
563 B<release.sh> always clones the current workspace into a sub-directory
564 named C<< openssl-I<SERIES>-tmp >>, where C<< I<SERIES> >> is taken from
565 the available version information in the source.
566
567 =head1 OPTIONS
568
569 =over 4
570
571 =item B<--alpha>, B<--beta>
572
573 Set the state of this branch to indicate that alpha or beta releases are
574 to be done.
575
576 B<--alpha> is only acceptable if the I<PATCH> version number is zero and
577 the current state is "in development" or that alpha releases are ongoing.
578
579 B<--beta> is only acceptable if the I<PATCH> version number is zero and
580 that alpha or beta releases are ongoing.
581
582 =item B<--next-beta>
583
584 Use together with B<--alpha> to switch to beta releases after the current
585 release is done.
586
587 =item B<--final>
588
589 Set the state of this branch to indicate that regular releases are to be
590 done.  This is only valid if alpha or beta releases are currently ongoing.
591
592 This implies B<--branch>.
593
594 =item B<--branch>
595
596 Create a branch specific for the I<SERIES>.x release series, if it doesn't
597 already exist, and switch to it.  The exact branch name will be
598 C<< openssl-I<SERIES>.x >>.
599
600 =item B<--no-upload>
601
602 Don't upload the produced files.
603
604 =item B<--no-update>
605
606 Don't run C<make update>.
607
608 =item B<--verbose>
609
610 Verbose output.
611
612 =item B<--debug>
613
614 Display extra debug output.  Implies B<--no-upload>
615
616 =item B<--local-user>=I<keyid>
617
618 Use I<keyid> as the local user for C<git tag> and for signing with C<gpg>.
619
620 If not given, then the default e-mail address' key is used.
621
622 =item B<--force>
623
624 Force execution.  Precisely, the check that the current branch is C<master>
625 or a release branch is not done.
626
627 =item B<--help>
628
629 Display a quick help text and exit.
630
631 =item B<--manual>
632
633 Display this manual and exit.
634
635 =back
636
637 =head1 RELEASE BRANCHES AND TAGS
638
639 Prior to OpenSSL 3.0, the release branches were named
640 C<< OpenSSL_I<SERIES>-stable >>, and the release tags were named
641 C<< OpenSSL_I<VERSION> >> for regular releases, or
642 C<< OpenSSL_I<VERSION>-preI<n> >> for pre-releases.
643
644 From OpenSSL 3.0 ongoing, the release branches are named
645 C<< openssl-I<SERIES>.x >>, and the release tags are named
646 C<< openssl-I<VERSION> >> for regular releases, or
647 C<< openssl-I<VERSION>-alphaI<n> >> for alpha releases
648 and C<< openssl-I<VERSION>-betaI<n> >> for beta releases.
649
650 B<release.sh> recognises both forms.
651
652 =head1 VERSION AND STATE
653
654 With OpenSSL 3.0, all the version and state information is in the file
655 F<VERSION>, where the following variables are used and changed:
656
657 =over 4
658
659 =item B<MAJOR>, B<MINOR>, B<PATCH>
660
661 The three part of the version number.
662
663 =item B<PRE_RELEASE_TAG>
664
665 The indicator of the current state of the branch.  The value may be one pf:
666
667 =over 4
668
669 =item C<dev>
670
671 This branch is "in development".  This is typical for the C<master> branch
672 unless there are ongoing alpha or beta releases.
673
674 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
675
676 This branch has alpha releases going on.  C<< alphaI<n>-dev >> is what
677 should normally be seen in the git workspace, indicating that
678 C<< alphaI<n> >> is in development.  C<< alphaI<n> >> is what should be
679 found in the alpha release tar file.
680
681 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
682
683 This branch has beta releases going on.  The details are otherwise exactly
684 as for alpha.
685
686 =item I<no value>
687
688 This is normally not seen in the git workspace, but should always be what's
689 found in the tar file of a regular release.
690
691 =back
692
693 =item B<RELEASE_DATE>
694
695 This is normally empty in the git workspace, but should always have the
696 release date in the tar file of any release.
697
698 =back
699
700 =head1 COPYRIGHT
701
702 Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
703
704 Licensed under the Apache License 2.0 (the "License").  You may not use
705 this file except in compliance with the License.  You can obtain a copy
706 in the file LICENSE in the source distribution or at
707 L<https://www.openssl.org/source/license.html>.
708
709 =cut
710 ### END MANUAL
711 EOF