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