jenkins_continuous_integration.sh 7.62 KB
Newer Older
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
#!/bin/bash
#
# Copyright (C) 2004-2010 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
#
# This file is part of Linux Educacional project
#
# Linux Educacional is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.

# -------------------------------------------------------------------------
# This script is used by jenkins to generate and publish debian packages.

# The LE5 project has several packages, separated in different directories.
# Jenkins polls the git repository periodically and runs this script when a
# change is detected, which will find out which packages have changed, build
# and publish them into the right mirror (unstable/testing/stable).
# -------------------------------------------------------------------------

PREFIX="$(dirname $0)"
REPOROOT="$PREFIX/.."
REPOCONFIGFILE="$REPOROOT/.git/config"
35
PUBLISHSCRIPT="$PREFIX/le-publish.sh"
36
PACKAGESDEST="$REPOROOT/pkgs"
37
JENKINSUSER="Jenkins <jenkins@c3sl.ufpr.br>"
38
39
40
41
42

# List of files/directories inside this repository that do not represent a
# module.
DONTGENERATE="bin doc README"

43
44
# Create necessary directories and maybe remove previously generated
# packages
45
46
function prepare() {
    mkdir -p $PACKAGESDEST
47
48
49
    if $REMOVE_OLD_PKGS; then
        rm -f $PACKAGESDEST/*.deb
    fi
50
51
}

52
53
54
55
56
57
58
59
# Check whether a git revision was made by jenkins.
# Return true if it was, false otherwise
function madeByJenkins() {
    local rev=$1
    git cat-file commit $rev | grep -q "author $JENKINSUSER"
    return $?
}

60
61
62
# Return all packages that have changed since the last build.
function getChangedPackages() {
    local allFiles=""
63
    local allRevs=""
64
65
    local pkgs=""

66
67
68
69
70
71
72
73
74
75
76
77
    # Get all revisions since last run
    allRevs=$(git rev-list --reverse ${GIT_PREVIOUS_COMMIT}..${GIT_COMMIT})

    lastRev=${GIT_PREVIOUS_COMMIT}
    for rev in $allRevs; do
        # Ignore changes made by jenkins
        if ! madeByJenkins $rev; then
            allFiles="$allFiles $(git diff --name-only ${lastRev}..${rev} |
                                cut -d/ -f1)"
        fi
        lastRev=$rev
    done
78
79

    # Filter only the ones that represents valid packages
80
    for file in $(echo $allFiles | sed 's/ /\n/g' | sort -u); do
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
        if test -d "$REPOROOT/$file" && ! echo $DONTGENERATE | grep -q "\<$file\>"; then
            pkgs="$pkgs $file"
        fi
    done

    echo $pkgs
}

# As we have tree mirrors for LE5 (unstable/testing/stable), let's find out
# and return in which one we are going to publish the generated packages.
function getCurrentRepository() {
    local repo=$(grep 'git@git.c3sl.ufpr.br:./le5/' $REPOCONFIGFILE |
                 cut -d'/' -f3 | cut -d'.' -f1)

    echo $repo
}

# Publish <pkg> on <repo>
99
# <repo>: unstable, testing, stable
100
101
function publish() {
    local pkg=$1
102
    local repo=$2
103
    local pkgFile=$(ls $PACKAGESDEST/$pkg*.deb | sort | tail -1)
104

105
    $PUBLISHSCRIPT "$repo" "$pkgFile"
106
    return $?
107
108
}

109
# Generate a debian package for $pkg ($1), updating the version based on
110
# $kind ($2), where $kind can be revision, minor, or major.
111
112
function createPackage() {
    local pkg=$1
113
114
115
    local kind=$2

    local version=""
116
    local newVersion=""
117
118
119
    local major=""
    local minor=""
    local revision=""
120
121
    local controlFile="$REPOROOT/$pkg/pacote/DEBIAN/control"
    local ret=""
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

    version=$(grep "^Version:" $controlFile | awk '{print $2}')

    major=$(echo $version | cut -d. -f1)
    minor=$(echo $version | cut -d. -f2)
    revision=$(echo $version | cut -d. -f3)

    case $kind in
        major)
            ((major++))
            minor=0
            revision=0
            ;;
        minor)
            ((minor++))
            revision=0
            ;;
        *)
            ((revision++))
            ;;
    esac

144
    newVersion="${major}.${minor}.${revision}"
145

146
    sed -i -e "s/Version:.*/Version: $newVersion/" $controlFile
147

148
149
150
151
152
153
154
155
156
    fakeroot dpkg -b $REPOROOT/$pkg/pacote/ $PACKAGESDEST
    ret=$?

    if test $ret -ne 0; then
        git checkout $controlFile
        return $ret
    fi

    return 0
157
158
159
}

