summaryrefslogtreecommitdiff
path: root/sandbox/infrastructure/release.sh
blob: dc8231aeaa927c663e57becc0754d6fe31f506ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
#!/bin/bash

# Author: Lea Wiemann
# Contact: grubert@users.sourceforge.net
# Revision: $Revision$
# Date: $Date$
# Copyright: This script has been placed in the public domain.

# USAGE see: docutils/docs/dev/release.txt

# must be run from docutils trunk/docutils, 
# because HISTORY and RELEASE_NOTES.txt are modified.

set -e

function print_command()
{
    # Print "$@", quoting parameters containing spaces.
    echo -n $
    for param in "$@"; do
        echo "$param" | grep -Fq ' ' && echo -n " '$param'" || echo -n " $param"
    done
}

function run()
{
    # Print and run "$@".
    print_command "$@"
    echo
    "$@"
}

function confirm()
{
    # Print, let the user confirm and run "$@".
    echo 'Press enter to run (or enter anything to skip):'
    print_command "$@"
    read
    test "$REPLY" && echo Skipped. || "$@"
}

function svn_up()
{
    if test $svn == svk; then
        confirm svk sync "$depot"
    fi
    confirm $svn up
}

function checkin()
{
    # Parameters: log_message, file, file, file ...
    log_message="$1"
    shift
    confirm $svn diff "$@"
    confirm $svn ci -m "$log_prefix $log_message" "$@"
}

function set_ver()
{
    # Parameters: old_version new_version
    shopt -s extglob
    echo Determining list of files to be changed...
    # BUG ls lists directories but does not descend
    files="docutils/__init__.py setup.py `$svn ls test/functional/expected/ | sed 's|^|test/functional/expected/|'`"
    echo "Now I'll change the version number to $2 in the following files:"
    echo $files
    echo
    echo 'Press enter to proceed (or enter anything to skip)...'
    read
    if [ ! "$REPLY" ]; then
        echo 'Modifying files with ed...'
        old_ver_regex="`echo "$1" | sed 's/\./\\\\./g'`"
        # "ed" returns an error code if there has been no substitution, so
        # we temporarily deactivate exit-on-error.
        set +e
        for F in $files; do
            (echo ",s/$old_ver_regex/$2/g"; echo 'wq') | ed "$F"
        done
        set -e
    fi
    echo
    echo 'CAUTION: please look at the diffs carefully, for wrongly'
    echo ' replaced embedded numbers.'
    checkin "set version number to $2" $files
}

function usage()
{
    echo 'Usage:'
    echo
    echo '    release.sh new_version svn_version[:branch_version] [stage]'
    echo
    echo 'The following things will be done:'
    echo
    echo '* Change version number to new_version.  (stage 1)'
    echo '* SVN-export, test, and release Docutils version new_version.  (stage 2)'
    echo '* Change version number to svn_version.  (stage 3)'
    echo
    echo 'If stage is supplied (1, 2 or 3), only the specified stage will'
    echo 'be executed.  Otherwise, it defaults to executing all stages.'
    echo
    echo 'Before doing dangerous things, you will be asked to press enter.'
    echo
    echo 'A maintenance branch called docutils-new_version will be created'
    echo 'if branch_version is given.  The version number inside the'
    echo 'maintenance branch will be set to branch_version.'
    echo 
    echo 'Access ssh,scp and sftp access to shell/frs.sourceforge.net'
    echo 'must be configured.'
    exit 1
}

