diff --git a/RELEASE_CHECKLIST.txt b/RELEASE_CHECKLIST.txt index 939ca30..ac886f3 100644 --- a/RELEASE_CHECKLIST.txt +++ b/RELEASE_CHECKLIST.txt @@ -4,19 +4,37 @@ ## Pre-release tasks * Figure out whether a release is worthwhile to do. + +Tiny/patch releases require some manual work: + +* Apply changes to the release branch, merge or cherry-pick +* Append to previous issues_closed_for*md file +* Add new tiny release section to ChangeLog +* Manually adjust versions in json_c_version, CMakeLists.txt, meson.build + +The rest of these instructions assume you're creating a minor or major release. + +* Load release shell functions + * `. reltools/reltools.subr` + * `set_rel_vars` * Analyze the previous release branch to see if anything should have been applied to master. + * `git log -r "${RELBASE}..${RELBRANCH}" | less` + * Look for anything other than generating docs, bumping the release + version, or changes cherry-picked from master. * Collect changes and assemble tentative release notes. - * Identify previous release branch point + * Create "Notes for v0.xx release" page at https://github.com/json-c/json-c/wiki * Check commit logs between previous branch point and now for - notable changes worth mentioning + notable changes worth mentioning. + * `git log --reverse -r "${RELBASE}"..master | less` * Create a new issues_closed_for_X.Y.md file + * `./reltools/gen_issues_closed.md` * Include notable entries from here in the release notes. * Analyze APIs between previous release branch and master to produce list of changes (added/removed/updated funcs, etc...), and detect backwards compat issues. * https://github.com/lvc/abi-compliance-checker - * See also `abi-check.sh` + * `./abi-check.sh` * If the new release is not backwards compatible, then this is a MAJOR release. * Mention removed features in ChangeLog * Consider re-adding backwards compatible support, through symbol @@ -24,16 +42,14 @@ * Be sure any new symbols are listed in json-c.sym as part of the _new_ release version. * Update the AUTHORS file - - PREV=$(git tag | tail -1) - ( git log -r ${PREV}..HEAD | grep Author: | sed -e's/Author: //' ; cat AUTHORS ) | sort -u > A1 - mv A1 AUTHORS + * `update_authors` * Exclude mentioning changes that have already been included in a point release of the previous release branch. -* Update ChangeLog with relevant notes before branching. +* Update ChangeLog with relevant notes *before* branching. +* Check that GitHub Actions are all working - https://github.com/json-c/json-c/actions * Check that the compile works on Linux - automatic through Travis * Check that the compile works on NetBSD * Check that the compile works on Windows - automatic through AppVeyor @@ -42,11 +58,9 @@ Start creating the new release: - PREV=$(git tag | tail -1) - PREV=${PREV#json-c-} - PREV=${PREV%-*} - release=0.$((${PREV#*.} + 1)) - cd ~ + . reltools/reltools.subr + release=$(get_next_relver) + cd ${HOME} git clone https://github.com/json-c/json-c json-c-${release} rm -rf distcheck @@ -66,6 +80,9 @@ Make any fixes/changes *before* branching. ------------ Using ${release}: + + # TODO: write me: ./reltools/bump_version.sh --release + Update the version in json_c_version.h Update the version in CMakeLists.txt (VERSION in the project(...) line) @@ -75,7 +92,7 @@ library version. Generally, unless we're doing a major release, change: to VERSION x.y+1.z - Update the version in meson.build (both at the top, and down under + Update the version in meson.build (both at the top, and soversion down under '# Build library') git commit -a -m "Bump version to ${release}" @@ -120,6 +137,9 @@ Tag the branch: git push origin json-c-${release} git push --tags + # Double check that API difference match previous run + ./abi-check.sh + ------------ Go to Amazon S3 service at: @@ -136,43 +156,22 @@ Logout of Amazon S3, and verify that the files are visible. Post-release checklist: +Update master branch version to ${version}.99, in ChangeLog, json_c_version.h, etc... + git checkout master + ./reltools/bump_relrease.sh --dev -Add new section to ChangeLog for ${release}+1 - -Use ${release}.99 to indicate a version "newer" than anything on the branch: - Update the version in json_c_version.h - Update the version in CMakeLists.txt - -Update the set_target_properties() line in CmakeLists.txt to match the release branch. - -Add a new empty section to the json-c.sym file, for ${release}+1 - - git commit -a -m "Update the master branch to version ${release}.99" + # check results, then: git push ------------ -Update the gh-pages branch with new docs: +Update the gh-pages branch with new docs (already generated earlier): - cd json-c-${release} - git checkout json-c-${release} - cd .. - - git clone -b gh-pages https://github.com/json-c/json-c json-c-pages - cd json-c-pages - mkdir json-c-${release} - cp -R ../json-c-${release}/doc json-c-${release}/. - git add json-c-${release} - rm json-c-current-release - ln -s json-c-${release} json-c-current-release - git commit -a -m "Add the ${release} docs." - - vi index.html - # Add/change links to current release. - - git commit -a -m "Update the doc links to point at ${release}" + reltag=$(get_most_recent_reltag) + ./reltools/publish_docs.sh "${reltag}" + # check results, then: git push ------------ diff --git a/amiga/package-amiga.sh b/amiga/package-amiga.sh index ac72155..854577c 100755 --- a/amiga/package-amiga.sh +++ b/amiga/package-amiga.sh @@ -34,15 +34,8 @@ rm -rf "$_lha_probe" # OS gets staged under its own directory. rm -rf "$DIST"; mkdir -p "$STAGE/json-c" -# Extract the version from either a release tag, or the dev version + abbreviated commit hash -GIT_DESCR=$(git describe --tags --always) -if [[ "$GIT_DESCR" == json-c-* ]] ; then - # e.g. 0.19-20260627 - JSON_C_VERS=${GIT_DESCR#json-c-} -else - # e.g. 0.19.99-09e45f6 - JSON_C_VERS=$(sed -ne'/define JSON_C_VERSION / { s/"$//; s/.*"//; p }' "${ROOT}/json_c_version.h")-${GIT_DESCR} -fi +. "${ROOT}/reltools/reltools.subr" +JSON_C_VERS=$(get_ver_descr) sed -e"s/VERSION/${JSON_C_VERS}/" "$AMIGA_DIR/json-c.readme.template" > "$STAGE/json-c/json-c.readme" built=() diff --git a/reltools/bump_version.sh b/reltools/bump_version.sh new file mode 100755 index 0000000..c39651e --- /dev/null +++ b/reltools/bump_version.sh @@ -0,0 +1,185 @@ +#!/bin/bash +# + +set -e -o pipefail +trap 'echo "ERROR: Unexpected exit in $0"' EXIT + +RUNDIR=$(dirname "$0") +RUNDIR=$(realpath "${RUNDIR}") +. "${RUNDIR}/reltools.subr" + +usage() +{ + local exitval="$1" ; shift + local errmsg="$1" + if [ "${exitval}" -ne 0 ] ; then + exec 1>&2 + fi + if [ -n "${errmsg}" ] ; then + echo "ERROR: ${errmsg}" 1>&2 + fi + cat <&2 + echo "See RELEASE_CHECKLIST.txt for steps to take" 1>&2 + trap - EXIT + exit 1 +} + +bump_dev_ver() +{ + if [ -n "$(git status --porcelain | grep -v reltools/bump_version.sh)" ] ; then + usage 1 "local changes in working directory, aborting" + fi + + RELVER=$(get_most_recent_relver) + DEVVER=${RELVER}.99 + NEXTVER=$(get_next_relver) + + if ! grep -q "^${NEXTVER}" ChangeLog ; then + # Add new section to ChangeLog for ${release}+1 + cat < ChangeLog.new +${NEXTVER} (future release) +======================================== +Deprecated and removed features: +-------------------------------- +* none yet + +New features +------------ +* none yet + +Significant changes and bug fixes +--------------------------------- +* none yet + +EOF + cat ChangeLog >> ChangeLog.new + mv ChangeLog.new ChangeLog + else + echo "Warning: ChangeLog already contains a ${NEXTVER} section" 1>&2 + fi + + + # Use ${release}.99 to indicate a version "newer" than anything on the branch: + if ! grep -q ${RELVER}.99 json_c_version.h ; then + local MAJOR MINOR + MAJOR=${RELVER%%.*} + MINOR=${RELVER#*.} + echo "Updating json_c_version.h to ${RELVER}.99" + sed -i \ + -e "s/#define JSON_C_MAJOR_VERSION .*/#define JSON_C_MAJOR_VERSION ${MAJOR}/" \ + -e "s/#define JSON_C_MINOR_VERSION .*/#define JSON_C_MINOR_VERSION ${MINOR}/" \ + -e "s/#define JSON_C_MICRO_VERSION .*/#define JSON_C_MICRO_VERSION 99/" \ + -e "s/#define JSON_C_VERSION \".*\"/#define JSON_C_VERSION \"${RELVER}.99\"/" \ + json_c_version.h + else + echo "Warning: json_c_version.h already contains ${RELVER}.99" 1>&2 + fi + + if ! grep -q "${RELVER}.99" CMakeLists.txt ; then + echo "Updating CMakeLists.txt to ${RELVER}.99" + sed -i \ + -e "s/project(\(.*\) VERSION .*)/project(\1 VERSION ${RELVER}.99)/" \ + CMakeLists.txt + else + echo "Warning: CMakeLists.txt already contains ${RELVER}.99" 1>&2 + fi + + local RELTAG + RELTAG=$(get_most_recent_reltag) + echo "Extracting VERSION, SOVERSION from ${RELTAG}:CMakeLists.txt" + + local REL_SOVER REL_SOVERNUM + REL_SOVER=$(git show ${RELTAG}:CMakeLists.txt | awk '/set_target_prop.*PROJECT_NAME/,/)/') + REL_VERNUM=$(echo "${REL_SOVER}" | grep " VERSION " | sed -e's/ *VERSION *//' ) + REL_SOVERNUM=$(echo "${REL_SOVER}" | grep " SOVERSION " | sed -e's/ *SOVERSION *//' -e's/)//' ) + echo " VERSION=${REL_VERNUM}" + echo " SOVERSION=${REL_SOVERNUM}" + if ! grep -q " VERSION ${REL_VERNUM}" CMakeLists.txt ; then + echo "Updating VERSION=${REL_VERNUM}, SOVERSION=${REL_VERNUM} in CMakeLists.txt to match release branch" + # Paste in the whole block from the releaes copy of CMakeLists.txt: + awk -v REL_SOVER="${REL_SOVER}" \ + '/set_target_prop.*PROJECT_NAME/,/)/ { + if (REL_SOVER) print REL_SOVER; + REL_SOVER=null; + next; + } + { print; }' \ + CMakeLists.txt > CMakeLists.txt.new + mv -f CMakeLists.txt.new CMakeLists.txt + else + echo "Warning: CMakeLists.txt already contains VERSION ${REL_VERNUM}" 1>&2 + fi + + if ! grep -q "${RELVER}.99" meson.build ; then + echo "Updating project version in meson.build to ${RELVER}.99" + sed -i -e"s/project(\(.*\)version:.*/project(\1version: '${RELVER}.99',/" meson.build + else + echo "Warning: meson.build already contains ${RELVER}.99" 1>&2 + fi + + if ! grep -q "version: *'${REL_SOVERNUM}'" meson.build ; then + echo "Updating soversion in meson.build to ${REL_VERNUM}, ${REL_SOVERNUM}" + awk -v version="'${REL_VERNUM}'" -v soversion="'${REL_SOVERNUM}'" \ + '/library\(.json-c/,/\)/ { + if ($1 == "version:") { gsub("'\''.*", version ","); } + if ($1 == "soversion:") { gsub("'\''.*", soversion ","); } + } + { print; }' < meson.build > meson.build.new + mv -f meson.build.new meson.build + else + echo "Warning: meson.build already contains soversion ${REL_VERNUM}, ${REL_SOVERNUM}" 1>&2 + fi + + if ! grep -q "JSONC_${NEXTVER}" json-c.sym; then + echo "Add a new empty section to the json-c.sym file, for ${NEXTVER}" + cat <> json-c.sym + +JSONC_${NEXTVER} { +# global: +} JSONC_${RELVER}; +EOF + else + echo "Warning: json-c-sym already has JSONC_${NEXTVER}" 1>&2 + fi + + git commit -a -m "Update the master branch to version ${release}.99" +} + +while [ $# -gt 0 ] ; do + case "$1" in + --dev) + bump_dev_ver + trap - EXIT + exit 0 + ;; + --release) + bump_release_ver + trap - EXIT + exit 0 + ;; + -h|--help) + usage 0 + ;; + *) + usage 1 "Unknown args: $*" + exit 1 + ;; + esac +done + +usage 1 "Need at least one argument" diff --git a/reltools/gen_issues_closed.sh b/reltools/gen_issues_closed.sh new file mode 100755 index 0000000..4b90363 --- /dev/null +++ b/reltools/gen_issues_closed.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -e -o pipefail + +RUNDIR=$(dirname "$0") +. "${RUNDIR}/reltools.subr" + +NEXT_VER=$(get_next_relver) + +MOST_RECENT=$(ls ${RUNDIR}/../issues_closed*md | sort -V | tail -1) +PREV=$(grep 'NOW=' "${MOST_RECENT}" | sed -e's/.*=//') +NOW=$(date +%Y-%m-%d) +set -x -v +curl -v "https://api.github.com/search/issues?q=repo%3Ajson-c%2Fjson-c+closed%3A>${PREV}+created%3A<${NOW}&sort=created&order=asc&per_page=100&page=1" > issues1.out + +set -o noclobber +NEW_FILE=issues_closed_for_${NEXT_VER}.md +cat < "${NEW_FILE}" +This list was created with: +\`\`\` +# PREV=${PREV} +# NOW=${NOW} +./reltools/gen_issues_closed.sh +\`\`\` + +EOF + +jq -r '.items[] | "[" + .title + "](" + .url + ")" | tostring' issues1.out >> "${NEW_FILE}" +sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),* [Issue #\2](https://github.com/json-c/json-c/issues/\2) - \1,' -i "${NEW_FILE}" +echo "${NEW_FILE}" + diff --git a/reltools/publish_docs.sh b/reltools/publish_docs.sh new file mode 100755 index 0000000..673f1e7 --- /dev/null +++ b/reltools/publish_docs.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# +# Publish release docs on the gh-pages branch in ~/json-c-pages +# Does NOT push changes +# + +set -e -o pipefail +trap 'echo "ERROR: Unexpected exit in $0"' EXIT + +RUNDIR=$(dirname "$0") +. "${RUNDIR}/reltools.subr" + +reltag="$1" +if [ -z "${reltag}" ] ; then + echo "Usage: $0 " 1>&2 + trap - EXIT + exit 1 +fi +release=${reltag%-*} # Strip off the date suffix +release=${release#json-c} + +cd "${HOME}" + +if [ ! -d "json-c-${release}" ] ; then + git clone https://github.com/json-c/json-c "json-c-${release}" +fi + +cd json-c-${release} +git checkout ${reltag} +if [ ! -e doc/html/index.html ] ; then + echo "ERROR: unable to find doc/html/index.html on at version ${reltag} in $(pwd)" 1>&2 + exit 1 +fi +cd .. + + +if [ ! -d json-c-pages ] ; then + git clone -b gh-pages https://github.com/json-c/json-c json-c-pages +fi +cd json-c-pages +mkdir -p json-c-${release} +cp -R ../json-c-${release}/doc json-c-${release}/. +git add json-c-${release} +rm json-c-current-release +ln -s json-c-${release} json-c-current-release +git commit -a -m "Add the ${release} docs." + +# TODO: automate changes to index.html +cat < to run vi index.html: " +vi index.html + +git commit -a -m "Update the doc links to point at ${release}" + +cat < "${JSON_C_TOP}/AUTHORS" +} + diff --git a/reltools/update_authors.sh b/reltools/update_authors.sh new file mode 100755 index 0000000..b3cbe09 --- /dev/null +++ b/reltools/update_authors.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e -o pipefail + +RUNDIR=$(dirname "$0") +TOP=${RUNDIR}/.. +. "${RUNDIR}/reltools.subr" + +update_authors() +{ + PREV=$(get_most_recent_reltag) + NEW_AUTHORS=$( git log -r ${PREV}..HEAD | grep Author: | sed -e's/Author: //' ; cat "${TOP}/AUTHORS" ) + echo "${NEW_AUTHORS}" | sort -u > "${TOP}/AUTHORS" +}