#! /usr/bin/env bash # Use fpm to package up files into an RPM. # Usage: # mk_rpm_fpmdir PACKAGENAME MANIFEST1 MANIFEST2 ... # Example: # Make a package foopkg manifest.txt # Where "manifest.txt" contains: # exec /usr/bin/stack_makefqdn misc/stack_makefqdn.py # exec /usr/bin/bar bar/bar.sh # read /usr/man/man1/bar.1 bar/bar.1.man # 0444 /etc/foo.conf bar/foo.conf set -e # Parameters for this RPM: PACKAGENAME=${1?"First arg must be the package name."} shift # What is my name? CMDNAME=$(basename $0) # Defaults that can be overridden: # Packages are 1.0 unless otherwise specifed: : ${PKGVERSION:=1.0} ; # If there is no iteration set, default to use the number of commits in the repository: if [[ -z "${PKGRELEASE}" ]]; then PKGRELEASE=$(git rev-list HEAD --count) if [[ $? != 0 ]]; then # We're not in a git repo, fall back to 1 so we cope with being built from # a tarball PKGRELEASE=1 fi fi # If there is no epoch, assume 0 : ${PKGEPOCH:=0} # If no arch defined, assume any. Other good values include "native". : ${PKGARCH:=all} # NOTE: If we later compile code, we set this to "native", which # FPM will translate to the correct value for local conditions. # Allow us to set a different OUTPUTDIR if we're building in CI/CD if [[ -z "${OUTPUTDIR}" ]]; then # The RPM is output here: (should be a place that can be wiped) OUTPUTDIR="${HOME}/rpmbuild-${PACKAGENAME}" else echo "Using ${OUTPUTDIR} for OUTPUTDIR instead of ${HOME}/rpmbuild-${PACKAGENAME}" fi INSTALLROOT="$OUTPUTDIR/installroot" # StackOverflow's TeamCity templates expect to find the list of artifacts here: RPM_BIN_LIST="${OUTPUTDIR}/bin-packages.txt" # -- Now the real work can be done. # Clean the output dir. rm -rf "$OUTPUTDIR" mkdir -p "$INSTALLROOT" # If there is a build script, execute it. BUILDSCRIPTNAME="./build.${PACKAGENAME}.sh" if [[ -x $BUILDSCRIPTNAME ]]; then echo "========== $BUILDSCRIPTNAME FOUND. Running." if [[ $PKGARCH == "all" ]]; then echo 'WARNING: PKGARCH=all (which may not what you want)' # If you are using a build.*.sh script, you probably want to # set PKGARCH to "native" before you run mk_rpm_fpmdir. fi $BUILDSCRIPTNAME "$INSTALLROOT" "${PKGVERSION}" # If we used the build build.*.sh script, it must do all compilation. # Therefore, we disable the automagic GO build feature. GO_COMPILE=false else GO_COMPILE=true fi # If there are additional args for fpm, read them into a variable. There is # a chdir later, therefore we can't rely on the file path working at that time. FPM_OPTIONS_FILE="./fpm_opts.${PACKAGENAME}.sh" if [[ -f $FPM_OPTIONS_FILE ]]; then echo "========== $FPM_OPTIONS_FILE FOUND. Loading." FPM_OPTIONS=$(<$FPM_OPTIONS_FILE) fi # Warning: The contents of the file are evaluated therefore # quotes and special chars must be quoted. # Copy any static files into place: set -o pipefail # Error out if any manifest is not found. cat "$@" | while read -a arr ; do PERM="${arr[0]}" case $PERM in \#*) continue ;; # Skip comments. exec) PERM=0755 ;; read) PERM=0744 ;; *) ;; esac DST="$INSTALLROOT/${arr[1]}" SRC="${arr[2]}" if [[ ${#arr[@]} != 3 ]] ; then echo "ERROR: Line must contain 3 items." echo "DEBUG NUM=${#arr[@]} PERM=$PERM DST=$DST SRC=$SRC" exit 1 fi if $GO_COMPILE && [[ $SRC == "cmd/"* || $SRC == *"/cmd/"* ]]; then echo "========== BUILD© $SRC" ( cd $(dirname "$SRC" ) && go get -d && go build ) PKGARCH=native else echo "========== COPY $SRC" fi if [[ ! -f "$SRC" ]]; then echo "${CMDNAME}: ERROR: File not found: $SRC" exit 1 fi install -D -T -b -m "$PERM" -T "$SRC" "$DST" done set -x # Build the RPM out of what is found in $INSTALLROOT: cd "$OUTPUTDIR" && fpm -s dir -t rpm \ -a "${PKGARCH}" \ -n "${PACKAGENAME}" \ --epoch "${PKGEPOCH}" \ --version "${PKGVERSION}" \ --iteration "${PKGRELEASE}" \ ${PKGDESCRIPTION:+ --description="${PKGDESCRIPTION}"} \ ${PKGVENDOR:+ --vendor="${PKGVENDOR}"} \ ${FPM_OPTIONS:+ $FPM_OPTIONS} \ -C "$INSTALLROOT" \ . # TeamCity templates for RPMS expect to find # the list of all packages created in bin-packages.txt. # Generate that list: find "$OUTPUTDIR" -maxdepth 1 -name '*.rpm' >"$RPM_BIN_LIST" # Output it for debugging purposes: cat "$RPM_BIN_LIST"