function initialize()
{
    if [ "$#" -lt 2 ]; then
        usage
    fi
    echo 'Initializing...'
    python_versions='2.6 2.7'
    for py_ver in $python_versions; do
        echo -n "Checking for Python $py_ver (python$py_ver)... "
        if ! echo 'print "OK"' | python$py_ver; then
            echo "WARN: Python $py_ver (python$py_ver) not found."
        fi
    done
    echo -n 'Clearing $PYTHONPATH... '
    export PYTHONPATH=
    echo 'done'
    echo -n 'Checking whether we are in a working copy... '
    if [ -f HISTORY.txt ]; then
        echo yes
    else
        echo "no (HISTORY.txt doesn't exist)"
        echo 'Aborting.'
        echo 'Please cd to a working copy before running this script.'
        exit 1
    fi
    echo -n 'Subversion binary to use: '
    # TODO breaks for newer svn, .svn is in upper. is this for svk 
    svn=svn
    echo $svn
    working_copy="`pwd -P`"
    echo "Working copy: $working_copy"
    svnurl="`$svn info . | grep ^URL: | sed 's/URL: //'`"
    if test -z "$svnurl"; then
        echo 'Unable to detect Subversion URL.  Aborting.'
        exit 1
    fi
    echo "Subversion URL: $svnurl"
    if ! echo "$svnurl" | grep -q 'branches\|trunk'; then
        echo 'Subversion URL contains neither "branches" nor "trunk".'
        echo 'Aborting.'
        exit 1
    fi
    if test `uname` = "Darwin" ; then
        svnroot="`echo "$svnurl" | sed -E 's/\/(branches|trunk).*//'`"
    else
        svnroot="`echo "$svnurl" | sed 's/\/\(branches\|trunk\).*//'`"
    fi
    echo "Subversion root URL: $svnroot"
    if test "$svnurl" = "$svnroot"; then
        echo 'Error: Subversion URL and Subversion root URL are the same.'
        echo '  probably a MacOSX sed problem.'
        exit 1
    fi
    echo -n 'Detecting current Docutils version... '
    old_ver="`python -c 'import docutils; print docutils.__version__'`"
    echo "$old_ver"
    new_ver="$1"
    # log_prefix is for SVN logs.
    log_prefix="Release $new_ver:"
    echo "New version number (for releasing): $new_ver"
    svn_ver="$2"
    if echo "$svn_ver" | grep -q :; then
        # Split at colon: svn_ver:branch_ver
        branch_ver="${svn_ver#*:}"
        svn_ver="${svn_ver%:*}"
    else
        branch_ver=
    fi
    echo "New Subversion version number (after releasing): $svn_ver"
    echo -n 'Create maintenance branch: '
    if test "$branch_ver"; then
        echo yes
        echo "New version number on maintenance branch: $branch_ver"
    else
        echo no
    fi
    if test "$branch_ver"; then
        echo -n 'Checking that we have a full checkout... '
        if echo "$working_copy" | grep -q 'branches\|trunk'; then
            echo OK
        else
            echo 'no'
            echo 'Working copy path contains neither "branches" nor "trunk".'
            echo 'You need a full checkout in order to branch.'
            echo 'Aborting.'
            exit 1
        fi
        wcroot="`echo "$working_copy" | sed 's/\/\(branches\|trunk\).*//'`"
        echo "Working copy root: $wcroot"
    fi
    tarball=docutils-"$new_ver".tar.gz
    echo "Tarball name: $tarball"
    echo 'Initialization completed.'
    echo
}

function test_tarball()
{
    # Assume we have the tarball in the current directory.
    # Pass test number as first parameter.
    echo 'Testing the release tarball.'
    run mkdir tarball_test/
    run cd tarball_test/
    confirm tar xzvf "../$tarball"
    echo
    run cd docutils-"$new_ver"
    echo 'Deleteing old installations. Installing the distribution.'
    echo "WARN: might not find installation."
    for py_ver in '"$python_versions"'; do
        echo "python$py_ver install/update and test."
        bash release-test.sh
        echo "Enter to test next."
        read
    done
}

function upload_tarball()
{
    # Assume we have the tarball in the working area.
    run cd "$working_area"
    mkdir $new_ver
    cp docutils-$new_ver.tar.gz $new_ver
    cp docutils/RELEASE-NOTES.txt $new_ver
    # README.txt would be displayed automatically on sf.
    # BUG user grubert hardcoded
    # short path  "/home/frs/project/docutils/docutils/" also exists
    scp -r $new_ver grubert,docutils@frs.sourceforge.net:/home/frs/project/d/do/docutils/docutils/
    echo 'Upload completed.'
}

