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"
230 orig_HEAD=$(git rev-parse HEAD)
232 # Initialize #########################################################
234 echo "== Initializing work tree"
238 # Generate a cloned directory name
239 release_clone="$orig_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" -o parent . "$release_clone"
252 # Branches we will work with. The release branch is where we make the
253 # changes for the release, the update branch is where we make the post-
255 update_branch="$orig_branch"
256 release_branch="openssl-$SERIES.x"
258 # among others, we only create a release branch if the patch number is zero
259 if [ "$update_branch" = "$release_branch" ] || [ $PATCH -ne 0 ]; then
260 if $do_branch && $warn_branch; then
261 echo >&2 "Warning! We're already in a release branch; --branch ignored"
266 if ! $do_branch; then
267 release_branch="$update_branch"
270 # Branches we create for PRs
271 branch_version="$VERSION${PRE_LABEL:+-$PRE_LABEL$PRE_NUM}"
272 tmp_update_branch="OSSL--$update_branch--$branch_version"
273 tmp_release_branch="OSSL--$release_branch--$branch_version"
275 # Check that we're still on the same branch as our parent repo, or on a
277 current_branch=$(git rev-parse --abbrev-ref HEAD)
278 if [ "$current_branch" = "$update_branch" ]; then
280 elif [ "$current_branch" = "$release_branch" ]; then
283 echo >&2 "The cloned sub-directory '$release_clone' is on a branch"
284 if [ "$update_branch" = "$release_branch" ]; then
285 echo >&2 "other than '$update_branch'."
287 echo >&2 "other than '$update_branch' or '$release_branch'."
289 echo >&2 "Please 'cd \"$(pwd)\"; git checkout $update_branch'"
294 $DEBUG >&2 "DEBUG: Source directory is $SOURCEDIR"
296 # Release ############################################################
298 # We always expect to start from a state of development
299 if [ "$TYPE" != 'dev' ]; then
300 echo >&2 "Not in a development branch"
301 echo >&2 "Have a look at the git log in $release_clone, it may be that"
302 echo >&2 "a previous crash left it in an intermediate state and that"
303 echo >&2 "need to drop the top commit:"
305 echo >&2 "(cd $release_clone; git reset --hard HEAD^)"
306 echo >&2 "# WARNING! LOOK BEFORE YOU ACT"
310 # Update the version information. This won't save anything anywhere, yet,
311 # but does check for possible next_method errors before we do bigger work.
312 next_release_state "$next_method"
314 # Create our temporary release branch
315 $VERBOSE "== Creating a local release branch: $tmp_release_branch"
316 git checkout $git_quiet -b "$tmp_release_branch"
318 echo "== Configuring OpenSSL for update and release. This may take a bit of time"
322 $VERBOSE "== Checking source file updates"
326 if [ -n "$(git status --porcelain)" ]; then
327 $VERBOSE "== Committing updates"
329 git commit $git_quiet -m 'make update'
330 if [ -n "$reviewers" ]; then
331 addrev --nopr $reviewers
335 # Create our temporary update branch, if it's not the release branch.
336 # This is used in post-release below
338 $VERBOSE "== Creating a local update branch: $tmp_update_branch"
339 git branch $git_quiet "$tmp_update_branch"
342 # Write the version information we updated
345 if [ -n "$PRE_LABEL" ]; then
346 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
347 release_text="$SERIES$BUILD_METADATA $PRE_LABEL $PRE_NUM"
348 announce_template=openssl-announce-pre-release.tmpl
350 release="$VERSION$BUILD_METADATA"
351 release_text="$release"
352 announce_template=openssl-announce-release.tmpl
354 tag="openssl-$release"
355 $VERBOSE "== Updated version information to $release"
357 $VERBOSE "== Updating files with release date for $release : $RELEASE_DATE"
358 for fixup in "$HERE/dev/release-aux"/fixup-*-release.pl; do
359 file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-release\.pl$||')"
361 RELEASE="$release" RELEASE_TEXT="$release_text" RELEASE_DATE="$RELEASE_DATE" \
362 perl -pi $fixup $file
365 $VERBOSE "== Comitting updates and tagging"
367 git commit $git_quiet -m "Prepare for release of $release_text"
368 if [ -n "$reviewers" ]; then
369 addrev --nopr $reviewers
371 echo "Tagging release with tag $tag. You may need to enter a pass phrase"
372 git tag$tagkey "$tag" -m "OpenSSL $release release tag"
374 tarfile=openssl-$release.tar
376 announce=openssl-$release.txt
378 echo "== Generating tar, hash and announcement files. This make take a bit of time"
380 $VERBOSE "== Making tarfile: $tgzfile"
381 # Unfortunately, util/mktar.sh does verbose output on STDERR... for good
382 # reason, but it means we don't display errors unless --verbose
383 ./util/mktar.sh --tarfile="../$tarfile" 2>&1 \
384 | while read L; do $VERBOSE "> $L"; done
386 if ! [ -f "../$tgzfile" ]; then
387 echo >&2 "Where did the tarball end up? (../$tgzfile)"
391 $VERBOSE "== Generating checksums: $tgzfile.sha1 $tgzfile.sha256"
392 openssl sha1 < "../$tgzfile" | \
393 (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha1"
394 openssl sha256 < "../$tgzfile" | \
395 (IFS='='; while read X H; do echo $H; done) > "../$tgzfile.sha256"
396 length=$(wc -c < "../$tgzfile")
397 sha1hash=$(cat "../$tgzfile.sha1")
398 sha256hash=$(cat "../$tgzfile.sha256")
400 $VERBOSE "== Generating announcement text: $announce"
401 # Hack the announcement template
402 cat "$HERE/dev/release-aux/$announce_template" \
403 | sed -e "s|\\\$release_text|$release_text|g" \
404 -e "s|\\\$release|$release|g" \
405 -e "s|\\\$series|$SERIES|g" \
406 -e "s|\\\$label|$PRE_LABEL|g" \
407 -e "s|\\\$tarfile|$tgzfile|" \
408 -e "s|\\\$length|$length|" \
409 -e "s|\\\$sha1hash|$sha1hash|" \
410 -e "s|\\\$sha256hash|$sha256hash|" \
411 | perl -p "$HERE/dev/release-aux/fix-title.pl" \
414 $VERBOSE "== Generating signatures: $tgzfile.asc $announce.asc"
415 rm -f "../$tgzfile.asc" "../$announce.asc"
416 echo "Signing the release files. You may need to enter a pass phrase"
417 gpg$gpgkey --use-agent -sba "../$tgzfile"
418 gpg$gpgkey --use-agent -sta --clearsign "../$announce"
420 # Push everything to the parent repo
421 $VERBOSE "== Push what we have to the parent repository"
422 git push --follow-tags parent HEAD
426 if [ "$VERBOSE" != ':' ]; then
429 echo "put ../$tgzfile"
430 echo "put ../$tgzfile.sha1"
431 echo "put ../$tgzfile.sha256"
432 echo "put ../$tgzfile.asc"
433 echo "put ../$announce.asc"
435 | sftp "$upload_address"
438 # Post-release #######################################################
440 $VERBOSE "== Reset all files to their pre-release contents"
441 git reset $git_quiet HEAD^ -- .
444 prev_release_text="$release_text"
445 prev_release_date="$RELEASE_DATE"
447 next_release_state "$next_method2"
450 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
451 release_text="$VERSION$BUILD_METADATA"
452 if [ -n "$PRE_LABEL" ]; then
453 release_text="$SERIES$BUILD_METADATA $PRE_LABEL $PRE_NUM"
455 $VERBOSE "== Updated version information to $release"
457 $VERBOSE "== Updating files for $release :"
458 for fixup in "$HERE/dev/release-aux"/fixup-*-postrelease.pl; do
459 file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-postrelease\.pl$||')"
461 RELEASE="$release" RELEASE_TEXT="$release_text" \
462 PREV_RELEASE_TEXT="$prev_release_text" \
463 PREV_RELEASE_DATE="$prev_release_date" \
464 perl -pi $fixup $file
467 $VERBOSE "== Comitting updates"
469 git commit $git_quiet -m "Prepare for $release_text"
470 if [ -n "$reviewers" ]; then
471 addrev --nopr $reviewers
474 # Push everything to the parent repo
475 $VERBOSE "== Push what we have to the parent repository"
479 $VERBOSE "== Going back to the update branch $tmp_update_branch"
480 git checkout $git_quiet "$tmp_update_branch"
483 next_release_state "minor"
486 release="$VERSION-$PRE_RELEASE_TAG$BUILD_METADATA"
487 release_text="$SERIES$BUILD_METADATA"
488 $VERBOSE "== Updated version information to $release"
490 $VERBOSE "== Updating files for $release :"
491 for fixup in "$HERE/dev/release-aux"/fixup-*-postrelease.pl; do
492 file="$(basename "$fixup" | sed -e 's|^fixup-||' -e 's|-postrelease\.pl$||')"
494 RELEASE="$release" RELEASE_TEXT="$release_text" \
495 perl -pi $fixup $file
498 $VERBOSE "== Comitting updates"
500 git commit $git_quiet -m "Prepare for $release_text"
501 if [ -n "$reviewers" ]; then
502 addrev --nopr $reviewers
506 # Push everything to the parent repo
507 $VERBOSE "== Push what we have to the parent repository"
510 # Done ###############################################################
517 ======================================================================
518 The release is done, and involves a few files and commits for you to
519 deal with. Everything you need has been pushed to your repository,
520 please see instructions that follow.
521 ======================================================================
528 The following files were uploaded to $upload_address, please ensure they
529 are dealt with appropriately:
541 ----------------------------------------------------------------------
546 You need to prepare the main repository with a new branch, '$release_branch'.
547 That is done directly in the server's bare repository like this:
549 git branch $release_branch $orig_HEAD
551 Two additional release branches have been added to your repository.
552 Push them to github, make PRs from them and have them approved:
557 When merging them into the main repository, do it like this:
559 git push openssl-git@git.openssl.org:openssl.git \\
560 $tmp_release_branch:$release_branch
561 git push openssl-git@git.openssl.org:openssl.git \\
562 $tmp_update_branch:$update_branch
563 git push openssl-git@git.openssl.org:openssl.git \\
568 One additional release branch has been added to your repository.
569 Push it to github, make a PR from it and have it approved:
573 When merging it into the main repository, do it like this:
575 git push openssl-git@git.openssl.org:openssl.git \\
576 $tmp_release_branch:$release_branch
577 git push openssl-git@git.openssl.org:openssl.git \\
584 ----------------------------------------------------------------------
589 When everything is done, or if something went wrong and you want to start
590 over, simply clean away temporary things left behind:
592 The release worktree:
594 rm -rf $release_clone
600 The additional release branches:
602 git branch -D $tmp_release_branch
603 git branch -D $tmp_update_branch
608 The temporary release branch:
610 git branch -D $tmp_release_branch
616 # cat is inconsequential, it's only there to fend off zealous shell parsers
617 # that parse all the way here.
624 release.sh - OpenSSL release script
635 B<--local-user>=I<keyid> |
636 B<--reviewer>=I<id> |
647 B<release.sh> creates an OpenSSL release, given current worktree conditions.
648 It will refuse to work unless the current branch is C<master> or a release
649 branch (see L</RELEASE BRANCHES AND TAGS> below for a discussion on those).
651 B<release.sh> tries to be smart and figure out the next release if no hints
652 are given through options, and will exit with an error in ambiguous cases.
654 B<release.sh> finishes off with instructions on what to do next. When
655 finishing commands are given, they must be followed exactly.
657 B<release.sh> leaves behind a clone of the local workspace, as well as one
658 or two branches in the local repository. These will be mentioned and can
659 safely be removed after all instructions have been successfully followed.
665 =item B<--alpha>, B<--beta>
667 Set the state of this branch to indicate that alpha or beta releases are
670 B<--alpha> is only acceptable if the I<PATCH> version number is zero and
671 the current state is "in development" or that alpha releases are ongoing.
673 B<--beta> is only acceptable if the I<PATCH> version number is zero and
674 that alpha or beta releases are ongoing.
678 Use together with B<--alpha> to switch to beta releases after the current
683 Set the state of this branch to indicate that regular releases are to be
684 done. This is only valid if alpha or beta releases are currently ongoing.
686 This implies B<--branch>.
690 Create a branch specific for the I<SERIES>.x release series, if it doesn't
691 already exist, and switch to it. The exact branch name will be
692 C<< openssl-I<SERIES>.x >>.
696 Don't upload the produced files.
700 Don't run C<make update>.
708 Display extra debug output. Implies B<--no-upload>
710 =item B<--local-user>=I<keyid>
712 Use I<keyid> as the local user for C<git tag> and for signing with C<gpg>.
714 If not given, then the default e-mail address' key is used.
716 =item B<--reviewer>=I<id>
718 Add I<id> to the set of reviewers for the commits performed by this script.
719 Multiple reviewers are allowed.
721 If no reviewer is given, you will have to run C<addrev> manually, which
722 means retagging a release commit manually as well.
726 Force execution. Precisely, the check that the current branch is C<master>
727 or a release branch is not done.
731 Display a quick help text and exit.
735 Display this manual and exit.
739 =head1 RELEASE BRANCHES AND TAGS
741 Prior to OpenSSL 3.0, the release branches were named
742 C<< OpenSSL_I<SERIES>-stable >>, and the release tags were named
743 C<< OpenSSL_I<VERSION> >> for regular releases, or
744 C<< OpenSSL_I<VERSION>-preI<n> >> for pre-releases.
746 From OpenSSL 3.0 ongoing, the release branches are named
747 C<< openssl-I<SERIES>.x >>, and the release tags are named
748 C<< openssl-I<VERSION> >> for regular releases, or
749 C<< openssl-I<VERSION>-alphaI<n> >> for alpha releases
750 and C<< openssl-I<VERSION>-betaI<n> >> for beta releases.
752 B<release.sh> recognises both forms.
754 =head1 VERSION AND STATE
756 With OpenSSL 3.0, all the version and state information is in the file
757 F<VERSION.dat>, where the following variables are used and changed:
761 =item B<MAJOR>, B<MINOR>, B<PATCH>
763 The three part of the version number.
765 =item B<PRE_RELEASE_TAG>
767 The indicator of the current state of the branch. The value may be one pf:
773 This branch is "in development". This is typical for the C<master> branch
774 unless there are ongoing alpha or beta releases.
776 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
778 This branch has alpha releases going on. C<< alphaI<n>-dev >> is what
779 should normally be seen in the git workspace, indicating that
780 C<< alphaI<n> >> is in development. C<< alphaI<n> >> is what should be
781 found in the alpha release tar file.
783 =item C<< alphaI<n> >> or C<< alphaI<n>-dev >>
785 This branch has beta releases going on. The details are otherwise exactly
790 This is normally not seen in the git workspace, but should always be what's
791 found in the tar file of a regular release.
795 =item B<RELEASE_DATE>
797 This is normally empty in the git workspace, but should always have the
798 release date in the tar file of any release.
804 Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
806 Licensed under the Apache License 2.0 (the "License"). You may not use
807 this file except in compliance with the License. You can obtain a copy
808 in the file LICENSE in the source distribution or at
809 L<https://www.openssl.org/source/license.html>.