2 # Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
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
9 # This is the most shell agnostic way to specify that POSIX rules.
14 Usage: release.sh [ options ... ]
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.
23 --branch Create a release branch 'openssl-{major}.{minor}.x',
24 where '{major}' and '{minor}' are the major and minor
27 --reviewer=<id> The reviewer of the commits.
29 For the purpose of signing tags and tar files, use this
30 key (default: use the default e-mail address’ key).
32 --no-upload Don't upload to upload@dev.openssl.org.
33 --no-update Don't perform 'make update'.
34 --verbose Verbose output.
35 --debug Include debug output. Implies --no-upload.
37 --force Force execution
42 If none of --alpha, --beta, or --final are given, this script tries to
43 figure out the next step.
48 # Set to one of 'major', 'minor', 'alpha', 'beta' or 'final'
71 upload_address=upload@dev.openssl.org
73 TEMP=$(getopt -l 'alpha,next-beta,beta,final' \
75 -l 'no-upload,no-update' \
81 -n release.sh -- - "$@")
85 --alpha | --beta | --final )
86 next_method=$(echo "x$1" | sed -e 's|^x--||')
87 if [ -z "$next_method2" ]; then
88 next_method2=$next_method
91 if [ "$next_method" = 'final' ]; then
96 next_method2=$(echo "x$1" | sed -e 's|^x--next-||')
129 reviewers="$reviewers $1=$2"
142 sed -e '1,/^### BEGIN MANUAL/d' \
143 -e '/^### END MANUAL/,$d' \
154 echo >&2 "Unknown option $1"
161 $DEBUG >&2 "DEBUG: \$next_method=$next_method"
162 $DEBUG >&2 "DEBUG: \$next_method2=$next_method2"
164 $DEBUG >&2 "DEBUG: \$do_branch=$do_branch"
166 $DEBUG >&2 "DEBUG: \$do_upload=$do_upload"
167 $DEBUG >&2 "DEBUG: \$do_update=$do_update"
168 $DEBUG >&2 "DEBUG: \$DEBUG=$DEBUG"
169 $DEBUG >&2 "DEBUG: \$VERBOSE=$VERBOSE"
170 $DEBUG >&2 "DEBUG: \$git_quiet=$git_quiet"
172 case "$next_method+$next_method2" in
173 major+major | minor+minor )
176 alpha+alpha | alpha+beta | beta+beta | final+final | + | +beta )
180 echo >&2 "Internal option error ($next_method, $next_method2)"
185 # Verbosity feed for certain commands
186 VERBOSITY_FIFO=/tmp/openssl-$$.fifo
187 mkfifo -m 600 $VERBOSITY_FIFO
188 ( cat $VERBOSITY_FIFO | while read L; do $VERBOSE "> $L"; done ) &
189 exec 42>$VERBOSITY_FIFO
190 trap "exec 42>&-; rm $VERBOSITY_FIFO" 0 2
192 # Setup ##############################################################
194 # Make sure we're in the work directory
198 # Check that we have the scripts that define functions we use
200 for fn in "$HERE/dev/release-aux/release-version-fn.sh" \
201 "$HERE/dev/release-aux/release-state-fn.sh"; do
202 if ! [ -f "$fn" ]; then
203 echo >&2 "'$fn' is missing"
211 # Load version functions
212 . $HERE/dev/release-aux/release-version-fn.sh
213 . $HERE/dev/release-aux/release-state-fn.sh
215 # Make sure it's a branch we recognise
216 orig_branch=$(git rev-parse --abbrev-ref HEAD)
217 if (echo "$orig_branch" \
220 -e '^OpenSSL_[0-9]+_[0-9]+_[0-9]+[a-z]*-stable$' \
221 -e '^openssl-[0-9]+\.[0-9]+\.x$'); then
226 echo >&2 "Not in master or any recognised release branch"
227 echo >&2 "Please 'git checkout' an approprite branch"
231 # Initialize #########################################################
233 echo "== Initializing work tree"
237 # Generate a cloned directory name
238 clone_branch="openssl-$SERIES.x"
239 release_clone="$clone_branch-release-tmp"
241 echo "== Work tree will be in $release_clone"
243 # Make a clone in a subdirectory and move there
244 if ! [ -d "$release_clone" ]; then
245 $VERBOSE "== Cloning to $release_clone"
246 git clone $git_quiet -b "$orig_branch" . "$release_clone"
252 current_branch="$(git rev-parse --abbrev-ref HEAD)"
253 new_branch="openssl-$SERIES.x"
255 # Check that we're still on the same branch, or on a release branch
256 if [ "$current_branch" = "$orig_branch" ]; then
258 elif [ "$current_branch" = "$new_branch" ]; then
261 echo >&2 "The cloned sub-directory '$release_clone' is on a branch"
262 echo >&2 "other than '$current_branch' or '$new_branch'"
263 echo >&2 "Please 'cd \"$(pwd)\"; git checkout $current_branch'"
268 if [ "$current_branch" = "$new_branch" ]; then
271 if ! $do_branch && $warn_branch; then
272 echo >&2 "Warning: --branch ignored, we're already in a release branch"
277 $DEBUG >&2 "DEBUG: Source directory is $SOURCEDIR"
279 # Release ############################################################
281 # We always expect to start from a state of development
282 if [ "$TYPE" != 'dev' ]; then
283 echo >&2 "Not in a development branch"
284 echo >&2 "Have a look at the git log in $release_clone, it may be that"
285 echo >&2 "a previous crash left it in an intermediate state and that"
286 echo >&2 "need to drop the top commit:"
288 echo >&2 "(cd $release_clone; git reset --hard HEAD^)"
289 echo >&2 "# WARNING! LOOK BEFORE YOU ACT"
293 # We only create a release branch if the patch number is zero
294 if [ $PATCH -ne 0 ]; then
296 echo >&2 "Warning! We're already in a release branch; --branch ignored"
301 # Update the version information. This won't save anything anywhere, yet,
302 # but does check for possible next_method errors before we do bigger work.
303 next_release_state "$next_method"
306 $VERBOSE "== Creating a release branch: $new_branch"
307 git checkout $git_quiet -b "$new_branch"
310 echo "== Configuring OpenSSL for update and release. This may take a bit of time"
314 $VERBOSE "== Checking source file updates"
318 if [ -n "$(git status --porcelain)" ]; then
319 $VERBOSE "== Committing updates"
321 git commit $git_quiet -m 'make update'
322 if [ -n "$reviewers" ]; then
323 addrev --nopr $reviewers
327 # Write the version information we updated
330 if [ -n "$PRE_LABEL" ]; then
331 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
332 release_text="$SERIES$BUILD_METADATA $PRE_LABEL $PRE_NUM"
333 announce_template=openssl-announce-pre-release.tmpl
335 release="$VERSION$BUILD_METADATA"
336 release_text="$release"
337 announce_template=openssl-announce-release.tmpl
339 tag="openssl-$release"
340 $VERBOSE "== Updated version information to $release"
342 $VERBOSE "== Updating files with release date for $release : $RELEASE_DATE"
343 for fixup in "$HERE/dev/release-aux"/fixup-*-release.pl; do
344 file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-release\.pl$||')"
346 RELEASE="$release" RELEASE_TEXT="$release_text" RELEASE_DATE="$RELEASE_DATE" \
347 perl -pi $fixup $file
350 $VERBOSE "== Comitting updates and tagging"
352 git commit $git_quiet -m "Prepare for release of $release_text"
353 if [ -n "$reviewers" ]; then
354 addrev --nopr $reviewers
356 echo "Tagging release with tag $tag. You may need to enter a pass phrase"
357 git tag$tagkey "$tag" -m "OpenSSL $release release tag"
359 tarfile=openssl-$release.tar
361 announce=openssl-$release.txt
363 echo "== Generating tar, hash and announcement files. This make take a bit of time"
365 $VERBOSE "== Making tarfile: $tgzfile"
366 # Unfortunately, util/mktar.sh does verbose output on STDERR... for good
367 # reason, but it means we don't display errors unless --verbose
368 ./util/mktar.sh --tarfile="../$tarfile" 2>&1 \
369 | while read L; do $VERBOSE "> $L"; done
371 if ! [ -f "../$tgzfile" ]; then
372 echo >&2 "Where did the tarball end up? (../$tgzfile)"
376 $VERBOSE "== Generating checksums: $tgzfile.sha1 $tgzfile.sha256"
377 openssl sha1 < "../$tgzfile" | \
378 (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha1"
379 openssl sha256 < "../$tgzfile" | \
380 (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha256"
381 length=$(wc -c < "../$tgzfile")
382 sha1hash=$(cat "../$tgzfile.sha1")
383 sha256hash=$(cat "../$tgzfile.sha256")
385 $VERBOSE "== Generating announcement text: $announce"
386 # Hack the announcement template
387 cat "$HERE/dev/release-aux/$announce_template" \
388 | sed -e "s|\\\$release_text|$release_text|g" \
389 -e "s|\\\$release|$release|g" \
390 -e "s|\\\$series|$SERIES|g" \
391 -e "s|\\\$label|$PRE_LABEL|g" \
392 -e "s|\\\$tarfile|$tgzfile|" \
393 -e "s|\\\$length|$length|" \
394 -e "s|\\\$sha1hash|$sha1hash|" \
395 -e "s|\\\$sha256hash|$sha256hash|" \
396 | perl -p "$HERE/dev/release-aux/fix-title.pl" \
399 $VERBOSE "== Generating signatures: $tgzfile.asc $announce.asc"
400 rm -f "../$tgzfile.asc" "../$announce.asc"
401 echo "Signing the release files. You may need to enter a pass phrase"
402 gpg$gpgkey --use-agent -sba "../$tgzfile"
403 gpg$gpgkey --use-agent -sta --clearsign "../$announce"
405 # We finish off by resetting all files, so we don't have to update
406 # files with release dates again
407 $VERBOSE "== Reset all files to their pre-commit contents"
408 git reset $git_quiet HEAD^ -- .
413 if [ "$VERBOSE" != ':' ]; then
416 echo "put ../$tgzfile"
417 echo "put ../$tgzfile.sha1"
418 echo "put ../$tgzfile.sha256"
419 echo "put ../$tgzfile.asc"
420 echo "put ../$announce.asc"
422 | sftp "$upload_address"
425 # Post-release #######################################################
427 prev_release_text="$release_text"
428 prev_release_date="$RELEASE_DATE"
430 next_release_state "$next_method2"
433 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
434 release_text="$VERSION$BUILD_METADATA"
435 if [ -n "$PRE_LABEL" ]; then
436 release_text="$SERIES$BUILD_METADATA $PRE_LABEL $PRE_NUM"
438 $VERBOSE "== Updated version information to $release"
440 $VERBOSE "== Updating files for $release :"
441 for fixup in "$HERE/dev/release-aux"/fixup-*-postrelease.pl; do
442 file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-postrelease\.pl$||')"
444 RELEASE="$release" RELEASE_TEXT="$release_text" \
445 PREV_RELEASE_TEXT="$prev_release_text" \
446 PREV_RELEASE_DATE="$prev_release_date" \
447 perl -pi $fixup $file
450 $VERBOSE "== Comitting updates"
452 git commit $git_quiet -m "Prepare for $release_text"
453 if [ -n "$reviewers" ]; then
454 addrev --nopr $reviewers
458 $VERBOSE "== Going back to the main branch $current_branch"
459 git checkout $git_quiet "$current_branch"
462 next_release_state "minor"
465 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
466 release_text="$SERIES$BUILD_METADATA"
467 $VERBOSE "== Updated version information to $release"
469 $VERBOSE "== Updating files for $release :"
470 for fixup in "$HERE/dev/release-aux"/fixup-*-postrelease.pl; do
471 file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-postrelease\.pl$||')"
473 RELEASE="$release" RELEASE_TEXT="$release_text" \
474 perl -pi $fixup $file
477 $VERBOSE "== Comitting updates"
479 git commit $git_quiet -m "Prepare for $release_text"
480 if [ -n "$reviewers" ]; then
481 addrev --nopr $reviewers
485 # Done ###############################################################
491 ======================================================================
492 The release is done, and involves a few commits for you to deal with.
493 It has all been done in a clone of this workspace, see details below.
497 Additionally, a release branch has been created for you, so you need
498 to look for new commits in two places.
505 These files were uploaded to $upload_address:
517 Release worktree: $release_clone
519 if [ "$current_branch" != "$new_branch" ]; then
521 Current branch: $current_branch
526 New release branch: $new_branch
531 ======================================================================
535 If something went wrong and you want to start over, all you need is to
536 remove the release worktree:
538 rm -rf $release_clone
540 If a tarball was uploaded, you must also clean that away, or ask you
541 kind OpenSSL sysadmin to do so.
546 # cat is inconsequential, it's only there to fend off zealous shell parsers
547 # that parse all the way here.
554 release.sh - OpenSSL release script
565 B<--local-user>=I<keyid> |
566 B<--reviewer>=I<id> |
577 B<release.sh> creates an OpenSSL release, given current worktree conditions.
578 It will refuse to work unless the current branch is C<master> or a release
579 branch (see L</RELEASE BRANCHES AND TAGS> below for a discussion on those).
581 B<release.sh> tries to be smart and figure out the next release if no hints
582 are given through options, and will exit with an error in ambiguous cases.
584 B<release.sh> always clones the current workspace into a sub-directory
585 named C<< openssl-I<SERIES>-tmp >>, where C<< I<SERIES> >> is taken from
586 the available version information in the source.
592 =item B<--alpha>, B<--beta>
594 Set the state of this branch to indicate that alpha or beta releases are
597 B<--alpha> is only acceptable if the I<PATCH> version number is zero and
598 the current state is "in development" or that alpha releases are ongoing.
600 B<--beta> is only acceptable if the I<PATCH> version number is zero and
601 that alpha or beta releases are ongoing.
605 Use together with B<--alpha> to switch to beta releases after the current
610 Set the state of this branch to indicate that regular releases are to be
611 done. This is only valid if alpha or beta releases are currently ongoing.
613 This implies B<--branch>.
617 Create a branch specific for the I<SERIES>.x release series, if it doesn't
618 already exist, and switch to it. The exact branch name will be
619 C<< openssl-I<SERIES>.x >>.
623 Don't upload the produced files.
627 Don't run C<make update>.
635 Display extra debug output. Implies B<--no-upload>
637 =item B<--local-user>=I<keyid>
639 Use I<keyid> as the local user for C<git tag> and for signing with C<gpg>.
641 If not given, then the default e-mail address' key is used.
643 =item B<--reviewer>=I<id>
645 Add I<id> to the set of reviewers for the commits performed by this script.
646 Multiple reviewers are allowed.
648 If no reviewer is given, you will have to run C<addrev> manually, which
649 means retagging a release commit manually as well.
653 Force execution. Precisely, the check that the current branch is C<master>
654 or a release branch is not done.
658 Display a quick help text and exit.
662 Display this manual and exit.
666 =head1 RELEASE BRANCHES AND TAGS
668 Prior to OpenSSL 3.0, the release branches were named
669 C<< OpenSSL_I<SERIES>-stable >>, and the release tags were named
670 C<< OpenSSL_I<VERSION> >> for regular releases, or
671 C<< OpenSSL_I<VERSION>-preI<n> >> for pre-releases.
673 From OpenSSL 3.0 ongoing, the release branches are named
674 C<< openssl-I<SERIES>.x >>, and the release tags are named
675 C<< openssl-I<VERSION> >> for regular releases, or
676 C<< openssl-I<VERSION>-alphaI<n> >> for alpha releases
677 and C<< openssl-I<VERSION>-betaI<n> >> for beta releases.
679 B<release.sh> recognises both forms.
681 =head1 VERSION AND STATE
683 With OpenSSL 3.0, all the version and state information is in the file
684 F<VERSION>, where the following variables are used and changed:
688 =item B<MAJOR>, B<MINOR>, B<PATCH>
690 The three part of the version number.
692 =item B<PRE_RELEASE_TAG>
694 The indicator of the current state of the branch. The value may be one pf:
700 This branch is "in development". This is typical for the C<master> branch
701 unless there are ongoing alpha or beta releases.
703 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
705 This branch has alpha releases going on. C<< alphaI<n>-dev >> is what
706 should normally be seen in the git workspace, indicating that
707 C<< alphaI<n> >> is in development. C<< alphaI<n> >> is what should be
708 found in the alpha release tar file.
710 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
712 This branch has beta releases going on. The details are otherwise exactly
717 This is normally not seen in the git workspace, but should always be what's
718 found in the tar file of a regular release.
722 =item B<RELEASE_DATE>
724 This is normally empty in the git workspace, but should always have the
725 release date in the tar file of any release.
731 Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
733 Licensed under the Apache License 2.0 (the "License"). You may not use
734 this file except in compliance with the License. You can obtain a copy
735 in the file LICENSE in the source distribution or at
736 L<https://www.openssl.org/source/license.html>.