2 # release.sh: openocd release process automation
3 # Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net>
4 # Release under the GNU GPL v2 (or later versions).
6 ## set these to control the build process
10 ## DO NOT PERFORM LIVE RELEASES UNLESS YOU ARE THE RELEASE MANAGER!!!
12 ## set this to perform individual steps on past releases
21 svn info | grep "$1" | cut -d':' -f2- | cut -c2-
25 SVN_ROOT="$(svn_info_get 'Repository Root')"
26 SVN_URL="$(svn_info_get 'URL')"
28 SVN_TRUNK="${SVN_ROOT}/trunk"
30 SVN_BRANCHES="${SVN_ROOT}/branches"
31 PACKAGE_BRANCH="${SVN_BRANCHES}/${PACKAGE_RELEASE}"
33 SVN_TAGS="${SVN_ROOT}/tags"
34 PACKAGE_TAG="${SVN_TAGS}/${PACKAGE_RELEASE}"
36 if [ "${SVN_URL}" = "${SVN_TRUNK}" ]; then
38 elif [ "${SVN_URL/${SVN_BRANCHES}/}" != "${SVN_URL}" ]; then
41 echo "error: bad URL: ${SVN_URL}" >&2
42 die "unable to branch from the current location"
47 Release Type: ${RELEASE_TYPE}
48 Branch URL: ${PACKAGE_BRANCH}
49 Tag URL: ${PACKAGE_TAG}
53 do_svn_echo_msg() { echo "svn: $1: $3"; }
59 [ "$*" ] && echo "Files: $@"
69 echo "svn: ${ACTION}: $@"
75 [ "${RELEASE_DRY_RUN}" ] || svn "$@"
83 package_info_load_name() {
84 grep AC_INIT configure.in | perl -ne 's/^.+\(\[([-\w]*)\],.+$/$1/ and print'
86 package_info_load_version() {
87 grep AC_INIT configure.in | perl -ne 's/^.+\[([-\w\.]*)\],$/$1/ and print'
91 [ -f "configure.in" ] || \
92 die "package_info_load: configure.in is missing"
94 PACKAGE_NAME="$(package_info_load_name)"
96 PACKAGE_TARNAME="${PACKAGE_NAME}"
98 PACKAGE_VERSION="$(package_info_load_version)"
99 [ "${RELEASE_VERSION}" ] || \
100 RELEASE_VERSION=${PACKAGE_VERSION/-in-development/}
102 [ "${PACKAGE_NAME}" -a "${PACKAGE_VERSION}" ] || \
103 die "package information is missing from configure script"
105 PACKAGE_VERSION_TAGS=
106 [ "${PACKAGE_VERSION/-/}" = "${PACKAGE_VERSION}" ] || \
107 PACKAGE_VERSION_TAGS="-${PACKAGE_VERSION#*-}"
108 PACKAGE_VERSION_BASE="${PACKAGE_VERSION%%-*}"
109 PACKAGE_MICRO="${PACKAGE_VERSION_BASE##*.}"
110 PACKAGE_MAJOR_AND_MINOR="${PACKAGE_VERSION_BASE%.*}"
111 PACKAGE_MAJOR="${PACKAGE_MAJOR_AND_MINOR%.*}"
112 PACKAGE_MINOR="${PACKAGE_MAJOR_AND_MINOR#*.}"
114 PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
115 if [ "${RELEASE_DRY_RUN}" ]; then
116 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${PACKAGE_VERSION}"
118 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${RELEASE_VERSION}"
122 package_info_show() {
124 Name: ${PACKAGE_TARNAME}
125 Release: ${RELEASE_VERSION}
126 Version: ${PACKAGE_VERSION}
127 Number: ${PACKAGE_VERSION_BASE}
128 Series: ${PACKAGE_MAJOR_AND_MINOR}
129 Major: ${PACKAGE_MAJOR}
130 Minor: ${PACKAGE_MINOR}
131 Micro: ${PACKAGE_MICRO}
132 Tags: ${PACKAGE_VERSION_TAGS}
133 Branch: ${PACKAGE_RELEASE}
134 Release: ${PACKAGE_TARNAME}-${PACKAGE_VERSION_BASE}${PACKAGE_VERSION_TAGS}
143 info Show a summary of the next pending release.
144 release Release the current tree as an archive.
145 upload Upload archives to berliOS project site
148 bootstrap Prepare the working copy for configuration and building.
149 configure Configures the package; runs bootstrap, if needed.
150 build Compiles the project; runs configure, if needed.
153 changelog Generate a new ChangeLog using svn2cl.
154 package Produce new distributable source archives.
155 stage Move archives to staging area for upload.
158 commit Perform branch and tag, as appropriate for the version.
159 branch Create a release branch from the project trunk.
160 tag Create a tag for the current release branch.
163 version ... Perform version number and tag manipulations.
164 maryslamb Mary had a little lamb, but no one noticed.
165 clean Forces regeneration of results.
166 clean_all Removes all traces of the release process.
167 help Provides this list of commands.
169 For more information about this script, see the Release Processes page
170 in the OpenOCD Developer's Manual (doc/manual/release.txt).
172 WARNING: This script should be used by the Release Manager ONLY.
176 do_usage() { usage; }
180 echo "Current Release Analysis:"
192 echo -n "Bootstrapping..."
193 ./bootstrap 2>&1 | perl tools/logger.pl > "release-bootstrap.log"
195 maybe_bootstrap() { [ -f "configure" ] || do_bootstrap; }
199 echo -n "Configuring..."
200 ./configure ${CONFIG_OPTS} 2>&1 | perl tools/logger.pl > "release-config.log"
202 maybe_configure() { [ -f "Makefile" ] || do_configure; }
206 echo -n "Compiling OpenOCD ${PACKAGE_VERSION}"
207 make ${MAKE_OPTS} -C doc stamp-vti 2>&1 \
208 | perl tools/logger.pl > "release-version.log"
209 make ${MAKE_OPTS} 2>&1 \
210 | perl tools/logger.pl > "release-make.log"
212 maybe_build() { [ -f "src/openocd" ] || do_build; }
213 do_build_clean() { [ -f Makefile ] && make maintainer-clean >/dev/null; }
216 if [ -f "configure" ]; then
217 echo "Re-running autoconf..."
219 echo "Re-running automake..."
222 if [ -f "Makefile" ]; then
229 echo "Updating working copy to HEAD..."
231 echo "Creating ChangeLog..."
232 svn2cl -i --authors AUTHORS.ChangeLog
235 if [ -z "${RELEASE_DRY_RUN}" ] \
236 || [ ! -f ChangeLog ] \
237 || [ "$(cat ChangeLog | wc -l)" -lt 2 ]
242 do_changelog_clean() {
243 do_svn revert ChangeLog
250 echo "Building distribution packages..."
251 make ${MAKE_OPTS} distcheck 2>&1 | perl tools/logger.pl > "release-pkg.log"
253 maybe_package() { [ -f "${PACKAGE_RELEASE}.zip" ] || do_package; }
255 for EXT in tar.gz tar.bz2 zip; do
262 echo "Staging package archives:"
264 for EXT in tar.gz tar.bz2 zip; do
265 local FILE="${PACKAGE_RELEASE}.${EXT}"
266 # create archive signatures
267 for HASH in md5 sha1; do
268 echo "sign: ${FILE}.${HASH}"
269 ${HASH}sum "${FILE}" > "archives/${FILE}.${HASH}"
272 mv -v "${FILE}" archives/
275 cp -a ChangeLog archives/
277 do_stage_clean() { rm -v -f -r archives; }
284 svn revert configure.in
285 rm -v -f release-*.log
295 usage: $0 version <command>
297 tag {add|remove} <label> Add or remove the specified tag.
298 bump {major|minor|micro|rc} Bump the specified version number;
299 resets less-significant numbers to zero.
300 All but 'rc' releases drop that tag.
305 local OLD_VERSION="${PACKAGE_VERSION}"
306 local NEW_VERSION="$1"
309 sed -i -e "/AC_INIT/ s|${OLD_VERSION}|${NEW_VERSION}|" configure.in
311 echo "${MSG}: ${OLD_VERSION} -> ${NEW_VERSION}"
313 do_version_bump_sed() {
314 local NEW_VERSION="$1"
315 [ -z "${PACKAGE_VERSION_TAGS}" ] || \
316 NEW_VERSION="${NEW_VERSION}${PACKAGE_VERSION_TAGS}"
318 do_version_sed "${NEW_VERSION}" \
319 "Bump ${CMD} package version number"
321 do_version_bump_major() {
322 has_version_tag 'rc\d' do_version_
323 do_version_bump_sed "$((PACKAGE_MAJOR + 1)).0.0"
325 do_version_bump_minor() {
326 do_version_bump_sed "${PACKAGE_MAJOR}.$((PACKAGE_MINOR + 1)).0"
328 do_version_bump_micro() {
329 do_version_bump_sed "${PACKAGE_MAJOR_AND_MINOR}.$((PACKAGE_MICRO + 1))"
331 do_version_bump_rc() {
332 die "patch missing: -rc support is not implemented"
338 major|minor|micro|rc)
339 eval "do_version_bump_${CMD}"
348 test "${PACKAGE_VERSION/-${TAG}/}" != "${PACKAGE_VERSION}"
351 do_version_tag_add() {
353 has_version_tag && die "error: tag '-${TAG}' exists in '${PACKAGE_VERSION}'"
354 do_version_sed "${PACKAGE_VERSION}-${TAG}" \
355 "Add '-${TAG}' version tag"
357 do_version_tag_remove() {
359 has_version_tag || die "error: tag '-${TAG}' missing from '${PACKAGE_VERSION}'"
360 do_version_sed "${PACKAGE_VERSION/-${TAG}/}" \
361 "Remove '-${TAG}' version tag"
370 eval "do_version_tag_${CMD}" "${i}"
379 do_version_commit() {
380 [ "$(svn diff configure.in | wc -l)" -gt 0 ] || \
381 die "error: no version changes to commit"
382 do_svn commit -m "$1" configure.in
391 do_version_commit "$(eval "do_version_${CMD}" "$@")"
396 [ "${MSG}" ] || die "usage: $0 version commit <message>"
397 do_version_commit "${MSG}"
410 do_svn copy -m "Branching version ${PACKAGE_VERSION}" \
411 "${SVN_TRUNK}" "${PACKAGE_BRANCH}"
416 do_svn copy -m "Tagging version ${PACKAGE_VERSION}" \
417 "${PACKAGE_BRANCH}" "${PACKAGE_TAG}"
423 [ "${PACKAGE_VERSION/in-development/}" = "${PACKAGE_VERSION}" ] || \
424 die "'${PACKAGE_NAME}-${PACKAGE_VERSION}' cannot be released"
426 [ "${PACKAGE_VERSION%.0}" = "${PACKAGE_VERSION}" ] || \
432 do_release_step_prep() {
433 do_version tag remove in-development
434 # reset RELEASE_VERSION now to allow release version to be detected
435 export RELEASE_VERSION=
437 do_release_step_commit() { do_commit; }
439 do_release_step_branch_bump() {
441 echo "Bump ${TYPE} version and add tag:"
442 do_version_bump ${TYPE}
443 do_version_tag_add in-development
445 do_release_step_branch() {
446 do_svn_switch "${PACKAGE_BRANCH}"
447 do_version_commit "$(do_release_step_branch_bump micro)"
448 do_svn_switch "${SVN_URL}"
450 do_release_step_news_msg() {
452 Archive released NEWS file: NEWS -> NEWS-${RELEASE_VERSION}
453 Create new NEWS file from relesse script template.
456 do_release_step_news() {
457 # archive NEWS and create new one from template
458 do_svn move "NEWS" "NEWS-${RELEASE_VERSION}"
460 [ "${RELEASE_DRY_RUN}" ] || cat >NEWS <<NEWS
461 This file should include items worth mentioning in the
462 OpenOCD ${PACKAGE_RELEASE} source archive release.
464 The following areas of OpenOCD functionality changed in this release:
469 Board, Target, and Interface Configuration Scripts:
473 For more details about what has changed since the last release,
474 see the ChangeLog associated with this source archive. For older NEWS,
475 see the NEWS files associated with each release (i.e. NEWS-<version>).
477 For more information about contributing test reports, bug fixes, or new
478 features and device support, please read the new Developer Manual (or
479 the BUGS and PATCHES files in the source archive).
483 local MSG="$(do_release_step_news_msg)"
484 do_svn commit -m "${MSG}" NEWS NEWS-${RELEASE_VERSION}
486 do_release_step_bump() {
487 # major and minor releases require branch version update too
488 [ "${RELEASE_TYPE}" = "micro" ] || do_release_step_branch
489 # bump the current tree version as required.
490 do_version_commit "$(do_release_step_branch_bump "${RELEASE_TYPE}")"
492 [ "${RELEASE_TYPE}" = "micro" ] || do_release_step_news
494 do_release_step_package() {
495 local A=${PACKAGE_TAG}
496 local B=${A/https/http}
497 local PACKAGE_BUILD=${B/${USER}@/}
498 do_svn_switch "${PACKAGE_TAG}"
499 do_svn_switch --relocate "${PACKAGE_TAG}" "${PACKAGE_BUILD}"
502 do_svn_switch --relocate "${PACKAGE_BUILD}" "${PACKAGE_TAG}"
503 do_svn_switch "${SVN_URL}"
506 do_release_step_1() { do_release_step_prep; }
507 do_release_step_2() { do_release_step_commit; }
508 do_release_step_3() { do_release_step_bump; }
509 do_release_step_4() { do_release_step_package; }
512 echo -n "Are you sure you want to release '${PACKAGE_RELEASE}'?"
514 if [ "${ANSWER}" != 'y' ]; then
515 echo "Live release aborted!"
521 for i in $(seq 5 -1 1); do
531 if [ -z "${RELEASE_DRY_RUN}" ]; then
533 do_countdown "Starting live release"
537 for i in $(seq 1 4); do
538 eval "do_release_step_${i}"
541 do_all() { do_release "$@"; }
547 svn revert configure.in
550 OPTIONS=$(getopt -o V --long live -n $0 -- "$@")
551 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
552 eval set -- "${OPTIONS}"
556 export RELEASE_DRY_RUN=
567 echo "Internal error"
574 [ "${CMD}" ] || usage
577 ACTION_CMDS="bootstrap|configure|build|changelog|package|stage|clean"
578 MISC_CMDS="all|info|version|tag|branch|commit|release|reset|help|usage"
579 CLEAN_CMDS="build_clean|changelog_clean|package_clean|stage_clean|clean_all"
580 CMDS="|${ACTION_CMDS}|${CLEAN_CMDS}|${MISC_CMDS}|"
581 is_command() { echo "${CMDS}" | grep "|$1|" >/dev/null; }
583 if is_command "${CMD}"; then
584 eval "do_${CMD}" "$@"
586 echo "error: unknown command: '${CMD}'"