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 "$@"
79 package_info_load_name() {
80 grep AC_INIT configure.in | perl -ne 's/^.+\(\[([-\w]*)\],.+$/$1/ and print'
82 package_info_load_version() {
83 grep AC_INIT configure.in | perl -ne 's/^.+\[([-\w\.]*)\],$/$1/ and print'
87 [ -f "configure.in" ] || \
88 die "package_info_load: configure.in is missing"
90 PACKAGE_NAME="$(package_info_load_name)"
92 PACKAGE_TARNAME="${PACKAGE_NAME}"
94 PACKAGE_VERSION="$(package_info_load_version)"
95 [ "${RELEASE_VERSION}" ] || \
96 RELEASE_VERSION=${PACKAGE_VERSION/-in-development/}
98 [ "${PACKAGE_NAME}" -a "${PACKAGE_VERSION}" ] || \
99 die "package information is missing from configure script"
101 PACKAGE_VERSION_TAGS=
102 [ "${PACKAGE_VERSION/-/}" = "${PACKAGE_VERSION}" ] || \
103 PACKAGE_VERSION_TAGS="-${PACKAGE_VERSION#*-}"
104 PACKAGE_VERSION_BASE="${PACKAGE_VERSION%%-*}"
105 PACKAGE_MICRO="${PACKAGE_VERSION_BASE##*.}"
106 PACKAGE_MAJOR_AND_MINOR="${PACKAGE_VERSION_BASE%.*}"
107 PACKAGE_MAJOR="${PACKAGE_MAJOR_AND_MINOR%.*}"
108 PACKAGE_MINOR="${PACKAGE_MAJOR_AND_MINOR#*.}"
110 PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
111 if [ "${RELEASE_DRY_RUN}" ]; then
112 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${PACKAGE_VERSION}"
114 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${RELEASE_VERSION}"
118 package_info_show() {
120 Name: ${PACKAGE_TARNAME}
121 Release: ${RELEASE_VERSION}
122 Version: ${PACKAGE_VERSION}
123 Number: ${PACKAGE_VERSION_BASE}
124 Series: ${PACKAGE_MAJOR_AND_MINOR}
125 Major: ${PACKAGE_MAJOR}
126 Minor: ${PACKAGE_MINOR}
127 Micro: ${PACKAGE_MICRO}
128 Tags: ${PACKAGE_VERSION_TAGS}
129 Branch: ${PACKAGE_RELEASE}
130 Release: ${PACKAGE_TARNAME}-${PACKAGE_VERSION_BASE}${PACKAGE_VERSION_TAGS}
139 info Show a summary of the next pending release.
140 release Release the current tree as an archive.
141 upload Upload archives to berliOS project site
144 bootstrap Prepare the working copy for configuration and building.
145 configure Configures the package; runs bootstrap, if needed.
146 build Compiles the project; runs configure, if needed.
149 changelog Generate a new ChangeLog using svn2cl.
150 package Produce new distributable source archives.
151 stage Move archives to staging area for upload.
154 commit Perform branch and tag, as appropriate for the version.
155 branch Create a release branch from the project trunk.
156 tag Create a tag for the current release branch.
159 version ... Perform version number and tag manipulations.
160 maryslamb Mary had a little lamb, but no one noticed.
161 clean Forces regeneration of results.
162 clean_all Removes all traces of the release process.
163 help Provides this list of commands.
165 For more information about this script, see the Release Processes page
166 in the OpenOCD Developer's Manual (doc/manual/release.txt).
168 WARNING: This script should be used by the Release Manager ONLY.
172 do_usage() { usage; }
176 echo "Current Release Analysis:"
188 echo -n "Bootstrapping..."
189 ./bootstrap 2>&1 | perl tools/logger.pl > "release-bootstrap.log"
191 maybe_bootstrap() { [ -f "configure" ] || do_bootstrap; }
195 echo -n "Configuring..."
196 ./configure ${CONFIG_OPTS} 2>&1 | perl tools/logger.pl > "release-config.log"
198 maybe_configure() { [ -f "Makefile" ] || do_configure; }
202 echo -n "Compiling OpenOCD ${PACKAGE_VERSION}"
203 make ${MAKE_OPTS} -C doc stamp-vti 2>&1 \
204 | perl tools/logger.pl > "release-version.log"
205 make ${MAKE_OPTS} 2>&1 \
206 | perl tools/logger.pl > "release-make.log"
208 maybe_build() { [ -f "src/openocd" ] || do_build; }
209 do_build_clean() { [ -f Makefile ] && make maintainer-clean >/dev/null; }
212 if [ -f "configure" ]; then
213 echo "Re-running autoconf..."
215 echo "Re-running automake..."
218 if [ -f "Makefile" ]; then
225 echo "Updating working copy to HEAD..."
227 echo "Creating ChangeLog..."
228 svn2cl -i --authors AUTHORS.ChangeLog
231 if [ -z "${RELEASE_DRY_RUN}" ] \
232 || [ ! -f ChangeLog ] \
233 || [ "$(cat ChangeLog | wc -l)" -lt 2 ]
238 do_changelog_clean() {
239 do_svn revert ChangeLog
246 echo "Building distribution packages..."
247 make ${MAKE_OPTS} distcheck 2>&1 | perl tools/logger.pl > "release-pkg.log"
249 maybe_package() { [ -f "${PACKAGE_RELEASE}.zip" ] || do_package; }
251 for EXT in tar.gz tar.bz2 zip; do
258 echo "Staging package archives:"
260 for EXT in tar.gz tar.bz2 zip; do
261 mv -v "${PACKAGE_RELEASE}.${EXT}" archives/
264 cp -a ChangeLog archives/
266 do_stage_clean() { rm -v -f -r archives; }
273 svn revert configure.in
274 rm -v -f release-*.log
284 usage: $0 version <command>
286 tag {add|remove} <label> Add or remove the specified tag.
287 bump {major|minor|micro|rc} Bump the specified version number;
288 resets less-significant numbers to zero.
289 All but 'rc' releases drop that tag.
294 local OLD_VERSION="${PACKAGE_VERSION}"
295 local NEW_VERSION="$1"
298 sed -i -e "/AC_INIT/ s|${OLD_VERSION}|${NEW_VERSION}|" configure.in
300 echo "${MSG}: ${OLD_VERSION} -> ${NEW_VERSION}"
302 do_version_bump_sed() {
303 local NEW_VERSION="$1"
304 [ -z "${PACKAGE_VERSION_TAGS}" ] || \
305 NEW_VERSION="${NEW_VERSION}${PACKAGE_VERSION_TAGS}"
307 do_version_sed "${NEW_VERSION}" \
308 "Bump ${CMD} package version number"
310 do_version_bump_major() {
311 has_version_tag 'rc\d' do_version_
312 do_version_bump_sed "$((PACKAGE_MAJOR + 1)).0.0"
314 do_version_bump_minor() {
315 do_version_bump_sed "${PACKAGE_MAJOR}.$((PACKAGE_MINOR + 1)).0"
317 do_version_bump_micro() {
318 do_version_bump_sed "${PACKAGE_MAJOR_AND_MINOR}.$((PACKAGE_MICRO + 1))"
320 do_version_bump_rc() {
321 die "patch missing: -rc support is not implemented"
327 major|minor|micro|rc)
328 eval "do_version_bump_${CMD}"
337 test "${PACKAGE_VERSION/-${TAG}/}" != "${PACKAGE_VERSION}"
340 do_version_tag_add() {
342 has_version_tag && die "error: tag '-${TAG}' exists in '${PACKAGE_VERSION}'"
343 do_version_sed "${PACKAGE_VERSION}-${TAG}" \
344 "Add '-${TAG}' version tag"
346 do_version_tag_remove() {
348 has_version_tag || die "error: tag '-${TAG}' missing from '${PACKAGE_VERSION}'"
349 do_version_sed "${PACKAGE_VERSION/-${TAG}/}" \
350 "Remove '-${TAG}' version tag"
359 eval "do_version_tag_${CMD}" "${i}"
368 do_version_commit() {
369 [ "$(svn diff configure.in | wc -l)" -gt 0 ] || \
370 die "error: no version changes to commit"
371 do_svn commit -m "$1" configure.in
380 do_version_commit "$(eval "do_version_${CMD}" "$@")"
385 [ "${MSG}" ] || die "usage: $0 version commit <message>"
386 do_version_commit "${MSG}"
399 do_svn copy -m "Branching version ${PACKAGE_VERSION}" \
400 "${SVN_TRUNK}" "${PACKAGE_BRANCH}"
405 do_svn copy -m "Tagging version ${PACKAGE_VERSION}" \
406 "${PACKAGE_BRANCH}" "${PACKAGE_TAG}"
412 [ "${PACKAGE_VERSION/in-development/}" = "${PACKAGE_VERSION}" ] || \
413 die "'${PACKAGE_NAME}-${PACKAGE_VERSION}' cannot be released"
415 [ "${PACKAGE_VERSION%.0}" = "${PACKAGE_VERSION}" ] || \
421 do_release_step_prep() {
422 do_version tag remove in-development
423 # reset RELEASE_VERSION now to allow release version to be detected
424 export RELEASE_VERSION=
426 do_release_step_commit() { do_commit; }
428 do_release_step_branch_bump() {
430 echo "Bump ${TYPE} version and add tag:"
431 do_version_bump ${TYPE}
432 do_version_tag_add in-development
434 do_release_step_branch() {
435 do_svn switch "${PACKAGE_BRANCH}"
437 do_version_commit "$(do_release_step_branch_bump micro)"
438 do_svn switch "${SVN_URL}"
441 do_release_step_bump() {
442 # major and minor releases require branch version update too
443 [ "${RELEASE_TYPE}" = "micro" ] || do_release_step_branch
444 # bump the current tree version as required.
445 do_version_commit "$(do_release_step_branch_bump "${RELEASE_TYPE}")"
447 # archive NEWS and create new one from template
448 do_svn move "NEWS" "NEWS-${RELEASE_VERSION}"
450 [ "${RELEASE_DRY_RUN}" ] || cat >NEWS <<NEWS
451 This file should include items worth mentioning in the
452 OpenOCD ${PACKAGE_RELEASE} source archive release.
454 The following areas of OpenOCD functionality changed in this release:
459 Board, Target, and Interface Configuration Scripts:
463 For more details about what has changed since the last release,
464 see the ChangeLog associated with this source archive. For older NEWS,
465 see the NEWS files associated with each release (i.e. NEWS-<version>).
467 For more information about contributing test reports, bug fixes, or new
468 features and device support, please read the new Developer Manual (or
469 the BUGS and PATCHES files in the source archive).
473 Archive released NEWS file: NEWS -> NEWS-${RELEASE_VERSION}
474 Create new NEWS file from relesse script template.
476 do_svn commit -m "${MSG}" NEWS NEWS-${RELEASE_VERSION}
478 do_release_step_package() {
479 local A=${PACKAGE_TAG}
480 local B=${A/https/http}
481 local PACKAGE_BUILD=${B/${USER}@/}
482 do_svn switch "${PACKAGE_BUILD}"
487 do_release_step_1() { do_release_step_prep; }
488 do_release_step_2() { do_release_step_commit; }
489 do_release_step_3() { do_release_step_bump; }
490 do_release_step_4() { do_release_step_package; }
493 echo -n "Are you sure you want to release '${PACKAGE_RELEASE}'?"
495 if [ "${ANSWER}" != 'y' ]; then
496 echo "Live release aborted!"
502 for i in $(seq 5 -1 1); do
512 if [ -z "${RELEASE_DRY_RUN}" ]; then
514 do_countdown "Starting live release"
518 for i in $(seq 1 4); do
519 eval "do_release_step_${i}"
522 do_all() { do_release "$@"; }
528 svn revert configure.in
531 OPTIONS=$(getopt -o V --long live -n $0 -- "$@")
532 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
533 eval set -- "${OPTIONS}"
537 export RELEASE_DRY_RUN=
548 echo "Internal error"
555 [ "${CMD}" ] || usage
558 ACTION_CMDS="bootstrap|configure|build|changelog|package|stage|clean"
559 MISC_CMDS="all|info|version|tag|branch|commit|release|reset|help|usage"
560 CLEAN_CMDS="build_clean|changelog_clean|package_clean|stage_clean|clean_all"
561 CMDS="|${ACTION_CMDS}|${CLEAN_CMDS}|${MISC_CMDS}|"
562 is_command() { echo "${CMDS}" | grep "|$1|" >/dev/null; }
564 if is_command "${CMD}"; then
565 eval "do_${CMD}" "$@"
567 echo "error: unknown command: '${CMD}'"