diff options
-rwxr-xr-x | scripts/ci/build_status_command.sh | 11 | ||||
-rwxr-xr-x | scripts/packages/package_info_generator.sh | 8 | ||||
-rw-r--r-- | scripts/release/BUILD | 6 | ||||
-rwxr-xr-x | scripts/release/common.sh | 124 | ||||
-rwxr-xr-x | scripts/release/release.sh | 53 | ||||
-rwxr-xr-x | scripts/release/release_test.sh | 22 | ||||
-rwxr-xr-x | scripts/release/relnotes.sh | 33 | ||||
-rwxr-xr-x | scripts/release/relnotes_test.sh | 5 |
8 files changed, 163 insertions, 99 deletions
diff --git a/scripts/ci/build_status_command.sh b/scripts/ci/build_status_command.sh index e04b208e87..2bbbbffcd5 100755 --- a/scripts/ci/build_status_command.sh +++ b/scripts/ci/build_status_command.sh @@ -32,13 +32,8 @@ fi if [ -n "${BUILD_LOG-}" ]; then echo "RELEASE_BUILD_LOG ${BUILD_LOG}" fi -echo "RELEASE_COMMIT_MSG $(git_commit_msg | tr '\n' '\f')" -release_name=$(get_release_name) -rc=$(get_release_candidate) +release_name=$(get_full_release_name) if [ -n "${release_name}" ]; then - if [ -n "${rc}" ]; then - echo "RELEASE_NAME ${release_name}rc${rc}" - else - echo "RELEASE_NAME ${release_name}" - fi + echo "RELEASE_NAME ${release_name}" + echo "RELEASE_NOTES $(get_full_release_notes | tr '\n' '\f')" fi diff --git a/scripts/packages/package_info_generator.sh b/scripts/packages/package_info_generator.sh index 4d477760df..d7377b4be1 100755 --- a/scripts/packages/package_info_generator.sh +++ b/scripts/packages/package_info_generator.sh @@ -25,7 +25,7 @@ git_hash= url= built_by= build_log= -commit_msg= +release_notes= for i in "${@}"; do while read line; do @@ -44,8 +44,8 @@ for i in "${@}"; do RELEASE_BUILD_LOG) build_log="$value" ;; - RELEASE_COMMIT_MSG) - commit_msg="$value" + RELEASE_NOTES) + release_notes="$value" ;; RELEASE_COMMIT_URL) commit_url="$value" @@ -60,7 +60,7 @@ if [ -z "${release_name}" ]; then # Not a release echo "# Binary package at HEAD (@$git_hash)" else - echo "# $commit_msg" # Make the first line the header + echo "# ${release_notes}" # Make the first line the header # Subsection for environment echo echo "## Build informations" diff --git a/scripts/release/BUILD b/scripts/release/BUILD index a6a4ab0801..832b98ebda 100644 --- a/scripts/release/BUILD +++ b/scripts/release/BUILD @@ -9,7 +9,10 @@ filegroup( sh_library( name = "relnotes", - srcs = ["relnotes.sh"], + srcs = [ + "common.sh", + "relnotes.sh", + ], ) sh_test( @@ -30,7 +33,6 @@ sh_test( sh_library( name = "release", srcs = [ - "common.sh", "release.sh", ], deps = [":relnotes"], diff --git a/scripts/release/common.sh b/scripts/release/common.sh index e17cedc183..2f0bc0d69a 100755 --- a/scripts/release/common.sh +++ b/scripts/release/common.sh @@ -49,6 +49,35 @@ function get_release_name() { git notes --ref=release show "$@" 2>/dev/null | xargs echo || true } +# Get the short hash of a commit +function git_commit_shorthash() { + git rev-parse --short "${1}" +} + +# Get the subject (first line of the commit message) of a commit +function git_commit_subject() { + git show -s --pretty=format:%s "$@" +} + +# Get the list of commit hashes between two revisions +function git_log_hash() { + local baseline="$1" + local head="$2" + shift 2 + git log --pretty=format:%H "${baseline}".."${head}" "$@" +} + +# Extract the full release name from the git notes +function get_full_release_name() { + local name="$(get_release_name "$@")" + local rc="$(get_release_candidate "$@")" + if [ -n "${rc}" ]; then + echo "${name}rc${rc}" + else + echo "${name}" + fi +} + # Extract the release notes from the git notes function get_release_notes() { git notes --ref=release-notes show "$@" 2>/dev/null || true @@ -66,3 +95,98 @@ function get_release_branch() { fi echo "${branch_name}" } + +# fmt behaves differently on *BSD and on GNU/Linux, use fold. +function wrap_text() { + fold -s -w $1 | sed 's/ *$//' +} + +# Create the revision information given a list of commits. The first +# commit should be the baseline, and the other ones are the cherry-picks. +# The result is of the form: +# Baseline: BASELINE_COMMIT +# +# Cherry picks: +# + CHERRY_PICK1: commit message summary of the CHERRY_PICK1. This +# message will be wrapped into 70 columns. +# + CHERRY_PICK2: commit message summary of the CHERRY_PICK2. +function create_revision_information() { + echo "Baseline: $(git_commit_shorthash "${1}")" + local first=1 + shift + while [ -n "${1-}" ]; do + if [[ "$first" -eq 1 ]]; then + echo -e "\nCherry picks:" + first=0 + fi + local hash="$(git_commit_shorthash "${1}")" + local subject="$(git_commit_subject $hash)" + local lines=$(echo "$subject" | wrap_text 56) # 14 leading spaces. + echo " + $hash: $lines" | head -1 + echo "$lines" | tail -n +2 | sed 's/^/ /' + shift + done +} + +# Get the baseline of master. +# Args: $1: release branch, default to HEAD +function get_release_baseline() { + git merge-base master "${1:-HEAD}" +} + +# Get the list of cherry-picks since master +# Args: +# $1: branch, default to HEAD +# $2: baseline change, default to $(get_release_baseline $1) +function get_cherrypicks() { + local branch="${1:-HEAD}" + local baseline="${2:-$(get_release_baseline "${branch}")}" + # List of changes since the baseline on the release branch + local changes="$(git_log_hash "${baseline}" "${branch}" --reverse)" + # List of changes since the baseline on the master branch, and their patch-id + local master_changes="$(git_log_hash "${baseline}" master | xargs git show | git patch-id)" + # Now for each changes on the release branch + for i in ${changes}; do + # Find the change with the same patch-id on the master branch + echo "${master_changes}" \ + | grep "^$(git show "$i" | git patch-id | cut -d " " -f 1)" \ + | cut -d " " -f 2 + done +} + +# Generate the title of the release with the date from the release name ($1). +function get_release_title() { + echo "Release ${1} ($(date +%Y-%m-%d))" +} + +# Generate the release message to be added to the changelog +# from the release notes for release $1 +function generate_release_message() { + local release_name="$1" + local branch="${2:-HEAD}" + local baseline="$(get_release_baseline "${branch}")" + local cherrypicks="$(get_cherrypicks "${branch}" "${baseline}")" + +cat <<EOF +$(get_release_title "$release_name") + +$(create_revision_information $baseline $cherrypicks) + +$(get_release_notes "${branch}") +EOF +} + +# Returns the release notes for the CHANGELOG.md taken from either from +# the notes for a release candidate or from the commit message for a +# full release. +function get_full_release_notes() { + local release_name="$(get_full_release_name "$@")" + + if [[ "${release_name}" =~ rc[0-9]+$ ]]; then + # Release candidate, we need to generate from the notes + generate_release_message "${release_name}" "$@" + else + # Full release, returns the commit message + git_commit_msg "$@" + fi +} diff --git a/scripts/release/release.sh b/scripts/release/release.sh index 2dbb35fe29..06d1294ecf 100755 --- a/scripts/release/release.sh +++ b/scripts/release/release.sh @@ -97,48 +97,24 @@ function release_note_editor() { # Create the release commit by changing the CHANGELOG file function create_release_commit() { - local release_title="$1" - local release_name="$2" - local relnotes="$3" - local tmpfile="$4" - local baseline="$5" - shift 5 - local cherrypicks=$@ + local infos=$(generate_release_message "${1}") local changelog_path="$PWD/CHANGELOG.md" - version_info=$(create_revision_information $baseline $cherrypicks) # CHANGELOG.md - cat >${tmpfile} <<EOF -## ${release_title} - -EOF - if [ -n "${version_info}" ]; then - cat >>${tmpfile} <<EOF -\`\`\` -${version_info} -\`\`\` -EOF - fi - cat >>${tmpfile} <<EOF - -${relnotes} -EOF - + local tmpfile="$(mktemp ${TMPDIR:-/tmp}/relnotes-XXXXXXXX)" + trap "rm -f ${tmpfile}" EXIT + echo -n "## ${infos}" >${tmpfile} if [ -f "${changelog_path}" ]; then echo >>${tmpfile} cat "${changelog_path}" >>${tmpfile} fi - cat ${tmpfile} > ${changelog_path} + cat "${tmpfile}" > ${changelog_path} git add ${changelog_path} - # Commit message - cat >${tmpfile} <<EOF -${release_title} - -${version_info} + rm -f "${tmpfile}" + trap - EXIT -${relnotes} -EOF - git commit --no-verify -F ${tmpfile} --no-edit --author "${RELEASE_AUTHOR}" + # Commit + git commit --no-verify -m "${infos}" --no-edit --author "${RELEASE_AUTHOR}" } function apply_cherry_picks() { @@ -174,7 +150,6 @@ function create_release() { shift 2 local origin_branch=$(git_get_branch) local branch_name="release-${release_name}" - local release_title="Release ${release_name} ($(date +%Y-%m-%d))" local tmpfile=$(mktemp ${TMPDIR:-/tmp}/relnotes-XXXXXXXX) local tmpfile2=$(mktemp ${TMPDIR:-/tmp}/relnotes-XXXXXXXX) trap 'rm -f ${tmpfile} ${tmpfile2}' EXIT @@ -204,20 +179,21 @@ function create_release() { echo "Creating release notes" echo "${RELEASE_NOTE_MESSAGE}" > ${tmpfile} - echo "# ${release_title}" >> ${tmpfile} + echo "# $(get_release_title "${release_name}rc${rc}")" >> ${tmpfile} echo >> ${tmpfile} create_release_notes "${tmpfile2}" >> ${tmpfile} release_note_editor ${tmpfile} "${origin_branch}" "${branch_name}" local relnotes="$(cat ${tmpfile})" - create_release_commit "${release_title}" "${release_name}" \ - "${relnotes}" "${tmpfile}" "${baseline}" $@ release_name=$(set_release_name "${release_name}" "${rc}") # Add the release notes git notes --ref=release-notes add -f -m "${relnotes}" + + # Return to the original branch git checkout ${origin_branch} &> /dev/null echo "Created ${release_name} on branch ${branch_name}." + # Clean-up rm -f ${tmpfile} ${tmpfile2} trap - EXIT } @@ -256,7 +232,8 @@ function do_release() { echo -n "You are about to release branch ${branch} in tag ${tag_name}, confirm? [y/N] " read answer if [ "$answer" = "y" -o "$answer" = "Y" ]; then - # Remove release "candidate" + echo "Creating the release commit" + create_release_commit "${tag_name}" set_release_name "${tag_name}" echo "Creating the tag" git tag ${tag_name} diff --git a/scripts/release/release_test.sh b/scripts/release/release_test.sh index 8eb6cbc1db..8df6eddcee 100755 --- a/scripts/release/release_test.sh +++ b/scripts/release/release_test.sh @@ -62,7 +62,7 @@ function create() { local new_branch=$(git_get_branch) assert_equals "$old_branch" "$new_branch" assert_contains "Created $name.* on branch release-$name." $TEST_log - git show -s --pretty=format:%B "release-$name" >$TEST_log + get_full_release_notes "release-$name" >$TEST_log } function push() { @@ -80,8 +80,6 @@ function push() { function release() { local tag=$1 local branch=$(git_get_branch) - local changelog=$(cat CHANGELOG.md) - local commit=$(git show -s --pretty=format:%B $branch) echo y | ${RELEASE_SCRIPT} release || fail "Failed to release ${branch}" assert_equals master "$(git_get_branch)" git tag >$TEST_log @@ -91,7 +89,7 @@ function release() { git --git-dir=${GERRIT_ROOT} tag >$TEST_log expect_not_log $tag # Test commit is everywhere - assert_equals "$commit" "$(git show -s --pretty=format:%B $tag)" + local commit="$(git show -s --pretty=format:%B $tag)" assert_equals "$commit" "$(git show -s --pretty=format:%B master)" assert_equals "$commit" \ "$(git --git-dir=${GITHUB_ROOT} show -s --pretty=format:%B $tag)" @@ -101,7 +99,7 @@ function release() { "$(git --git-dir=${GERRIT_ROOT} show -s --pretty=format:%B master)" # Now test for CHANGELOG.md file in master branch - assert_equals "$changelog" "$(git show $tag:CHANGELOG.md)" + local changelog="$(git show $tag:CHANGELOG.md)" assert_equals "$changelog" "$(git show master:CHANGELOG.md)" assert_equals "$changelog" \ "$(git --git-dir=${GITHUB_ROOT} show $tag:CHANGELOG.md)" @@ -116,7 +114,7 @@ function abandon() { local tag="$1" local branch="release-$tag" git checkout "$branch" - local changelog="$(git show master:CHANGELOG.md)" + local changelog="$(git show master:CHANGELOG.md || true)" local master_sha1=$(git rev-parse master) echo y | ${RELEASE_SCRIPT} abandon || fail "Failed to abandon release ${branch}" assert_equals master "$(git_get_branch)" @@ -151,7 +149,7 @@ function test_release_workflow() { export EDITOR=true # Initial release create v0 965c392 - expect_log "Release v0" + expect_log "Release v0rc1" expect_log "Initial release" # Push the release branch push v0 @@ -177,7 +175,7 @@ Important changes: # Every line starting with a # will be removed as well as every # empty line at the start and at the end. -# Release v1 ($(date +%Y-%m-%d)) +# Release v1rc1 ($(date +%Y-%m-%d)) ${RELNOTES} @@ -202,7 +200,7 @@ cat ${TEST_TMPDIR}/replacement.log >\$1 EOF chmod +x ${EDITOR} create v1 1170dc6 0540fde - local header='Release v1 ('$(date +%Y-%m-%d)') + local header='Release v1rc1 ('$(date +%Y-%m-%d)') Baseline: 1170dc6 @@ -219,7 +217,7 @@ Cherry picks: # Test creating a second candidate echo "#!$(which true)" >${EDITOR} create v1 1170dc6 0540fde cef25c4 - header='Release v1 ('$(date +%Y-%m-%d)') + header='Release v1rc2 ('$(date +%Y-%m-%d)') Baseline: 1170dc6 @@ -249,7 +247,7 @@ echo 'Dummy release' >\$1 EOF # Create release create --force_rc=2 v2 2464526 - expect_log "Release v2" + expect_log "Release v2rc2" expect_log "Baseline: 2464526" assert_equals 2 "$(get_release_candidate release-v2)" # Abandon it @@ -261,7 +259,7 @@ EOF chmod +x .git/hooks/commit-msg # Re-create release create v2 2464526 - expect_log "Release v2" + expect_log "Release v2rc1" expect_log "Baseline: 2464526" expect_not_log "HOOK-SHOULD-BE-IGNORED" # Push diff --git a/scripts/release/relnotes.sh b/scripts/release/relnotes.sh index b749028571..2c4a0ab7cc 100755 --- a/scripts/release/relnotes.sh +++ b/scripts/release/relnotes.sh @@ -99,11 +99,6 @@ function generate_release_notes() { done } -# fmt behaves differently on *BSD and on GNU/Linux, use fold. -function wrap_text() { - fold -s -w $1 | sed 's/ *$//' -} - # Returns the list of release notes in arguments into a list of points in # a markdown list. The release notes are wrapped to 70 characters so it # displays nicely in a git history. @@ -146,31 +141,3 @@ function create_release_notes() { [ -n "${last_release}" ] || { echo "Initial release."; return 0; } release_notes ${last_release} } - -# Create the revision information given a list of commits. The first -# commit should be the baseline, and the other one are the cherry-picks. -# The result is of the form: -# Baseline: BASELINE_COMMIT -# -# Cherry picks: -# + CHERRY_PICK1: commit message summary of the CHERRY_PICK1. This -# message will be wrapped into 70 columns. -# + CHERRY_PICK2: commit message summary of the CHERRY_PICK2. -function create_revision_information() { - echo "Baseline: $(git rev-parse --short "${1}")" - first=1 - shift - while [ -n "${1-}" ]; do - if [[ "$first" -eq 1 ]]; then - echo -e "\nCherry picks:" - first=0 - fi - - local hash="$(git rev-parse --short "${1}")" - local subject=$(git show -s --pretty=format:%s $hash) - local lines=$(echo "$subject" | wrap_text 56) # 14 leading spaces. - echo " + $hash: $lines" | head -1 - echo "$lines" | tail -n +2 | sed 's/^/ /' - shift - done -} diff --git a/scripts/release/relnotes_test.sh b/scripts/release/relnotes_test.sh index 9322b5d817..972a4e38d4 100755 --- a/scripts/release/relnotes_test.sh +++ b/scripts/release/relnotes_test.sh @@ -24,6 +24,7 @@ source ${SCRIPT_DIR}/testenv.sh || { echo "testenv.sh not found!" >&2; exit 1; } setup_git_repository ### Load the relnotes script +source ${SCRIPT_DIR}/common.sh || { echo "common.sh not found!" >&2; exit 1; } source ${SCRIPT_DIR}/relnotes.sh || { echo "relnotes.sh not found!" >&2; exit 1; } ### Tests method @@ -207,8 +208,8 @@ Cherry picks: + 14d905b: Add --with_aspect_deps flag to blaze query. This flag should produce additional information about aspect dependencies when --output is set to {xml, proto}.' - assert_equals "$expected" \ - "$(create_revision_information 965c392ab1d68d5bc23fdef3d86d635ec9d2da8e bb59d88 14d905b5cce9a1bbc2911331809b03679b23dad1)" + actual="$(create_revision_information 965c392ab1d68d5bc23fdef3d86d635ec9d2da8e bb59d88 14d905b5cce9a1bbc2911331809b03679b23dad1)" + assert_equals "$expected" "$actual" } run_suite "Release notes generation tests" |