function showHelp() {
160
    echo "$0 OPTION... <previous commit> [current commit]"
161
    echo ""
162
163
    echo -n "Generate packages that have changed since <previous commit> to "
    echo -n "[current commit]. If [current commit] is ommited, the script "
164
    echo "uses HEAD. The generated packages will be stored on $PACKAGESDEST"
165
166
167
168
169
170
    echo "Options are:"
    echo -en "-p\tPublish generated packages on LE5 mirror. The "
    echo -n "mirror that will be updated is based on the repository where "
    echo -n "this script is running. E.g: repository unstable will imply in "
    echo "the mirror le5-unstable being updated."

171
172
173
    echo -en "-c\tCommit and push changes to the repository. The only "
    echo -n "changes made by this script is on the Version field on "
    echo "<package>/pacote/DEBIAN/control."
174
175

    echo -en "-r\tRemove packages generated on previous execution of this "
176
    echo "script."
177
178
179
}

# Sanity check
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
if test $# -lt 1 || test $# -gt 5; then
    showHelp
    exit 1
fi

PUBLISH=false
COMMIT=false
REMOVE_OLD_PKGS=false
GIT_PREVIOUS_COMMIT=""
GIT_COMMIT=""
while test $# -gt 0; do
    arg=$1
    case $arg in
        -p)
            PUBLISH=true
            ;;
        -c)
            COMMIT=true
            ;;
        -r)
            REMOVE_OLD_PKGS=true
            ;;
        [^-]*)
            if test -z "$GIT_PREVIOUS_COMMIT"; then
                GIT_PREVIOUS_COMMIT=$arg
            elif test -z "$GIT_COMMIT"; then
                GIT_COMMIT=$arg
            else
                echo "Unrecognized parameter $arg"
                showHelp
                exit 1
            fi
            ;;
        *)
            echo "Unrecognized parameter $arg"
            showHelp
            exit 1
    esac
    shift
done

if test -z "$GIT_PREVIOUS_COMMIT"; then
    echo "You must suply GIT_PREVIOUS_COMMIT"
223
224
225
226
    showHelp
    exit 1
fi

227
228
229
230
231
# Remove previous generated debian packages.
# This is necessary because jenkins would archive again files already
# archied on previous execution os this script
prepare

232
233
234
235
repository="le5-$(getCurrentRepository)"
pkgs=$(getChangedPackages)
nOfPackages=$(echo $pkgs | wc -l)

236
# FIXME: checkout and pull from a specified branch, not only master
237
if $COMMIT && test $nOfPackages -gt 0; then
238
239
240
241
    git checkout master
    git pull
fi

242
for pkg in $pkgs; do
243
    # Generate Package
244
    # TODO: allow user to change minor and major too
245
    echo "Generating package $pkg"
246
247
248
249
250
    if ! createPackage $pkg revision; then
        echo ERROR creating package $pkg.
        exit 1
    fi

251
    # Publish it
252
    if $PUBLISH; then
253
254
        echo "Publishing package $pkg on le5-$repository"
        if ! publish $pkg $repository; then
255
            echo "ERROR publishing package $pkg on repository $repository."
256
257
            exit 1
        fi
258
    fi
259
done
260

261
if $COMMIT && test $nOfPackages -gt 0; then
262
    git commit -s -a -m "New packages generated by Jenkins"
263
    # TODO: push to the branch being used, which is not necessarily master
264
265
266
267
    if ! git push; then
        echo "ERROR: Failed to push changes to repository $repository."
        exit 1
    fi
268
fi