Improve the release script before 0.2.0:
[openocd.git] / tools / release.sh
1 #!/bin/sh -e
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).
5
6 ## set these to control the build process
7 #CONFIG_OPTS=""
8 #MAKE_OPTS=""
9
10 ## DO NOT PERFORM LIVE RELEASES UNLESS YOU ARE THE RELEASE MANAGER!!!
11 RELEASE_DRY_RUN=1
12 ## set this to perform individual steps on past releases
13 RELEASE_VERSION=
14
15 die() {
16 echo "$@" >&2
17 exit 1
18 }
19
20 svn_info_get() {
21 svn info | grep "$1" | cut -d':' -f2- | cut -c2-
22 }
23
24 svn_setup_load() {
25 SVN_ROOT="$(svn_info_get 'Repository Root')"
26 SVN_URL="$(svn_info_get 'URL')"
27
28 SVN_TRUNK="${SVN_ROOT}/trunk"
29
30 SVN_BRANCHES="${SVN_ROOT}/branches"
31 PACKAGE_BRANCH="${SVN_BRANCHES}/${PACKAGE_RELEASE}"
32
33 SVN_TAGS="${SVN_ROOT}/tags"
34 PACKAGE_TAG="${SVN_TAGS}/${PACKAGE_RELEASE}"
35
36 if [ "${SVN_URL}" = "${SVN_TRUNK}" ]; then
37 RELEASE_TYPE=minor
38 elif [ "${SVN_URL/${SVN_BRANCHES}/}" != "${SVN_URL}" ]; then
39 RELEASE_TYPE=micro
40 else
41 echo "error: bad URL: ${SVN_URL}" >&2
42 die "unable to branch from the current location"
43 fi
44 }
45 svn_setup_show() {
46 cat <<INFO
47 Release Type: ${RELEASE_TYPE}
48 Branch URL: ${PACKAGE_BRANCH}
49 Tag URL: ${PACKAGE_TAG}
50 INFO
51 }
52
53 do_svn_echo_msg() { echo "svn: $1: $3"; }
54 do_svn_echo() {
55 case "$1" in
56 commit)
57 do_svn_echo_msg "$@"
58 shift 3
59 [ "$*" ] && echo "Files: $@"
60 ;;
61 copy|move)
62 do_svn_echo_msg "$@"
63 echo "From: ${4:-$2}"
64 echo " To: ${5:-$3}"
65 ;;
66 *)
67 local ACTION="$1"
68 shift
69 echo "svn: ${ACTION}: $@"
70 ;;
71 esac
72 }
73 do_svn() {
74 do_svn_echo "$@"
75 [ "${RELEASE_DRY_RUN}" ] || svn "$@"
76 }
77 do_svn_switch() {
78 do_svn switch "$1"
79 package_info_load
80 }
81
82
83 package_info_load_name() {
84 grep AC_INIT configure.in | perl -ne 's/^.+\(\[([-\w]*)\],.+$/$1/ and print'
85 }
86 package_info_load_version() {
87 grep AC_INIT configure.in | perl -ne 's/^.+\[([-\w\.]*)\],$/$1/ and print'
88 }
89
90 package_info_load() {
91 [ -f "configure.in" ] || \
92 die "package_info_load: configure.in is missing"
93
94 PACKAGE_NAME="$(package_info_load_name)"
95 # todo: fix this
96 PACKAGE_TARNAME="${PACKAGE_NAME}"
97
98 PACKAGE_VERSION="$(package_info_load_version)"
99 [ "${RELEASE_VERSION}" ] || \
100 RELEASE_VERSION=${PACKAGE_VERSION/-in-development/}
101
102 [ "${PACKAGE_NAME}" -a "${PACKAGE_VERSION}" ] || \
103 die "package information is missing from configure script"
104
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#*.}"
113
114 PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
115 if [ "${RELEASE_DRY_RUN}" ]; then
116 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${PACKAGE_VERSION}"
117 else
118 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${RELEASE_VERSION}"
119 fi
120 }
121
122 package_info_show() {
123 cat <<INFO
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}
135 INFO
136 }
137
138 usage() {
139 cat << USAGE
140 usage: $0 <command>
141
142 Main Commands:
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
146
147 Build Commands:
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.
151
152 Packaging Commands:
153 changelog Generate a new ChangeLog using svn2cl.
154 package Produce new distributable source archives.
155 stage Move archives to staging area for upload.
156
157 Repository Commands:
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.
161
162 Other Commands:
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.
168
169 For more information about this script, see the Release Processes page
170 in the OpenOCD Developer's Manual (doc/manual/release.txt).
171
172 WARNING: This script should be used by the Release Manager ONLY.
173 USAGE
174 exit 0
175 }
176 do_usage() { usage; }
177 do_help() { usage; }
178
179 do_info_show() {
180 echo "Current Release Analysis:"
181 package_info_show
182 svn_setup_show
183 }
184
185 do_info() {
186 package_info_load
187 svn_setup_load
188 do_info_show
189 }
190
191 do_bootstrap() {
192 echo -n "Bootstrapping..."
193 ./bootstrap 2>&1 | perl tools/logger.pl > "release-bootstrap.log"
194 }
195 maybe_bootstrap() { [ -f "configure" ] || do_bootstrap; }
196
197 do_configure() {
198 maybe_bootstrap
199 echo -n "Configuring..."
200 ./configure ${CONFIG_OPTS} 2>&1 | perl tools/logger.pl > "release-config.log"
201 }
202 maybe_configure() { [ -f "Makefile" ] || do_configure; }
203
204 do_build() {
205 maybe_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"
211 }
212 maybe_build() { [ -f "src/openocd" ] || do_build; }
213 do_build_clean() { [ -f Makefile ] && make maintainer-clean >/dev/null; }
214
215 maybe_rebuild() {
216 if [ -f "configure" ]; then
217 echo "Re-running autoconf..."
218 autoconf
219 echo "Re-running automake..."
220 automake
221 fi
222 if [ -f "Makefile" ]; then
223 do_configure
224 do_build
225 fi
226 }
227
228 do_changelog() {
229 echo "Updating working copy to HEAD..."
230 do_svn update
231 echo "Creating ChangeLog..."
232 svn2cl -i --authors AUTHORS.ChangeLog
233 }
234 maybe_changelog() {
235 if [ -z "${RELEASE_DRY_RUN}" ] \
236 || [ ! -f ChangeLog ] \
237 || [ "$(cat ChangeLog | wc -l)" -lt 2 ]
238 then
239 do_changelog
240 fi
241 }
242 do_changelog_clean() {
243 do_svn revert ChangeLog
244 }
245
246 do_package() {
247 package_info_load
248 maybe_changelog
249 maybe_build
250 echo "Building distribution packages..."
251 make ${MAKE_OPTS} distcheck 2>&1 | perl tools/logger.pl > "release-pkg.log"
252 }
253 maybe_package() { [ -f "${PACKAGE_RELEASE}.zip" ] || do_package; }
254 do_package_clean() {
255 for EXT in tar.gz tar.bz2 zip; do
256 rm -v -f *.${EXT}
257 done
258 }
259
260 do_stage() {
261 maybe_package
262 echo "Staging package archives:"
263 mkdir -p archives
264 for EXT in tar.gz tar.bz2 zip; do
265 mv -v "${PACKAGE_RELEASE}.${EXT}" archives/
266 done
267 cp -a NEWS archives/
268 cp -a ChangeLog archives/
269 }
270 do_stage_clean() { rm -v -f -r archives; }
271
272 do_clean() {
273 do_build_clean
274 do_package_clean
275 rm -v -f configure
276
277 svn revert configure.in
278 rm -v -f release-*.log
279 }
280 do_clean_all() {
281 do_clean
282 do_changelog_clean
283 do_stage_clean
284 }
285
286 do_version_usage() {
287 cat << USAGE
288 usage: $0 version <command>
289 Version Commands:
290 tag {add|remove} <label> Add or remove the specified tag.
291 bump {major|minor|micro|rc} Bump the specified version number;
292 resets less-significant numbers to zero.
293 All but 'rc' releases drop that tag.
294 USAGE
295 }
296
297 do_version_sed() {
298 local OLD_VERSION="${PACKAGE_VERSION}"
299 local NEW_VERSION="$1"
300 local MSG="$2"
301
302 sed -i -e "/AC_INIT/ s|${OLD_VERSION}|${NEW_VERSION}|" configure.in
303 package_info_load
304 echo "${MSG}: ${OLD_VERSION} -> ${NEW_VERSION}"
305 }
306 do_version_bump_sed() {
307 local NEW_VERSION="$1"
308 [ -z "${PACKAGE_VERSION_TAGS}" ] || \
309 NEW_VERSION="${NEW_VERSION}${PACKAGE_VERSION_TAGS}"
310
311 do_version_sed "${NEW_VERSION}" \
312 "Bump ${CMD} package version number"
313 }
314 do_version_bump_major() {
315 has_version_tag 'rc\d' do_version_
316 do_version_bump_sed "$((PACKAGE_MAJOR + 1)).0.0"
317 }
318 do_version_bump_minor() {
319 do_version_bump_sed "${PACKAGE_MAJOR}.$((PACKAGE_MINOR + 1)).0"
320 }
321 do_version_bump_micro() {
322 do_version_bump_sed "${PACKAGE_MAJOR_AND_MINOR}.$((PACKAGE_MICRO + 1))"
323 }
324 do_version_bump_rc() {
325 die "patch missing: -rc support is not implemented"
326 }
327 do_version_bump() {
328 CMD="$1"
329 shift
330 case "${CMD}" in
331 major|minor|micro|rc)
332 eval "do_version_bump_${CMD}"
333 ;;
334 *)
335 do_version_usage
336 ;;
337 esac
338 }
339
340 has_version_tag() {
341 test "${PACKAGE_VERSION/-${TAG}/}" != "${PACKAGE_VERSION}"
342 }
343
344 do_version_tag_add() {
345 local TAG="$1"
346 has_version_tag && die "error: tag '-${TAG}' exists in '${PACKAGE_VERSION}'"
347 do_version_sed "${PACKAGE_VERSION}-${TAG}" \
348 "Add '-${TAG}' version tag"
349 }
350 do_version_tag_remove() {
351 local TAG="$1"
352 has_version_tag || die "error: tag '-${TAG}' missing from '${PACKAGE_VERSION}'"
353 do_version_sed "${PACKAGE_VERSION/-${TAG}/}" \
354 "Remove '-${TAG}' version tag"
355 }
356 do_version_tag() {
357 CMD="$1"
358 shift
359 case "${CMD}" in
360 add|remove)
361 local i=
362 for i in "$@"; do
363 eval "do_version_tag_${CMD}" "${i}"
364 done
365 ;;
366 *)
367 do_version_usage
368 ;;
369 esac
370 }
371
372 do_version_commit() {
373 [ "$(svn diff configure.in | wc -l)" -gt 0 ] || \
374 die "error: no version changes to commit"
375 do_svn commit -m "$1" configure.in
376 }
377
378 do_version() {
379 package_info_load
380 CMD="$1"
381 shift
382 case "${CMD}" in
383 tag|bump)
384 do_version_commit "$(eval "do_version_${CMD}" "$@")"
385 maybe_rebuild
386 ;;
387 commit)
388 local MSG="$1"
389 [ "${MSG}" ] || die "usage: $0 version commit <message>"
390 do_version_commit "${MSG}"
391 maybe_rebuild
392 ;;
393 *)
394 do_version_usage
395 ;;
396 esac
397 }
398
399
400 do_branch() {
401 package_info_load
402 svn_setup_load
403 do_svn copy -m "Branching version ${PACKAGE_VERSION}" \
404 "${SVN_TRUNK}" "${PACKAGE_BRANCH}"
405 }
406 do_tag() {
407 package_info_load
408 svn_setup_load
409 do_svn copy -m "Tagging version ${PACKAGE_VERSION}" \
410 "${PACKAGE_BRANCH}" "${PACKAGE_TAG}"
411 }
412 do_commit() {
413 package_info_load
414 svn_setup_load
415
416 [ "${PACKAGE_VERSION/in-development/}" = "${PACKAGE_VERSION}" ] || \
417 die "'${PACKAGE_NAME}-${PACKAGE_VERSION}' cannot be released"
418
419 [ "${PACKAGE_VERSION%.0}" = "${PACKAGE_VERSION}" ] || \
420 do_branch
421 do_tag
422 }
423
424
425 do_release_step_prep() {
426 do_version tag remove in-development
427 # reset RELEASE_VERSION now to allow release version to be detected
428 export RELEASE_VERSION=
429 }
430 do_release_step_commit() { do_commit; }
431
432 do_release_step_branch_bump() {
433 local TYPE="$1"
434 echo "Bump ${TYPE} version and add tag:"
435 do_version_bump ${TYPE}
436 do_version_tag_add in-development
437 }
438 do_release_step_branch() {
439 do_svn_switch "${PACKAGE_BRANCH}"
440 do_version_commit "$(do_release_step_branch_bump micro)"
441 do_svn_switch "${SVN_URL}"
442 }
443 do_release_step_bump() {
444 # major and minor releases require branch version update too
445 [ "${RELEASE_TYPE}" = "micro" ] || do_release_step_branch
446 # bump the current tree version as required.
447 do_version_commit "$(do_release_step_branch_bump "${RELEASE_TYPE}")"
448
449 [ "${RELEASE_TYPE}" = "micro" ] && return
450
451 # archive NEWS and create new one from template
452 do_svn move "NEWS" "NEWS-${RELEASE_VERSION}"
453
454 [ "${RELEASE_DRY_RUN}" ] || cat >NEWS <<NEWS
455 This file should include items worth mentioning in the
456 OpenOCD ${PACKAGE_RELEASE} source archive release.
457
458 The following areas of OpenOCD functionality changed in this release:
459
460 JTAG Layer:
461 Target Layer:
462 Flash Layer:
463 Board, Target, and Interface Configuration Scripts:
464 Documentation:
465 Build and Release:
466
467 For more details about what has changed since the last release,
468 see the ChangeLog associated with this source archive. For older NEWS,
469 see the NEWS files associated with each release (i.e. NEWS-<version>).
470
471 For more information about contributing test reports, bug fixes, or new
472 features and device support, please read the new Developer Manual (or
473 the BUGS and PATCHES files in the source archive).
474 NEWS
475
476 MSG=<<MSG
477 Archive released NEWS file: NEWS -> NEWS-${RELEASE_VERSION}
478 Create new NEWS file from relesse script template.
479 MSG
480 do_svn commit -m "${MSG}" NEWS NEWS-${RELEASE_VERSION}
481 }
482 do_release_step_package() {
483 local A=${PACKAGE_TAG}
484 local B=${A/https/http}
485 local PACKAGE_BUILD=${B/${USER}@/}
486 do_svn_switch "${PACKAGE_BUILD}"
487 do_stage
488 do_clean
489 do_svn_switch "${SVN_URL}"
490 }
491
492 do_release_step_1() { do_release_step_prep; }
493 do_release_step_2() { do_release_step_commit; }
494 do_release_step_3() { do_release_step_bump; }
495 do_release_step_4() { do_release_step_package; }
496
497 do_release_check() {
498 echo -n "Are you sure you want to release '${PACKAGE_RELEASE}'?"
499 read ANSWER
500 if [ "${ANSWER}" != 'y' ]; then
501 echo "Live release aborted!"
502 exit 0
503 fi
504 }
505 do_countdown() {
506 echo -n "$1 in "
507 for i in $(seq 5 -1 1); do
508 echo -n "$i, "
509 done
510 echo "go!"
511 }
512
513 do_release() {
514 package_info_load
515 package_info_show
516
517 if [ -z "${RELEASE_DRY_RUN}" ]; then
518 do_release_check
519 do_countdown "Starting live release"
520 fi
521
522 local i=
523 for i in $(seq 1 4); do
524 eval "do_release_step_${i}"
525 done
526 }
527 do_all() { do_release "$@"; }
528
529 do_reset() {
530 maybe_bootstrap
531 maybe_configure
532 do_clean_all
533 svn revert configure.in
534 }
535
536 OPTIONS=$(getopt -o V --long live -n $0 -- "$@")
537 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
538 eval set -- "${OPTIONS}"
539 while true; do
540 case "$1" in
541 --live)
542 export RELEASE_DRY_RUN=
543 shift
544 ;;
545 -V)
546 exec $0 info
547 ;;
548 --)
549 shift
550 break
551 ;;
552 *)
553 echo "Internal error"
554 exit 1
555 ;;
556 esac
557 done
558
559 CMD=$1
560 [ "${CMD}" ] || usage
561 shift
562
563 ACTION_CMDS="bootstrap|configure|build|changelog|package|stage|clean"
564 MISC_CMDS="all|info|version|tag|branch|commit|release|reset|help|usage"
565 CLEAN_CMDS="build_clean|changelog_clean|package_clean|stage_clean|clean_all"
566 CMDS="|${ACTION_CMDS}|${CLEAN_CMDS}|${MISC_CMDS}|"
567 is_command() { echo "${CMDS}" | grep "|$1|" >/dev/null; }
568
569 if is_command "${CMD}"; then
570 eval "do_${CMD}" "$@"
571 else
572 echo "error: unknown command: '${CMD}'"
573 usage
574 fi

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)