function upload_htdocs()
{
    # Assume we have the tarball in the working area.
    run cd "$working_area"
    echo "Upload htdocs for $new_ver"
    run mkdir htdocs
    run cd htdocs
    confirm tar xzvf "../$tarball"
    run cd docutils-"$new_ver"/tools/
    echo "BUG no docutils installation left."
    echo "DO NOT call manually in $(pwd)"
    confirm ./buildhtml.py --local ..
    confirm ./buildhtml.py ../docs
    run cd ..
    echo '$ find . -name test -type d -prune -o -name \*.css -print0 \
        -o -name \*.html -print0 -o -name \*.txt -print0 \
        | tar -cjvf docutils-docs.tar.bz2 -T - --null'
    find . -name test -type d -prune -o -name \*.css -print0 \
        -o -name \*.html -print0 -o -name \*.txt -print0 \
        | tar -cjvf docutils-docs.tar.bz2 -T - --null
    echo 'Upload docs to SF.net...'
    echo 'Press enter (or enter anything to skip).'
    read
    if [ ! "$REPLY" ]; then
       mkdir $new_ver
       cd $new_ver
       tar xjvf ../docutils-docs.tar.bz2
	   cd ..
	   chmod -R g+rw $new_ver
	   scp -r -p -C $new_ver web.sourceforge.net:/home/groups/d/do/docutils/htdocs
    fi
}

function create_maintenance_branch()
{
    echo 'Creating maintenance branch.'
    branch_name="docutils-$new_ver"
    echo "Branch name: $branch_name"
    branch_url="$svnroot/branches/$branch_name"
    echo "Branch URL: $branch_url"
    confirm svn cp "$svnurl" "$branch_url" -m \
        "$log_prefix created maintenance branch for version $new_ver"
    cd "$wcroot"
    svn_up
    cd branches/"$branch_name"
    set_ver "$new_ver" "$branch_ver"
}

function run_stage()
{
    if [ ! "$1" ]; then
        run_stage 1
        echo
        run_stage 2
        echo
        run_stage 3
    else
        echo "Press enter to run stage $1 (or enter anything to skip this stage)."
        read
        if [ ! "$REPLY" ]; then
            cd "$working_copy"
            if [ "$1" == 1 ]; then
                stage_1
            elif [ "$1" == 2 ]; then
                stage_2
            elif [ "$1" == 3 ]; then
                stage_3
            else
                echo 'Invalid stage.'
                echo
                usage
            fi
            echo
            echo "Stage $1 completed."
        else
            echo "Skipped stage $1."
        fi
    fi
}

function stage_1()
{
    svn_up
    echo
    # update __version_details__ string
    (echo ",s/^__version_details__ = .*\$/__version_details__ = 'release'/";
        echo wq) | ed docutils/__init__.py 2> /dev/null
    set_ver "$old_ver" "$new_ver"
    echo
    history_files='HISTORY.txt RELEASE-NOTES.txt'
    echo "Now updating the following files: $history_files"
    old_string="Changes Since [0-9.]+"
    new_string="Release $new_ver (`date --utc --iso-8601`)"
    echo 'Press enter to replace "'"$old_string"'" with "'"$new_string"\",
    echo 'or enter anything to skip.'
    read
    test "$REPLY" || python -c "for filename in '$history_files'.split():
        import re
        h = file(filename).read()
        h = re.sub('$old_string\\n=+', '$new_string\\n' + '=' * len('$new_string'), h, count=1)
        file(filename, 'w').write(h)"
    checkin 'closed "Changes Since ..." section' $history_files
}

