1#! /usr/bin/env bash 2 3set -euo pipefail 4 5if [ "$1" != "package" ]; then 6 if (grep -r KJ_DBG c++/src | egrep -v '/debug(-test)?[.]' | grep -v 'See KJ_DBG\.$'); then 7 echo '*** Error: There are instances of KJ_DBG in the code.' >&2 8 exit 1 9 fi 10 11 if (egrep -r 'TODO\((now|soon)\)' *); then 12 echo '*** Error: There are release-blocking TODOs in the code.' >&2 13 exit 1 14 fi 15fi 16 17doit() { 18 echo "@@@@ $@" 19 "$@" 20} 21 22get_version() { 23 local VERSION=$(grep '^AC_INIT' c++/configure.ac | sed -e 's/^[^]]*],\[\([^]]*\)].*$/\1/g') 24 if [[ ! "$VERSION" =~ $1 ]]; then 25 echo "Couldn't parse version: $VERSION" >&2 26 exit 1 27 fi 28 echo "$VERSION" 29} 30 31get_release_version() { 32 get_version '^[0-9]+[.][0-9]+[.][0-9]+(-rc[0-9]+|[.][0-9]+)?$' 33} 34 35update_version() { 36 local OLD=$1 37 local NEW=$2 38 local BRANCH_DESC=$3 39 40 local OLD_REGEX=${OLD//./[.]} 41 doit sed -i -e "s/$OLD_REGEX/$NEW/g" c++/configure.ac 42 doit sed -i -e "s/set(VERSION.*)/set(VERSION $NEW)/g" c++/CMakeLists.txt 43 44 local NEW_NOTAG=${NEW%%-*} 45 declare -a NEW_ARR=(${NEW_NOTAG//./ }) 46 doit sed -i -re " 47 s/^#define CAPNP_VERSION_MAJOR [0-9]+\$/#define CAPNP_VERSION_MAJOR ${NEW_ARR[0]}/g; 48 s/^#define CAPNP_VERSION_MINOR [0-9]+\$/#define CAPNP_VERSION_MINOR ${NEW_ARR[1]}/g; 49 s/^#define CAPNP_VERSION_MICRO [0-9]+\$/#define CAPNP_VERSION_MICRO ${NEW_ARR[2]:-0}/g" \ 50 c++/src/capnp/common.h 51 52 local NEW_COMBINED=$(( ${NEW_ARR[0]} * 1000000 + ${NEW_ARR[1]} * 1000 + ${NEW_ARR[2]:-0 })) 53 doit sed -i -re "s/^#if CAPNP_VERSION != [0-9]*\$/#if CAPNP_VERSION != $NEW_COMBINED/g" \ 54 c++/src/*/*.capnp.h c++/src/*/*/*.capnp.h 55 56 doit git commit -a -m "Set $BRANCH_DESC version to $NEW." 57} 58 59build_packages() { 60 local VERSION=$1 61 local VERSION_BASE=${VERSION%%-*} 62 63 echo "=========================================================================" 64 echo "Building C++ package..." 65 echo "=========================================================================" 66 67 # make dist tarball and move into .. 68 cd c++ 69 doit autoreconf -i 70 doit ./configure 71 doit make -j6 distcheck 72 doit mv capnproto-c++-$VERSION.tar.gz .. 73 doit make distclean 74 75 # build windows executables 76 doit ./configure --host=i686-w64-mingw32 --with-external-capnp \ 77 --disable-shared CXXFLAGS='-static-libgcc -static-libstdc++' 78 doit make -j6 capnp.exe capnpc-c++.exe capnpc-capnp.exe 79 doit i686-w64-mingw32-strip capnp.exe capnpc-c++.exe capnpc-capnp.exe 80 doit mkdir capnproto-tools-win32-$VERSION 81 doit mv capnp.exe capnpc-c++.exe capnpc-capnp.exe capnproto-tools-win32-$VERSION 82 doit make maintainer-clean 83 84 # repack dist tarball and win32 tools into win32 zip, with DOS line endings 85 doit tar zxf ../capnproto-c++-$VERSION.tar.gz 86 find capnproto-c++-$VERSION -name '*.c++' -o -name '*.h' -o -name '*.capnp' -o -name '*.md' -o -name '*.txt' | grep -v testdata | doit xargs unix2dos 87 doit zip -r ../capnproto-c++-win32-$VERSION.zip capnproto-c++-$VERSION capnproto-tools-win32-$VERSION 88 89 rm -rf capnproto-c++-$VERSION capnproto-tools-win32-$VERSION 90 cd .. 91} 92 93cherry_pick() { 94 shift 95 if [ $# -gt 0 ]; then 96 echo "=========================================================================" 97 echo "Cherry-picking fixes" 98 echo "=========================================================================" 99 doit git cherry-pick "$@" 100 fi 101} 102 103done_banner() { 104 local VERSION=$1 105 local PUSH=$2 106 local FINAL=$3 107 echo "=========================================================================" 108 echo "Done" 109 echo "=========================================================================" 110 echo "Ready to release:" 111 echo " capnproto-c++-$VERSION.tar.gz" 112 echo " capnproto-c++-win32-$VERSION.zip" 113 echo "Don't forget to push changes:" 114 echo " git push origin $PUSH" 115 116 read -s -n 1 -p "Shall I push to git and upload to capnproto.org now? (y/N)" YESNO 117 118 echo 119 case "$YESNO" in 120 y | Y ) 121 doit git push origin $PUSH 122 doit gce-ss copy-files capnproto-c++-$VERSION.tar.gz capnproto-c++-win32-$VERSION.zip \ 123 alpha2:/var/www/capnproto.org 124 125 if [ "$FINAL" = yes ]; then 126 echo "=========================================================================" 127 echo "Publishing docs" 128 echo "=========================================================================" 129 cd doc 130 doit ./push-site.sh 131 cd .. 132 echo "=========================================================================" 133 echo "Really done" 134 echo "=========================================================================" 135 fi 136 137 echo "Release is available at:" 138 echo " http://capnproto.org/capnproto-c++-$VERSION.tar.gz" 139 ;; 140 * ) 141 echo "OK, do it yourself then." 142 ;; 143 esac 144} 145 146BRANCH=$(git rev-parse --abbrev-ref HEAD) 147 148case "${1-}:$BRANCH" in 149 # ====================================================================================== 150 candidate:master ) 151 echo "New major release." 152 153 if [ $# -gt 1 ]; then 154 echo "Cannot cherry-pick when starting from master. Do it yourself." >&2 155 exit 1 156 fi 157 158 HEAD_VERSION=$(get_version '^[0-9]+[.][0-9]+-dev$') 159 RELEASE_VERSION=${HEAD_VERSION%%-dev}.0 160 161 echo "Version: $RELEASE_VERSION" 162 163 echo "=========================================================================" 164 echo "Creating release branch..." 165 echo "=========================================================================" 166 doit git checkout -b release-$RELEASE_VERSION 167 168 update_version $HEAD_VERSION $RELEASE_VERSION-rc1 "release branch" 169 170 build_packages $RELEASE_VERSION-rc1 171 172 echo "=========================================================================" 173 echo "Updating version in master branch..." 174 echo "=========================================================================" 175 176 doit git checkout master 177 declare -a VERSION_ARR=(${RELEASE_VERSION//./ }) 178 NEXT_VERSION=${VERSION_ARR[0]}.$((VERSION_ARR[1] + 1)) 179 180 update_version $HEAD_VERSION $NEXT_VERSION-dev "mainline" 181 182 done_banner $RELEASE_VERSION-rc1 "master release-$RELEASE_VERSION" no 183 ;; 184 185 # ====================================================================================== 186 candidate:release-* ) 187 echo "New release candidate." 188 OLD_VERSION=$(get_release_version) 189 190 if [[ $OLD_VERSION == *-rc* ]]; then 191 # New release candidate for existing release. 192 193 RC=${OLD_VERSION##*-rc} 194 BRANCH_VERSION=${OLD_VERSION%%-rc*} 195 RC_VERSION=$BRANCH_VERSION-rc$(( RC + 1 )) 196 197 echo "Version: $RC_VERSION" 198 else 199 # New micro release. 200 201 declare -a VERSION_ARR=(${OLD_VERSION//./ }) 202 BRANCH_VERSION=${VERSION_ARR[0]}.${VERSION_ARR[1]}.$((VERSION_ARR[2] + 1)) 203 204 RC_VERSION=$BRANCH_VERSION-rc1 205 echo "Version: $RC_VERSION" 206 207 echo "=========================================================================" 208 echo "Creating new release branch..." 209 echo "=========================================================================" 210 211 doit git checkout -b release-$BRANCH_VERSION 212 fi 213 214 echo "=========================================================================" 215 echo "Updating version number to $RC_VERSION..." 216 echo "=========================================================================" 217 218 update_version $OLD_VERSION $RC_VERSION "release branch" 219 220 cherry_pick "$@" 221 222 build_packages $RC_VERSION 223 224 done_banner $RC_VERSION release-$BRANCH_VERSION no 225 ;; 226 227 # ====================================================================================== 228 final:release-* ) 229 echo "Final release." 230 OLD_VERSION=$(get_release_version) 231 232 if [[ $OLD_VERSION != *-rc* ]]; then 233 echo "Current version is already a final release. You need to create a new candidate first." >&2 234 exit 1 235 fi 236 237 if [ $# -gt 1 ]; then 238 echo "Cannot cherry-pick into final release. Make another candidate." >&2 239 exit 1 240 fi 241 242 RC=${OLD_VERSION##*-rc} 243 NEW_VERSION=${OLD_VERSION%%-rc*} 244 245 echo "Version: $NEW_VERSION" 246 247 echo "=========================================================================" 248 echo "Updating version number to $NEW_VERSION..." 249 echo "=========================================================================" 250 251 doit sed -i -re "s/capnproto-c[+][+]-[0-9]+[.][0-9]+[.][0-9]+([.][0-9]+)?\>/capnproto-c++-$NEW_VERSION/g" doc/install.md 252 doit sed -i -re "s/capnproto-c[+][+]-win32-[0-9]+[.][0-9]+[.][0-9]+([.][0-9]+)?\>/capnproto-c++-win32-$NEW_VERSION/g" doc/install.md 253 doit sed -i -re "s/capnproto-tools-win32-[0-9]+[.][0-9]+[.][0-9]+([.][0-9]+)?\>/capnproto-tools-win32-$NEW_VERSION/g" doc/install.md 254 update_version $OLD_VERSION $NEW_VERSION "release branch" 255 256 doit git tag v$NEW_VERSION 257 258 build_packages $NEW_VERSION 259 260 done_banner $NEW_VERSION "v$NEW_VERSION release-$NEW_VERSION" yes 261 ;; 262 263 # ====================================================================================== 264 security:release-* ) 265 echo "Security release." 266 OLD_VERSION=$(get_release_version) 267 268 if [[ $OLD_VERSION == *-rc* ]]; then 269 echo "Security releases don't have candidates." >&2 270 exit 1 271 fi 272 273 declare -a VERSION_ARR=(${OLD_VERSION//./ } 0) 274 NEW_VERSION=${VERSION_ARR[0]}.${VERSION_ARR[1]}.${VERSION_ARR[2]}.$((VERSION_ARR[3] + 1)) 275 276 echo "Version: $NEW_VERSION" 277 278 echo "=========================================================================" 279 echo "Updating version number to $NEW_VERSION..." 280 echo "=========================================================================" 281 282 doit sed -i -re "s/capnproto-c[+][+]-[0-9]+[.][0-9]+[.][0-9]+([.][0-9]+)?\>/capnproto-c++-$NEW_VERSION/g" doc/install.md 283 doit sed -i -re "s/capnproto-c[+][+]-win32-[0-9]+[.][0-9]+[.][0-9]+([.][0-9]+)?\>/capnproto-c++-win32-$NEW_VERSION/g" doc/install.md 284 doit sed -i -re "s/capnproto-tools-win32-[0-9]+[.][0-9]+[.][0-9]+([.][0-9]+)?\>/capnproto-tools-win32-$NEW_VERSION/g" doc/install.md 285 update_version $OLD_VERSION $NEW_VERSION "release branch" 286 287 cherry_pick "$@" 288 289 doit git tag v$NEW_VERSION 290 291 build_packages $NEW_VERSION 292 293 done_banner $NEW_VERSION "v$NEW_VERSION release-$NEW_VERSION" yes 294 ;; 295 296 # ====================================================================================== 297 retry:release-* ) 298 echo "Retrying release." 299 OLD_VERSION=$(get_release_version) 300 echo "Version: $OLD_VERSION" 301 302 if [[ $OLD_VERSION == *-rc* ]]; then 303 # We can add more cherry-picks when retrying a candidate. 304 cherry_pick "$@" 305 else 306 if [ $# -gt 1 ]; then 307 echo "Cannot cherry-pick into final release. Make another candidate." >&2 308 exit 1 309 fi 310 fi 311 312 OLD_VERSION=$(get_release_version) 313 build_packages $OLD_VERSION 314 315 if [[ $OLD_VERSION == *-rc* ]]; then 316 BRANCH_VERSION=${OLD_VERSION%%-rc*} 317 done_banner $OLD_VERSION release-$BRANCH_VERSION no 318 else 319 doit git tag v$OLD_VERSION 320 done_banner $OLD_VERSION "v$OLD_VERSION release-$OLD_VERSION" no 321 fi 322 ;; 323 324 # ====================================================================================== 325 package:* ) 326 echo "Just building a package." 327 build_packages $(get_version '.*') 328 ;; 329 330 # ====================================================================================== 331 *:master ) 332 echo "Invalid command for mainline branch. Only command is 'candidate'." >&2 333 exit 1 334 ;; 335 336 *:release-* ) 337 echo "Invalid command for release branch. Commands are 'candidate', 'final', and 'retry'." >&2 338 exit 1 339 ;; 340 341 * ) 342 echo "Not a master or release branch." >&2 343 exit 1 344 ;; 345esac 346