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
|
#!/bin/bash
set -eu
function print_usage(){
cat <<END
Usage: $0 [Options] <srpm> [scope1 [scope2 ...]]
This command automates the release process from SRPM to bodhi
DESCRIPTION
This program runs the build in koji build system, then submit successful
builds to bodhi the package update system.
Scopes tells this program what branches to be build.
The default scope (without specifing any scope) is all active branches
(the branches that currently accepts new builds) of this package.
You can also specify something like "fedora" "epel7" "el6",
which basically means that all fedora active branches (including rawhide),
as well as EPEL 7 and EPEL 6, will be processed.
If the scopes cover more than one branches, and this program will
also merge git branches for real build (without option "-s").
For example, if the scopes covers master, f24 and f23, it will firstly
import the SRPM on master branch and build, if successful, then it will
checkout the f24 and "git merge master", and so on.
The FedPkg git repos will be cloned as sub-directory of current directory
by default. The destination can be changed by either option '-d' or enviornment
FEDPKG_DIR. Note that this program will not resolve the merge conflict, it is
recommended to build with scratch-build first.
Scratch build mode can be invoked with option '-s'.
ARGUMENTS
<srpm>
Source RPM to be build from.
[scope1 [scope2 ...]]
What should be build against.
Valid values:
rawhide: Build rawhide.
fedora: Build actives fedora releases, including Rawhide.
fedora_1: Build the latest supported fedora releases.
This is one release eariler than rawhide.
fedora_2: Build the second latest supported fedora releases.
This is two releases eariler than rawhide.
f22 f21 ...: Build the specified fedora releases.
epel: Build the currently supported EPEL releases.
epel_1: Build the latest supported EPEL releases.
epel_2: Build the second latest supported EPEL releases.
epel7 el6 ... : The EPEL releases to be built.
If scopes is not specified, then it will use the existing branch for koji.
OPTIONS
-b <bugs>: The list of bug this update fixed. Split with ','.
-d <work_dir>: The parent directory of a fedpkg module.
-m <message>: Message used as commit message.
If not specified, then use the latest changelog text.
(i.e. rpm -qp --queryformat "%{ChangeLogText}" <srpm>)
-s: Scratch build instead of real build.
-t updateType: Update type. Valid values:
[bugfix|security|enhancement|newpackage].
Default:
newpackage: if this package does not exist in bodhi
enhancement: if the latest change log item has "Enhancement:"
bugfix: for everything else.
-u <bodhi_username>: Fedora Account name
Default: See environment BODHI_USER
srpm: SRPM file to be scratch-built with koji.
ENVIRONMENT
FEDPKG_DIR
The directory that this program should work on.
If -d is not specified, this program will use this value as
work directory.
BODHI_USER
Bodhi username. This means your Fedora account ID.
If not specified, it assumes environment variableLOGNAME.
EXIT_STATUS
Success:
EXIT_OK
Fatal that should stop immediately:
EXIT_FATAL_UNSPECIFIED: Unspecified fatal error,
usually indicate a bug in our scripts.
EXIT_FATAL_INVALID_OPTIONS: Wrong options were given.
EXIT_FATAL_MISSING_DEPENDENCY: Cannot find dependency.
EXIT_FATAL_UNKNOWN_MODULE: Invalid or unknown module name.
EXIT_FATAL_FAIL: Script detected that a fatal error occurred.
Error that need to stop before next stage:
EXIT_ERROR_FAIL: Script detected that an error occurred.
Return value, should not print error messages:
EXIT_RETURN_FALSE: Script should return false.
END
}
##=== Finding Library ===
ScriptFile=$(readlink -e "${BASH_SOURCE[0]}" 2>/dev/null || realpath "${BASH_SOURCE[0]}")
export ScriptDir=$(dirname $ScriptFile)
source $ScriptDir/cmake-fedora-functions
##=== Begin Functions ===
function add_bodhi_target () {
local target=$1
if [[ -z $BodhiTargets ]];then
BodhiTargets=$target
else
if [[ $BodhiMajorVer -ge 2 ]];then
BodhiTargets=",$target"
else
BodhiTargets=" $target"
fi
fi
}
function contains_element () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
# is target been built in koji
# Valid target example: cmake-fedora-1.4.0-1.fc21
function is_target_built(){
target=$1
$KOJI_CMD buildinfo $target | grep -qcs -i "State: COMPLETE"
}
# is package exists in bodhi
# Valid target example: cmake-fedora
function is_package_new_in_bodhi(){
local package=$1
{
LC_ALL=C
if $BODHI_CMD updates query --packages $package | grep '^0 updates found' > /dev/null; then
return 0
else
return 1
fi
}
}
function try_command(){
if ! "$@" ;then
ret=$?
echo "cmake-fedora-fedpkg: Failed to $@" > /dev/stderr
exit $ret
fi
}
# is target in bodhi
# Valid target example: cmake-fedora-1.4.0-1.fc21
function is_target_in_bodhi(){
local result=$($CURL_CMD -X GET "https://bodhi.fedoraproject.org/builds/?nvr=$1")
if [[ -z "$result" ]]; then
return 1
elif grep -qcs -i '"total": 0,' <<< "$result" > /dev/null;then
return 1
fi
return 0
}
function is_update_enhancement(){
echo $ChangeLogText | grep -qcs -e "Enhancement:"
}
## fedpkg_build <gitBranch> <firstBranch> [Options]
function fedpkg_build(){
local optArray=()
local gitBranch=$1
local firstBranch=$2
shift 2
echo -n "Has $Build already been built in koji? ... " > /dev/stderr
if is_target_built $Build ;then
echo "yes, skip this." > /dev/stderr
else
echo "no, start building." > /dev/stderr
if [[ $ScratchBuild -eq 1 ]];then
local kojiBranch=$($ScriptDir/cmake-fedora-koji branch $gitBranch)
try_command ${FEDPKG_CMD} --release $kojiBranch scratch-build --srpm "$Srpm" "$@"
else
## Real build
if [[ "$gitBranch" = "$firstBranch" ]];then
try_command $GIT_CMD stash
try_command $GIT_CMD fetch
try_command $FEDPKG_CMD switch-branch $gitBranch
try_command $FEDPKG_CMD pull
try_command $FEDPKG_CMD import "$Srpm"
## git diff --quiet also imply --exit-code
if ! $GIT_CMD diff --quiet HEAD ;then
# Has something to commit
try_command $FEDPKG_CMD commit -m "$ChangeLogText"
fi
try_command $FEDPKG_CMD push
try_command $FEDPKG_CMD build
else
try_command $FEDPKG_CMD switch-branch $gitBranch
try_command $GIT_CMD merge $firstBranch
try_command $FEDPKG_CMD push
try_command $FEDPKG_CMD build
fi
fi
fi
}
##=== Arguments Parsing ===
if [ $# = 0 ]; then
print_usage
exit $EXIT_OK
fi
WorkDir=${FEDPKG_DIR:-$PWD}
Msg=
BodhiOptArray=( --request testing )
Bugs=
ScratchBuild=0
UpdateType=
BodhiUser=${BODHI_USER:=$LOGNAME}
BodhiTargets=''
while getopts "hb:d:m:st:u:" opt;do
case $opt in
h)
print_usage
exit $EXIT_OK
;;
b )
Bugs="$OPTARG"
;;
d )
WorkDir="$OPTARG"
;;
m )
Msg="$OPTARG"
;;
s )
ScratchBuild=1
;;
t )
UpdateType="$OPTARG"
;;
u )
BodhiUser="$OPTARG"
;;
* )
;;
esac
done
shift $((OPTIND-1))
Srpm=${1-}
shift
if [[ -z $Srpm ]];then
print_usage
echo "Unspecified <Srpm>"
exit $EXIT_FATAL_INVALID_OPTIONS
fi
if [[ ! -r $Srpm ]];then
print_usage
echo "Failed to read file $Srpm"
exit $EXIT_FATAL_INVALID_OPTIONS
fi
## This program will change directory, need to know the absolute path
Srpm=$(cmfd_realpath $Srpm)
##=== Dependency Checking ===
cmfd_set_dependencies_programs bodhi curl fedpkg git koji rpm
BodhiMajorVer=$( $BODHI_CMD --version | sed -e 's/\..*$//' )
##=== Variable can be determined after dependency checking ===
Name=`$RPM_CMD -qp --queryformat "%{NAME}" $Srpm`
echo "Name=$Name" > /dev/stderr
## Nvr here does not include release tag,
## (e.g. cmake-fedora-2.0.0-1)
Nvr=`$RPM_CMD -qp --queryformat "%{nvr}" $Srpm | sed -e 's/\.fc[0-9]*$//' | sed -e 's/\.el[0-9]*$//'`
if [[ $ScratchBuild -eq 0 ]];then
ChangeLogText=$($RPM_CMD -qp --queryformat "%{ChangeLogText}" $Srpm)
echo "ChangeLogText=$ChangeLogText" > /dev/stderr
BodhiOptArray+=(--notes "$ChangeLogText")
## Variable that required by real build
if [[ -n "$Bugs" ]];then
BodhiOptArray+=(--bugs $Bugs)
else
BugStr=$(sed -E -ne '/RHBZ/ s/^.*[Ff]ixe[ds]\s*RHBZ#([0-9]+).*$/\1/ p' <<<"$ChangeLogText" | xargs)
if [[ -n $BugStr ]];then
BodhiOptArray+=(--bugs $(sed -E -e 's/\s+/,/g' <<< "$BugStr") )
fi
fi
if [[ -z "$Msg" ]];then
Msg=$ChangeLogText
fi
if [[ -z "$UpdateType" ]];then
if is_package_new_in_bodhi $Name; then
UpdateType=newpackage
elif is_update_enhancement; then
UpdateType=enhancement
else
UpdateType=bugfix
fi
fi
echo "UpdateType=$UpdateType" > /dev/stderr
BodhiOptArray+=(--type $UpdateType)
fi
##=== Determine Branch To Build ===
ScopeBranchArray=( $($ScriptDir/cmake-fedora-koji git-branch $@ ) )
PackageBranchArray=( $($ScriptDir/cmake-fedora-pkgdb git-branch $Name) )
declare -a ActionBranchArray=()
if [ -z "$PackageBranchArray" ];then
## Cannot found package in PkgDb, maybe a new package?
if [ $ScratchBuild -eq 0 ];then
## Failed as the non-scratch build requires a existing package
echo "[ERROR] Failed to find package $Name in PkgDB for a real build." > /dev/stderr
exit $EXIT_FATAL_FAIL
fi
ActionBranchArray=(${ScopeBranchArray[@]})
else
## Interset between scope and branches that package has
for activeBranch in "${PackageBranchArray[@]}"; do
if contains_element "$activeBranch" "${ScopeBranchArray[@]}";then
ActionBranchArray+=( $activeBranch )
fi
done
fi
echo -n "Branches to process:"
(IFS=' ' echo "${ActionBranchArray[@]}")
if [[ ${#ActionBranchArray[@]} -gt 1 && $ScratchBuild -eq 0 ]];then
## More than one branches for real build, thus need git branches
GitNeedMerge=1
else
GitNeedMerge=0
fi
if [[ $ScratchBuild -eq 0 ]];then
if [[ ! -w "$WorkDir" ]];then
if ! mkdir -p "$WorkDir"; then
echo "$WorkDir is not writable." > /dev/stderr
exit $EXIT_FATAL_INVALID_OPTIONS
fi
fi
cd "$WorkDir"
if [[ ! -x "$Name" ]] ;then
try_command $FEDPKG_CMD clone "$Name"
fi
echo "WorkDir=$WorkDir" > /dev/stderr
cd "$Name"
fi
##=== Build ===
First=
for b in "${ActionBranchArray[@]}";do
if [[ -z "$First" ]];then
First=$b
fi
KojiBuildInfoSuffix=$($ScriptDir/cmake-fedora-koji koji-buildinfo-suffix $b)
Build="$Nvr.$KojiBuildInfoSuffix"
try_command fedpkg_build "$b" "$First"
if [[ $ScratchBuild -eq 0 ]];then
## bodhi does not build rawhide
[[ $b = 'master' ]] && continue
BodhiBranch=$($ScriptDir/cmake-fedora-koji bodhi-branch $b)
if [[ -n "$BodhiBranch" ]];then
echo -n "Has $Build already in bodhi? ... " > /dev/stderr
if is_target_in_bodhi $Build ; then
echo "yes, skip this." > /dev/stderr
else
echo "no, will push it." > /dev/stderr
add_bodhi_target $Build
fi
fi
fi
done
if [[ $ScratchBuild -eq 0 ]];then
if [[ -n "$BodhiTargets" ]];then
if [[ $BodhiMajorVer -ge 2 ]];then
try_command ${BODHI_CMD} updates new "${BodhiOptArray[@]:-}" --user $BodhiUser $BodhiTargets
else
try_command ${BODHI_CMD} -n "${BodhiOptArray[@]:-}" -u $BodhiUser $BodhiTargets
fi
else
echo "Nothing to push to bodhi." > /dev/stderr
fi
fi
|