26be151183d6902a37145f87adf841eb49616690
[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 ## specifies the --next release type: major, minor, micro, rc, tag
11 #RELEASE_TYPE=tag
12 ## For tag release type, specifies the name of the tag (e.g. "foo").
13 ## The default is the current user name, as found by the 'id' command.
14 #RELEASE_TAG="$(id -un)"
15
16 source "tools/release/helpers.sh"
17
18 VERSION_SH="tools/release/version.sh"
19
20 usage() {
21 cat << USAGE
22 usage: $0 <command> ...
23 Command Options:
24 --next name The branch's next release type: major, minor, micro, rc, tag.
25 --next-tag name The name for the package version tag.
26 --live Perform the actions in the repository.
27
28 Main Commands:
29 info Show a summary of the next pending release.
30 release Release the current tree as an archive.
31
32 Build Commands:
33 bootstrap Prepare the working copy for configuration and building.
34 configure Configures the package; runs bootstrap, if needed.
35 build Compiles the project; runs configure, if needed.
36
37 Packaging Commands:
38 changelog Generate a new ChangeLog using ${SCM}2cl.
39 package Produce new distributable source archives.
40 stage Move archives to staging area for upload.
41
42 Other Commands:
43 clean Forces regeneration of results.
44 clean_all Removes all traces of the release process.
45 help Provides this list of commands.
46
47 For more information about this script, see the Release Processes page
48 in the OpenOCD Developer's Manual (doc/manual/release.txt).
49 USAGE
50 exit 0
51 }
52 do_usage() { usage; }
53 do_help() { usage; }
54
55 do_info() {
56 echo "Current Release Analysis:"
57 package_info_show
58 }
59
60 do_bootstrap() {
61 echo -n "Bootstrapping..."
62 ./bootstrap 2>&1 | perl tools/logger.pl > "release-bootstrap.log"
63 }
64 maybe_bootstrap() { [ -f "configure" ] || do_bootstrap; }
65
66 do_configure() {
67 maybe_bootstrap
68 echo -n "Configuring..."
69 ./configure ${CONFIG_OPTS} 2>&1 | perl tools/logger.pl > "release-config.log"
70 }
71 maybe_configure() { [ -f "Makefile" ] || do_configure; }
72
73 do_build() {
74 maybe_configure
75 echo -n "Compiling OpenOCD ${PACKAGE_VERSION}"
76 make ${MAKE_OPTS} -C doc stamp-vti 2>&1 \
77 | perl tools/logger.pl > "release-version.log"
78 make ${MAKE_OPTS} 2>&1 \
79 | perl tools/logger.pl > "release-make.log"
80 }
81 maybe_build() { [ -f "src/openocd" ] || do_build; }
82 do_build_clean() { [ -f Makefile ] && make maintainer-clean >/dev/null; }
83
84 do_changelog() {
85 echo "Creating ChangeLog..."
86 local CMD=tools/git2cl/git2cl
87 eval ${CMD} ${OPTS} > ChangeLog
88 }
89 do_changelog_clean() {
90 git checkout ChangeLog
91 }
92
93 do_package() {
94 do_changelog
95 maybe_build
96 echo "Building distribution packages..."
97 make ${MAKE_OPTS} distcheck 2>&1 | perl tools/logger.pl > "release-pkg.log"
98 }
99 maybe_package() { [ -f "${PACKAGE_RELEASE}.zip" ] || do_package; }
100 do_package_clean() {
101 for EXT in tar.gz tar.bz2 zip; do
102 rm -v -f *.${EXT}
103 done
104 }
105
106 do_stage() {
107 maybe_package
108 echo "Staging package archives:"
109 mkdir -p archives
110 for EXT in tar.gz tar.bz2 zip; do
111 local FILE="${PACKAGE_RELEASE}.${EXT}"
112 # create archive signatures
113 for HASH in md5 sha1; do
114 echo "sign: ${FILE}.${HASH}"
115 ${HASH}sum "${FILE}" > "archives/${FILE}.${HASH}"
116 done
117 # save archive
118 mv -v "${FILE}" archives/
119 done
120 cp -a NEWS archives/
121 cp -a ChangeLog archives/
122 }
123 do_stage_clean() { rm -v -f -r archives; }
124
125 do_clean() {
126 do_build_clean
127 do_package_clean
128 do_changelog_clean
129 rm -v -f release-*.log
130 }
131 do_clean_all() {
132 do_clean
133 do_stage_clean
134 }
135
136 do_version_commit() {
137 [ "$*" ] || die "usage: $0 commit <message>"
138 git add configure.in || die "error: no version changes to commit"
139 git commit -q -m "$*" configure.in
140 }
141
142 do_version_finalize() {
143 echo "The ${PACKAGE_NAME} ${RELEASE_VERSION} release."
144 echo
145 ${VERSION_SH} tag remove dev
146 [ -z "${RELEASE_FINAL}" ] || ${VERSION_SH} bump final rc
147 }
148 has_dev_tag() {
149 [ "${PACKAGE_VERSION/dev/}" != "${PACKAGE_VERSION}" ]
150 }
151 do_release_step_branch() {
152 git checkout -b "v${RELEASE_VERSION}-release"
153 }
154
155 do_release_step_tag() {
156 do_version_commit "$(do_version_finalize)"
157 package_info_load
158 [ "${PACKAGE_VERSION/dev/}" = "${PACKAGE_VERSION}" ] || \
159 die "'${PACKAGE_NAME}-${PACKAGE_VERSION}' should not be tagged"
160 local MSG="The ${PACKAGE_STRING} release."
161 git tag -m "${MSG}" "v${PACKAGE_VERSION}"
162 }
163
164 do_bump_version() {
165 echo -n "Bump ${RELEASE_TYPE} "
166 [ -z "${RELEASE_TAG}" ] || echo -n "-${RELEASE_TAG} "
167 echo -n "version and add "
168 [ -z "${RELEASE_START_RC}" ] || echo -n "-rc0"
169 echo "-dev tag."
170 echo
171 ${VERSION_SH} bump "${RELEASE_TYPE}" "${RELEASE_TAG}"
172 [ -z "${RELEASE_START_RC}" ] || ${VERSION_SH} bump tag rc
173 ${VERSION_SH} tag add dev
174 }
175 do_release_step_bump() {
176 # bump the version number
177 do_version_commit "$(do_bump_version)"
178 }
179
180 do_release_step_news_msg() {
181 cat <<MSG
182 Archive and recreate NEWS file.
183
184 Archive released NEWS file as NEWS-${RELEASE_VERSION}.
185 Create new NEWS file from release script template.
186 MSG
187 }
188 do_release_step_news() {
189 # only archive the NEWS file for major/minor releases
190 [ "${RELEASE_TYPE}" = "major" -o "${RELEASE_TYPE}" = "minor" ] || \
191 return 0
192 # archive NEWS and create new one from template
193 git mv "NEWS" "NEWS-${RELEASE_VERSION}"
194
195 cat >NEWS <<NEWS
196 This file should include items worth mentioning in the
197 OpenOCD ${NEXT_RELEASE_VERSION} source archive release.
198
199 The following areas of OpenOCD functionality changed in this release:
200
201 JTAG Layer:
202 Target Layer:
203 Flash Layer:
204 Board, Target, and Interface Configuration Scripts:
205 Documentation:
206 Build and Release:
207
208 For more details about what has changed since the last release,
209 see the ChangeLog associated with this source archive. For older NEWS,
210 see the NEWS files associated with each release (i.e. NEWS-<version>).
211
212 For more information about contributing test reports, bug fixes, or new
213 features and device support, please read the new Developer Manual (or
214 the BUGS and PATCHES files in the source archive).
215 NEWS
216 git add NEWS
217
218 local MSG="$(do_release_step_news_msg)"
219 git commit -q -m "${MSG}" NEWS "NEWS-${RELEASE_VERSION}"
220 }
221
222 do_release_step_package() {
223 [ -z "${RELEASE_FAST}" ] || return 0
224
225 git checkout -q "v${RELEASE_VERSION}"
226 do_stage
227 do_clean
228 }
229
230 do_release_step_rebranch() {
231 # return to the new development head
232 local OLD_BRANCH="v${RELEASE_VERSION}-release"
233 git checkout "${OLD_BRANCH}"
234
235 # create new branch with new version information
236 package_info_load
237 git checkout -b "v${PACKAGE_VERSION}"
238 git branch -d "${OLD_BRANCH}"
239 }
240
241 do_release_step_0() { do_release_step_branch; }
242 do_release_step_1() { do_release_step_tag; }
243 do_release_step_2() { do_release_step_bump; }
244 do_release_step_3() { do_release_step_news; }
245 do_release_step_4() { do_release_step_package; }
246 do_release_step_5() { do_release_step_rebranch; }
247
248 do_release_setup() {
249 echo "Starting $CMD for ${RELEASE_VERSION}..."
250 [ "${RELEASE_TYPE}" ] || \
251 die "The --next release type must be provided. See --help."
252 }
253
254 do_release_check() {
255 [ -z "${RELEASE_FAST}" ] || return 0
256 echo "Are you sure you want to ${CMD} '${PACKAGE_RELEASE}', "
257 echo -n " to start a new ${RELEASE_TYPE} development cycle? (y/N) "
258 read ANSWER
259 if [ "${ANSWER}" != 'y' ]; then
260 echo "Live release aborted!"
261 exit 0
262 fi
263 do_countdown "Starting live release"
264 }
265 do_countdown() {
266 echo -n "$1 in "
267 for i in $(seq 5 -1 1); do
268 echo -n "$i, "
269 sleep 1
270 done
271 echo "go!"
272 }
273
274 do_branch() {
275 do_release_setup
276 local i=
277 for i in 0 2 5; do
278 "do_release_step_${i}"
279 done
280 }
281
282 do_release() {
283 local CMD='release'
284 do_release_setup
285 do_release_check
286 local i=
287 for i in $(seq 0 5); do
288 "do_release_step_${i}"
289 done
290 }
291 do_all() { do_release "$@"; }
292
293 do_reset() {
294 maybe_bootstrap
295 maybe_configure
296 do_clean_all
297 git checkout configure.in
298 }
299
300 LONGOPTS="fast,final,start-rc,next-tag:,next:,help"
301 OPTIONS=$(getopt -o 'V,n:' --long "${LONGOPTS}" -n $0 -- "$@")
302 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
303 eval set -- "${OPTIONS}"
304 while true; do
305 case "$1" in
306 --fast)
307 RELEASE_FAST=yes
308 shift
309 ;;
310 --final)
311 RELEASE_FINAL=yes
312 shift
313 ;;
314 --start-rc)
315 RELEASE_START_RC=yes
316 shift
317 ;;
318 -n|--next)
319 export RELEASE_TYPE="$2"
320 shift 2
321 ;;
322 --next-tag)
323 export RELEASE_TAG="$2"
324 shift 2
325 ;;
326 -V)
327 exec $0 info
328 ;;
329 --)
330 shift
331 break
332 ;;
333 --help)
334 usage
335 shift
336 ;;
337 *)
338 echo "Internal error"
339 exit 1
340 ;;
341 esac
342 done
343
344 case "${RELEASE_TYPE}" in
345 major|minor|micro|rc)
346 ;;
347 tag)
348 [ "${RELEASE_TAG}" ] || RELEASE_TAG="$(id -u -n)"
349 ;;
350 '')
351 ;;
352 *)
353 die "Unknown release type '${RELEASE_TYPE}'"
354 ;;
355 esac
356
357 CMD=$1
358 [ "${CMD}" ] || usage
359 shift
360
361 ACTION_CMDS="bootstrap|configure|build|changelog|package|stage|clean"
362 MISC_CMDS="all|info|release|branch|reset|help|usage"
363 CLEAN_CMDS="build_clean|changelog_clean|package_clean|stage_clean|clean_all"
364 CMDS="|${ACTION_CMDS}|${CLEAN_CMDS}|${MISC_CMDS}|"
365 is_command() { echo "${CMDS}" | grep "|$1|" >/dev/null; }
366
367 package_info_load
368 if is_command "${CMD}"; then
369 "do_${CMD}" "$@"
370 echo "Done with '${CMD}'." >&2
371 else
372 echo "error: unknown command: '${CMD}'"
373 usage
374 fi