blob: 473b1a998a0b3d87f259a6e449bf6b5333d632f3 [file] [log] [blame]
#!/usr/bin/env sh
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# shellcheck shell=ash
if ! type -p realpath; then
# by default, macOS does not have realpath
realpath() {
ls "$(
cd "$(dirname "$0")"
pwd -P # -P resolves symlinks
)/$(basename "$0")"
}
export -f realpath
fi;
if { ! stat -c%u . >/dev/null && stat -f%u .; } >/dev/null 2>&1; then
#BSD stat uses -f as its formatting flag instead of -c
stat() {
local format=''
while getopts c: option; do
case "$option" in
c) format="$OPTARG";;
*) return 1
esac
done
shift $(( OPTIND - 1 ))
unset OPTIND
$(which stat) "-f${format}" "$@"
}
export -f stat
fi
removeFirstArg() {
shift
echo "$@"
}
# ---------------------------------------
# versionOk checks version number against required version.
# ``versionOk 1.2.3 2.0.4.7'' returns false value indicating
# version you have is not at least version you need
# if versionOk $haveversion $needversion; then
# echo "Need at least version $needversion"; return 1
# fi
versionOk() {
local h="$1" n="$2"
# string compare -- no need to do more if the same
[ "$h" = "$n" ] && return 0
# split into fields
local have="${h//\./ }"
local need="${n//\./ }"
# cmp first entry of each array. Bail when unequal.
while [ -n "$have" ] && [ "$have" = "$need" ]; do
# pop 1st entry from each
have="$(removeFirstArg ${have})"
need="$(removeFirstArg ${need})"
done
have="${have%% *}";
need="${need%% *}";
if [ "${have:-0}" -lt "${need:-0}" ]; then
return 1
fi
return 0
}
# ---------------------------------------
getRevCount() {
local buildNum
buildNum=$(getBuildNumber)
echo "${buildNum%.*}"
}
# ---------------------------------------
isInGitTree() {
# ignore output -- use exit status
git rev-parse --is-inside-work-tree >/dev/null 2>&1
}
# ---------------------------------------
getBuildNumber() {
local in_git=''
if isInGitTree; then
local commits sha
commits="$(git rev-list HEAD 2>/dev/null | wc -l | awk '{print $1}')" # awk is for BSD compatibility
sha="$(git rev-parse --short=8 HEAD)"
echo "$commits.$sha"
else
# Expect it's from the released tarball -- if BUILD_NUMBER file is not present, abort
if [ ! -f "${TC_DIR}/BUILD_NUMBER" ]; then
echo "Not in git repository and no BUILD_NUMBER present -- aborting!"
return 1
fi
grep -v '^#' "${TC_DIR}/BUILD_NUMBER"
fi
}
# ---------------------------------------
getGoVersion() {
local directory="$1"
local go_version_file="$directory/GO_VERSION"
[ -r "$go_version_file" ] || { echo "Could not read $go_version_file: $!"; return 1; }
cat "$go_version_file"
}
# ---------------------------------------
getVersion() {
local d="$1"
local vf="$d/VERSION"
[ -r "$vf" ] || { echo "Could not read $vf: $!"; return 1; }
cat "$vf"
}
# ---------------------------------------
getRhelVersion() {
local releasever=${RHEL_VERSION:-}
if [ -n "$releasever" ]; then
echo "el${releasever}"
return
fi
local redhat_release=/etc/redhat-release
local default_version=7
if [ -e $redhat_release ]; then
releasever="$(rpm -q --qf '%{version}' -f $redhat_release)"
releasever="${releasever%%.*}"
else
echo "${redhat_release} not found, defaulting to major release ${default_version}" >/dev/stderr
releasever=${default_version}
fi;
echo "el${releasever}"
}
# ---------------------------------------
getCommit() {
local buildNum
buildNum="$(getBuildNumber)"
echo "${buildNum%.*}"
}
# ---------------------------------------
checkEnvironment() {
include_programs='' exclude_programs=''
while getopts i:e: option; do
case "$option" in
i) include_programs="$OPTARG";;
e) exclude_programs="$OPTARG";;
*) return 1
esac
done
unset OPTIND
include_file="$(mktemp)"
exclude_file="$(mktemp)"
printf '%s\n' git rpmbuild ${include_programs//,/ } | sort >"$include_file"
printf '%s\n' ${exclude_programs//,/ } | sort >"$exclude_file"
programs="$(comm -23 "$include_file" "$exclude_file")"
rm "$include_file" "$exclude_file"
# verify required tools available in path -- extra tools required by subsystem are passed in
for program in $programs; do
if ! type "$program"; then
echo "$program not found in PATH"
return 1
fi
done
# verify git version
requiredGitVersion=1.7.12
if ! versionOk "$(git --version | tr -dc 0-9. )" "$requiredGitVersion"; then
echo "$(git --version) must be at least $requiredGitVersion"
return 1
fi
TC_VERSION='' BUILD_NUMBER='' RPMBUILD='' DIST=''
TC_VERSION="$(getVersion "$TC_DIR")"
BUILD_NUMBER="$(getBuildNumber)"
GO_VERSION="$(getGoVersion "$TC_DIR")"
RHEL_VERSION="$(getRhelVersion)"
WORKSPACE="${WORKSPACE:-$TC_DIR}"
RPMBUILD="$WORKSPACE/rpmbuild"
GOOS="${GOOS:-linux}"
RPM_TARGET_OS="${RPM_TARGET_OS:-$GOOS}"
DIST="$WORKSPACE/dist"
export TC_VERSION BUILD_NUMBER GO_VERSION RHEL_VERSION WORKSPACE RPMBUILD GOOS RPM_TARGET_OS DIST
mkdir -p "$DIST" || { echo "Could not create ${DIST}: ${?}"; return 1; }
echo "Build environment has been verified."
echo "=================================================="
echo "WORKSPACE: $WORKSPACE"
echo "BUILD_NUMBER: $BUILD_NUMBER"
echo "RHEL_VERSION: $RHEL_VERSION"
echo "TC_VERSION: $TC_VERSION"
echo "--------------------------------------------------"
}
# ---------------------------------------
createSourceDir() {
local target="${1}-${TC_VERSION}"
local srcpath="$RPMBUILD/SOURCES/$target"
mkdir -p "$srcpath" || { echo "Could not create $srcpath: $?"; return 1; }
echo "$srcpath"
}
# ---------------------------------------
buildRpm() {
for package in "$@"; do
local pre="${package}-${TC_VERSION}-${BUILD_NUMBER}.${RHEL_VERSION}"
local rpm
rpm="${pre}.$(uname -m).rpm"
local srpm="${pre}.src.rpm"
echo "Building the rpm."
{ set +o nounset
set -- # Clear arguments for reuse
if [ "$DEBUG_BUILD" = true ]; then
echo 'RPM will not strip binaries before packaging.';
set -- "$@" --define '%__os_install_post %{nil}' # Do not strip binaries before packaging
fi;
set -- "$@" --define '%_source_payload w2.xzdio' # xz level 2 compression for text files
set -- "$@" --define '%_binary_payload w2.xzdio' # xz level 2 compression for binary files
set -o nounset; }
build_flags="-ba";
if [[ "$NO_SOURCE" -eq 1 ]]; then
build_flags="-bb";
fi
pushd "$RPMBUILD";
rpmbuild --define "_topdir $(pwd)" \
--define "traffic_control_version $TC_VERSION" \
--define "go_version $GO_VERSION" \
--define "commit $(getCommit)" \
--define "build_number $BUILD_NUMBER.$RHEL_VERSION" \
--define "_target_os $RPM_TARGET_OS" \
"$build_flags" SPECS/$package.spec \
"$@";
code=$?
if [[ "$code" -ne 0 ]]; then
echo "RPM BUILD FAILED: $code" >&2;
return $code;
fi
echo
echo "========================================================================================"
echo "RPM BUILD FOR $package SUCCEEDED, See $DIST/$rpm for the newly built rpm."
echo "========================================================================================"
echo
rpmDest=".";
srcRPMDest=".";
if [[ "$SIMPLE" -eq 1 ]]; then
rpmDest="${package}.rpm";
srcRPMDest="${package}.src.rpm";
fi
cp -f "$RPMBUILD/RPMS/$(uname -m)/$rpm" "$DIST/$rpmDest";
code="$?";
if [[ "$code" -ne 0 ]]; then
echo "Could not copy $rpm to $DIST: $code" >&2;
return "$code";
fi
if [[ "$NO_SOURCE" -eq 1 ]]; then
return 0;
fi
cp -f "$RPMBUILD/SRPMS/$srpm" "$DIST/$srcRPMDest";
code="$?";
if [[ "$code" -ne 0 ]]; then
echo "Could not copy $srpm to $DIST: $code" >&2;
return "$code";
fi
done
}
# ---------------------------------------
createTarball() {
local projDir
projDir="$(cd "$1"; pwd)"
local projName=trafficcontrol
local version
version="$(getVersion "$TC_DIR")"
local tarball="dist/apache-${projName}-${version}.tar.gz"
local tarDir
tarDir="$(basename "$tarball" .tar.gz)"
local tarLink
( trap 'rm -f "${projDir}/BUILD_NUMBER" "$projLink"' EXIT
projLink="$(dirname "$projDir")/${tarDir}"
ln -sf "$projDir" "$projLink"
# Create a BUILDNUMBER file and add to tarball
getBuildNumber >"${projDir}/BUILD_NUMBER"
# create the tarball from BUILD_NUMBER and files tracked in git
git ls-files |
sed "s|^|${tarDir}/|g" |
tar -czf "$tarball" -C "${projLink}/.." -T - "${tarDir}/BUILD_NUMBER"
# ^ read files from stdin to avoid tar argument limit
)
echo "$tarball"
}
# ---------------------------------------
createDocsTarball() {
local projDir
projDir="$(cd "$1"; pwd)"
local projName=trafficcontrol
local version
version="$(getVersion "$TC_DIR")"
local tarball="dist/apache-$projName-$version-docs.tar.gz"
local tarDir="${projDir}/docs/build/"
# Create a BUILDNUMBER file and add to tarball
getBuildNumber >"${tarDir}/BUILD_NUMBER"
# create the tarball only from files in repo and BUILD_NUMBER
tar -czf "$tarball" -C "$tarDir" .
rm "${tarDir}/BUILD_NUMBER"
echo "$tarball"
}
# ----------------------------------------
# verify whether the minor-level version of the go compiler is greater or equal
# to the minor-level version in the GO_VERSION file: returns 0 if if not.
# returns 1 if it is.
#
verify_and_set_go_version() {
if [ -v GO_VERSION ]; then
GO_VERSION="$(getGoVersion .)"
else
GO_VERSION=''
fi
local major_version="$(echo "$GO_VERSION" | awk -F. '{print $1}')"
local minor_version="$(echo "$GO_VERSION" | awk -F. '{print $2}')"
GO_VERSION="none"
GO="none"
go_in_path="$(type -p go)"
local group_1='' group_2=''
for g in "$go_in_path" /usr/bin/go /usr/local/go/bin/go; do
if [ -z "$g" ] || [ ! -x "$g" ]; then
continue
fi
go_version="$($g version | awk '{print $3}')"
version_pattern='.*go([1-9]+)\.([1-9]+).*'
if echo "$go_version" | grep -E "$version_pattern"; then
group_1="$(echo "$go_version" | sed -E "s/${version_pattern}/\1/")"
group_2="$(echo "$go_version" | sed -E "s/${version_pattern}/\2/")"
if [ ! "$group_1" -ge "$major_version" ] || [ ! "$group_2" -ge "$minor_version" ]; then
GO_VERSION="${group_1}.${group_2}"; export GO_VERSION
echo "go version for $g is ${group_1}.${group_2}"
continue
fi
GO_VERSION="${group_1}.${group_2}"; export GO_VERSION
GO=$g; export GO
PATH="$(dirname "$g"):${PATH}"; export PATH
echo "go version for $g is ${group_1}.${group_2}"
echo "will use $g"
return 0
fi
done
if [ "$GO" = none ]; then
echo "ERROR: this build needs go ${major_version}.${minor_version} or greater and no usable go compiler was found, found GO_VERSION: $GO_VERSION"
unset GO_VERSION
return 1
fi
}