Rewrite release script to use GIT.
[fw/openocd] / 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