function stage_2()
{
    echo 'Creating working area...'
    working_area="`echo ~/tmp/docutils-release.$$`"
    run mkdir -p "$working_area"
    echo
    echo 'Getting a fresh export.'
    echo 'Press enter to proceed (or enter anything to skip)...'
    read
    if [ ! "$REPLY" ]; then
        run cd "$working_area"
        confirm svn export "$svnurl"
        echo
        echo 'Building the release tarball.'
        run cd docutils
        confirm ./setup.py sdist
        run cd ..
        echo 'Tarball built.'
        run cp docutils/dist/"$tarball" .
        echo 'BETTER run release-test.sh manually for each installed python version.'
        echo "DO: cd $working_area and call sandbox/infrastructure/release-test.sh py_ver docutils_ver"
        confirm test_tarball
        echo "Testing documentation and uploading htdocs of version $new_ver..."
        confirm upload_htdocs
        echo "Tagging current revision..."
        confirm svn cp "$svnurl" "$svnroot/tags/docutils-$new_ver/" -m "$log_prefix tagging released revision"
        echo "Uploading $tarball to SF.net."
        confirm upload_tarball
        echo 'Now go to https://sourceforge.net/projects/docutils/files/docutils'
        echo 'and follow the instructions at'
        echo 'http://docutils.sf.net/docs/dev/release.html#file-release-system'
        echo
        echo 'Then press enter.'
        read
    fi
    run cd $working_area
    echo 'Downloading the tarball to verify its integrity.'
    while true; do
	    # BUG path is wrong. project admin filemanager shows md5sum
        confirm wget http://sourceforge.net/projects/docutils/files/"$tarball"
        echo 'Was the download successful?'
        echo 'If yes, press enter to continue, otherwise enter anything to repeat'
        echo '(it is possible that the file will show up in a few minutes).'
        read
        test "$REPLY" || break
    done
    confirm test_tarball
    echo 'we are registered with PyPI...'
    echo 'upload to pypi with twine or set download url for this release'

    echo 'Press enter to proceed (or enter anything to skip)...'
    read
    if [ ! "$REPLY" ]; then
        echo "Unpacking tarball..."
        ls -l
        pwd
        run twine upload "$tarball"
        echo "verify on PyPI. hide older releases."
        echo "TODO TEST build wheels and upload"
        run pip wheel docutils
        run twine upload docutils-*-py2-none-any.whl
        run pip3 wheel docutils
        run twine upload wheelhouse/docutils-${new_ver}-py3-none-any.whl
    fi
}

function stage_3()
{
    svn_up
    echo
    # update __version_details__ string
    (echo ",s/^__version_details__ = .*\$/__version_details__ = 'repository'/";
        echo wq) | ed docutils/__init__.py 2> /dev/null
    checkin 'set __version_details__ to "repository"'
    echo
    history_files='HISTORY.txt RELEASE-NOTES.txt'
    echo "Now updating the following files: $history_files"
    add_string="Changes Since $new_ver"
    before="Release "
    echo 'Press enter to add "'"$add_string"'" section,'
    echo 'or enter anything to skip.'
    read
    test "$REPLY" || python -c "for filename in '$history_files'.split():
        import re
        h = file(filename).read()
        h = re.sub('\n$before', '\\n$add_string\\n' + '=' * len('$add_string') +
                   '\\n\\n\\n$before', h, count=1)
        file(filename, 'w').write(h)"
    checkin "added empty \"Changes Since $new_ver\" section" $history_files
    echo
    if test "$branch_ver"; then
        create_maintenance_branch
        cd "$working_copy"
    fi
    set_ver "$new_ver" "$svn_ver"
    echo 'Please change version number in README.txt'
    echo
    echo 'Please update the web page now (web/index.txt).'
    echo 'cd into sandbox/infrastructure'
    echo 'and call docutils-update.local (requires linux, macosx cp misses something)'
    echo "Press enter when you're done."
    read
}

initialize "$@"
run_stage "$3"
echo
echo 'Finished.'
echo 'Run alltests.py on svn version now.'

# Local Variables:
# indent-tabs-mode: nil
# End: