jenkins_continuous_integration.sh 6.6 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
CREATEPACKAGESCRIPT="$PREFIX/build_package.sh"
37
PACKAGESDEST="$REPOROOT/pkgs"
38
JENKINSUSER="Jenkins <jenkins@c3sl.ufpr.br>"
39
40
41
42
43

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

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

53
54
55
56
57
58
59
60
# 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 $?
}

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

67
68
69
70
71
72
73
74
    # 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} |
75
                                  grep "package" | cut -d/ -f1)"
76
77
78
        fi
        lastRev=$rev
    done
79
80

    # Filter only the ones that represents valid packages
81
    for file in $(echo $allFiles | sed 's/ /\n/g' | sort -u); do
82
83
84
85
86
87
88
89
90
91
92
        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() {
93
    local repo=$(grep 'url = ' $REPOCONFIGFILE |
94
95
96
97
98
99
                 cut -d'/' -f3 | cut -d'.' -f1)

    echo $repo
}

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

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

110
# Print program help
111
function showHelp() {
112
    echo "$0 OPTION... <previous commit> [current commit]"
113
    echo ""
114
115
    echo -n "Generate packages that have changed since <previous commit> to "
    echo -n "[current commit]. If [current commit] is ommited, the script "
116
    echo "uses HEAD. The generated packages will be stored on $PACKAGESDEST"
117
118
119
120
121
122
    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."

123
124
125
    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."
126
127

    echo -en "-r\tRemove packages generated on previous execution of this "
128
    echo "script."
129
130
131
}

# Sanity check
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
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"
175
176
177
178
    showHelp
    exit 1
fi

179
180
181
182
183
# Remove previous generated debian packages.
# This is necessary because jenkins would archive again files already
# archied on previous execution os this script
prepare

184
185
186
187
repository="le5-$(getCurrentRepository)"
pkgs=$(getChangedPackages)
nOfPackages=$(echo $pkgs | wc -l)

188
# FIXME: checkout and pull from a specified branch, not only master
189
if $COMMIT && test $nOfPackages -gt 0; then
190
191
192
193
    git checkout master
    git pull
fi

194
for pkg in $pkgs; do
195
    # Generate Package
196
    # TODO: allow user to change minor and major too
197
    echo "Generating package $pkg"
198
    if ! $CREATEPACKAGESCRIPT $pkg "revision"; then
199
200
201
202
        echo ERROR creating package $pkg.
        exit 1
    fi

203
    # Publish it
204
    if $PUBLISH; then
205
206
        echo "Publishing package $pkg on le5-$repository"
        if ! publish $pkg $repository; then
207
            echo "ERROR publishing package $pkg on repository $repository."
208
209
            exit 1
        fi
210
    fi
211
done
212

213
if $COMMIT && test $nOfPackages -gt 0; then
214
    git commit -s -a -m "New packages generated by Jenkins"
215
    # TODO: push to the branch being used, which is not necessarily master
216
217
218
219
    if ! git push; then
        echo "ERROR: Failed to push changes to repository $repository."
        exit 1
    fi
220
fi