Skip to content
Snippets Groups Projects
build.sh 11.9 KiB
Newer Older
rubo77's avatar
rubo77 committed
#!/bin/bash -e
# =====================================================================
# Build script for Freifunk Nord firmware
#
# Source: 
# Contact: 
# Web: 
#
# Credits:
#   - Freifunk Darmstadt for your great support
#   - Freifunk Fulda for the base of the gitlab-ci support
# =====================================================================

rubo77's avatar
rubo77 committed
# Default make options (override with -m)
Ruben Barkow's avatar
Ruben Barkow committed
MAKEOPTS="-j 4 GLUON_DEPRECATED=upgrade"
rubo77's avatar
rubo77 committed

# Default is set to use current work directory
SITEDIR="$(pwd)"

# Default build identifier set to snapshot
BUILD="snapshot"

# Specify deployment server and user
DEPLOYMENT_SERVER="116.202.216.125"
rubo77's avatar
rubo77 committed
DEPLOYMENT_USER="rsync"
DEPLOYMENT_PATH="/opt/firmware/nord"

# Path to signing key
SIGNKEY=""

# Error codes
E_ILLEGAL_ARGS=126

# Help function used in error messages and -h option
rubo77's avatar
rubo77 committed
usage() {
  echo ""
  echo "Build script for Freifunk-Fulda gluon firmware."
  echo ""
  echo "-a: Autoupdater branch name (e.g. development)"
  echo "    Default: branch (see -b)"
rubo77's avatar
rubo77 committed
  echo "-b: Firmware branch name (e.g. development)"
  echo "    Default: current git branch"
  echo "-c: Build command: update | clean | download | build | sign | upload | prepare"
  echo "-d: Enable bash debug output"
  echo "-h: Show this help"
  echo "-m: Setting for make options (optional)"
  echo "    Default: \"${MAKEOPTS}\""
  echo "-n: Build identifier (optional)"
  echo "    Default: \"${BUILD}\""
  echo "-t: Gluon targets architectures to build"
  echo "    Default: \"${TARGETS}\""
  echo "-u: Upload target"
  echo "    Default: branch (see -b)"
rubo77's avatar
rubo77 committed
  echo "-r: Release number (optional)"
  echo "    Default: fetched from release file"
  echo "-w: Path to site directory"
  echo "    Default: current working directory"
  echo "-s: Path to signing key"
  echo "    Default: empty"
}

# Evaluate arguments for build script.
if [[ "${#}" == 0 ]]; then
  usage
  exit ${E_ILLEGAL_ARGS}
fi

# Evaluate arguments for build script.
while getopts a:b:c:dhm:n:t:u:w:s: flag; do
rubo77's avatar
rubo77 committed
  case ${flag} in
rubo77's avatar
rubo77 committed
    b)
        BRANCH="${OPTARG}"
	if [ "${BRANCH}" == "release-candidate" ] ; then
          BRANCH="rc"
	fi
rubo77's avatar
rubo77 committed
        ;;
    c)
      case "${OPTARG}" in
        update)
          COMMAND="${OPTARG}"
          ;;
        clean)
          COMMAND="${OPTARG}"
          ;;
        download)
          COMMAND="${OPTARG}"
          ;;
        build)
          COMMAND="${OPTARG}"
          ;;
        sign)
          COMMAND="${OPTARG}"
          ;;
        upload)
          COMMAND="${OPTARG}"
          ;;
        prepare)
          COMMAND="${OPTARG}"
          ;;
        *)
          echo "Error: Invalid build command set."
          usage
          exit ${E_ILLEGAL_ARGS}
          ;;
      esac
      ;;
    d)
      set -x
      ;;
    h)
      usage
      exit
      ;;
    m)
      MAKEOPTS="${OPTARG}"
      ;;
    n)
      BUILD="${OPTARG}"
      ;;
    t)
      TARGETS="${OPTARG}"
      ;;
rubo77's avatar
rubo77 committed
    r)
      RELEASE="${OPTARG}"
      ;;
    w)
      # Use the root project as site-config for make commands below
      SITEDIR="${OPTARG}"
      ;;
    s)
      SIGNKEY="${OPTARG}"
      ;;
    *)
      usage
      exit ${E_ILLEGAL_ARGS}
      ;;
  esac
done

# Strip of all remaining arguments
shift $((OPTIND - 1));

# Check if there are remaining arguments
if [[ "${#}" > 0 ]]; then
  echo "Error: Too many arguments: ${*}"
rubo77's avatar
rubo77 committed
  usage
  exit ${E_ILLEGAL_ARGS}
fi

# Set branch name
if [[ -z "${BRANCH}" ]]; then
  BRANCH=$(git symbolic-ref -q HEAD)
  BRANCH=${BRANCH##refs/heads/}
  BRANCH=${BRANCH:-HEAD}
fi

# Default to build branch specific targets if parameter -t is not set 
if [[ -z ${TARGETS+x} ]] ; then
  case "${BRANCH}" in
Ruben Barkow-Kuder's avatar
Ruben Barkow-Kuder committed
    "nord-2020.2.x")
Ruben Barkow's avatar
Ruben Barkow committed
      # all targets
      TARGETS="ar71xx-generic ar71xx-tiny ar71xx-nand ath79-generic brcm2708-bcm2708 brcm2708-bcm2709 ipq40xx-generic ipq806x-generic lantiq-xrx200 lantiq-xway mpc85xx-generic mpc85xx-p1020 ramips-mt7620 ramips-mt7621 ramips-mt76x8 ramips-rt305x sunxi-cortexa7"
      TARGETS+=" x86-generic x86-geode x86-64" # (VMs)
      TARGETS+=" ar71xx-mikrotik brcm2708-bcm2710 mvebu-cortexa9" # BROKEN targets
      ;;
    "master")
      TARGETS="ar71xx-tiny ar71xx-generic"
      TARGETS+=" ath79-generic" # (TP-Link Archer C6 v2, devolo WiFi pro 1200i)
rubo77's avatar
rubo77 committed
      TARGETS+=" x86-64 x86-generic" # (VMs)
      #TARGETS+=" ar71xx-nand" # (Netgear WNDR3700, WNDR4300, ZyXEL NBG6716)
Ruben Barkow's avatar
Ruben Barkow committed
      #TARGETS+=" mpc85xx-generic" # (tp-link-tl-wdr4900-v1)
Ruben Barkow's avatar
Ruben Barkow committed
      #TARGETS+=" ramips-mt7620" # (gl-inet mt300 und mt750, TP-Link Archer C2 (v1), C20 (v1), C20i, C50 (v1))
      #TARGETS+=" sunxi-cortexa7" # (Banana Pi M1)

Ruben Barkow's avatar
Ruben Barkow committed
      #TARGETS+=" brcm2708-bcm2708 brcm2708-bcm2709 brcm2708-bcm2710" # (raspberry Pi 1, 2)
      TARGETS+=" ipq40xx-generic" # (FitzBox 4040)
      TARGETS+=" lantiq-xrx200" # (FitzBox 7360 (v1, v2), 7360 SL, 7362 SL, 7412)
      TARGETS+=" ramips-mt7621" # (D-Link DIR-860L (B1) Ubiquiti EdgeRouter X, ZBT WG3526, Netgear EX6150 (v1), Netgear R6220)
Ruben Barkow's avatar
Ruben Barkow committed
      #TARGETS+=" ramips-mt76x8" # unstable WiFi (tp-link 841 v13, Netgear R6120 und archer c50)
Ruben Barkow's avatar
Ruben Barkow committed
      #TARGETS+=" ramips-rt305x" # (fonera, vocore a5)
      #TARGETS+=" ipq806x-generic" # unstable wifi drivers (tp-link-archer-c2600)
      
      # BROKEN:
      #TARGETS+=" ar71xx-mikrotik" # BROKEN: no sysupgrade support (mikrotik-nand)
      #TARGETS+=" brcm2708-bcm2710" # BROKEN: Untested (raspberry-pi-3)
      #TARGETS+=" mvebu-cortexa9" # BROKEN: No AP+IBSS or 11s support (linksys-wrt1200ac)
Ruben Barkow's avatar
Ruben Barkow committed
      # all targets
      TARGETS="ar71xx-generic ar71xx-tiny ar71xx-nand ath79-generic brcm2708-bcm2708 brcm2708-bcm2709 ipq40xx-generic ipq806x-generic lantiq-xrx200 lantiq-xway mpc85xx-generic mpc85xx-p1020 ramips-mt7620 ramips-mt7621 ramips-mt76x8 ramips-rt305x sunxi-cortexa7"
      TARGETS+=" x86-generic x86-geode x86-64" # (VMs)
      TARGETS+=" ar71xx-mikrotik brcm2708-bcm2710 mvebu-cortexa9" # BROKEN targets
    ;;
  esac
fi

if [[ -z "$AU_BRANCH" ]]; then
  AU_BRANCH="$BRANCH"
fi

if [[ -z "$UPLOAD_TARGET" ]]; then
  UPLOAD_TARGET="$BRANCH"
fi

rubo77's avatar
rubo77 committed
# Set command
if [[ -z "${COMMAND}" ]]; then
  echo "Error: Build command missing."
  usage
  exit ${E_ILLEGAL_ARGS}
fi

# Normalize the branch name
BRANCH="${BRANCH#origin/}" # Use the current git branch as autoupdate branch
BRANCH="${BRANCH//\//-}"   # Replace all slashes with dashes

rubo77's avatar
rubo77 committed
# Set release number
if [[ -z "${RELEASE}" ]]; then
  RELEASE=$(sed -e "s/BUILD/$BUILD/" "${SITEDIR}/release")
  case "${BRANCH}" in
    nightly)
      RELEASE="${RELEASE}~ngly"
      ;;
    next)
      RELEASE="${RELEASE}~next"
      ;;
    *)
      # Do nothing
      ;;
  esac
rubo77's avatar
rubo77 committed
fi

# Get the GIT commit description
COMMIT="$(git describe --always --dirty)"

# Number of days that may pass between releasing an updating
if [[ -z ${PRIORITY+x} ]] ; then
  case "${BRANCH}" in
    nightly)
      PRIORITY=0
      ;;
    *)
      PRIORITY=1
      ;;
  esac
fi
rubo77's avatar
rubo77 committed

update() {
  echo "--- Update Gluon Dependencies"
  make ${MAKEOPTS} \
       GLUON_SITEDIR="${SITEDIR}" \
       GLUON_OUTPUTDIR="${SITEDIR}/output" \
       GLUON_RELEASE="${RELEASE}" \
       GLUON_BRANCH="${AU_BRANCH}" \
rubo77's avatar
rubo77 committed
       GLUON_PRIORITY="${PRIORITY}" \
       update
}

clean() {
  for TARGET in ${TARGETS}; do
    echo "--- Clean Gluon Build Artifacts for target: ${TARGET}"
    make ${MAKEOPTS} \
         GLUON_SITEDIR="${SITEDIR}" \
         GLUON_OUTPUTDIR="${SITEDIR}/output" \
         GLUON_RELEASE="${RELEASE}" \
         GLUON_BRANCH="${AU_BRANCH}" \
rubo77's avatar
rubo77 committed
         GLUON_PRIORITY="${PRIORITY}" \
         GLUON_TARGET="${TARGET}" \
         clean
  done
}

download() {
  for TARGET in ${TARGETS}; do
    echo "--- Download Gluon Dependencies for target: ${TARGET}"
    make ${MAKEOPTS} \
         GLUON_SITEDIR="${SITEDIR}" \
         GLUON_OUTPUTDIR="${SITEDIR}/output" \
         GLUON_RELEASE="${RELEASE}" \
         GLUON_BRANCH="${AU_BRANCH}" \
rubo77's avatar
rubo77 committed
         GLUON_PRIORITY="${PRIORITY}" \
         GLUON_TARGET="${TARGET}" \
         download
  done
}

build() {
  for TARGET in ${TARGETS}; do
    echo "--- Build Gluon Images for target: ${TARGET}"
rubo77's avatar
rubo77 committed
        make ${MAKEOPTS} \
             GLUON_SITEDIR="${SITEDIR}" \
             GLUON_OUTPUTDIR="${SITEDIR}/output" \
             GLUON_RELEASE="${RELEASE}" \
             GLUON_BRANCH="${AU_BRANCH}" \
rubo77's avatar
rubo77 committed
             GLUON_PRIORITY="${PRIORITY}" \
             GLUON_TARGET="${TARGET}"
        ;;

      *)
        make ${MAKEOPTS} \
             GLUON_SITEDIR="${SITEDIR}" \
             GLUON_OUTPUTDIR="${SITEDIR}/output" \
             GLUON_RELEASE="${RELEASE}" \
             GLUON_BRANCH="${AU_BRANCH}" \
rubo77's avatar
rubo77 committed
             GLUON_TARGET="${TARGET}"
      ;;
    esac
  done

  echo "--- Build Gluon Manifest"
  make ${MAKEOPTS} \
       GLUON_SITEDIR="${SITEDIR}" \
       GLUON_OUTPUTDIR="${SITEDIR}/output" \
rubo77's avatar
rubo77 committed
       GLUON_BRANCH="${BRANCH}" \
       GLUON_PRIORITY="${PRIORITY}" \
       manifest

  cp "${SITEDIR}/output/images/sysupgrade/${BRANCH}.manifest" \
     "${SITEDIR}/output/images/sysupgrade/${BRANCH}.manifest.clean"

rubo77's avatar
rubo77 committed
  echo "--- Write Build file"
  cat > "${SITEDIR}/output/images/build" <<EOF
DATE=$(date '+%Y-%m-%d %H:%M:%S')
VERSION=$(cat "${SITEDIR}/release")
RELEASE=${RELEASE}
BUILD=${BUILD}
BRANCH=${BRANCH}
COMMIT=${COMMIT}
HOST=$(uname -n)
EOF
}

sign() {
  echo "--- Sign Gluon Firmware Build"

  # Add the signature to the local manifest
  contrib/sign.sh \
      "${SIGNKEY}" \
      "${SITEDIR}/output/images/sysupgrade/${BRANCH}.manifest"
}

upload() {
rubo77's avatar
rubo77 committed
  echo "--- Upload Gluon Firmware Images and Manifest"

  # Build the ssh command to use
  SSH="ssh"
  SSH="${SSH} -o stricthostkeychecking=no -v"

  # Determine upload target prefix
rubo77's avatar
rubo77 committed

  # Create the target directory on server
  ${SSH} \
      ${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER} \
      -- \
      mkdir \
          --parents \
          --verbose \
          "${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}"
rubo77's avatar
rubo77 committed

  # Add site metadata
  tar -czf "${SITEDIR}/output/images/site.tgz" --exclude='gluon' --exclude='output' "${SITEDIR}"

  # Compress images (Saves around 40% space, relevant because of shitty VDSL 50 upload speeds)
  echo "Compressing images..."
rubo77's avatar
rubo77 committed
  tar -cJf "${SITEDIR}/output/images.txz" -C "${SITEDIR}/output/images/" factory sysupgrade other
rubo77's avatar
rubo77 committed
  # Copy images to server
rubo77's avatar
rubo77 committed
  rsync \
      --verbose \
      --progress \
      --chmod=ugo=rwX \
Daniel Ehlers's avatar
Daniel Ehlers committed
      --rsh="${SSH} -p 22555" \
      "${SITEDIR}/output/images.txz" \
      "${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER}:${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}"

  echo "Uncompressing images..."
  ${SSH} \
      ${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER} \
      -- \
     tar -xJf "${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}/images.txz" -C "${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}/"

rubo77's avatar
rubo77 committed
  ${SSH} \
      ${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER} \
      -- \
      ln -sf \
          "${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}/sysupgrade" \
rubo77's avatar
rubo77 committed
          "${DEPLOYMENT_PATH}/${TARGET}/"
  ${SSH} \
      ${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER} \
      -- \
      ln -sf \
          "${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}/factory" \
rubo77's avatar
rubo77 committed
          "${DEPLOYMENT_PATH}/${TARGET}/"
rubo77's avatar
rubo77 committed
  ${SSH} \
      ${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER} \
      -- \
      ln -sf \
          "${DEPLOYMENT_PATH}/${TARGET}/${RELEASE}/other" \
          "${DEPLOYMENT_PATH}/${TARGET}/"
rubo77's avatar
rubo77 committed
}

prepare() {
  echo "--- Prepare directory for upload"

  # Determine upload target prefix
rubo77's avatar
rubo77 committed

  # Create the target directory on server
  mkdir \
    --parents \
    --verbose \
    "${SITEDIR}/output/firmware/${TARGET}"

  # Copy images to directory
  mv \
    --verbose \
    "${SITEDIR}/output/images" \
    "${SITEDIR}/output/firmware/${TARGET}/${RELEASE}"
rubo77's avatar
rubo77 committed

  # Link latest upload in target to 'current'
  cd "${SITEDIR}/output"
  ln \
      --symbolic \
      --force \
      --no-target-directory \
rubo77's avatar
rubo77 committed
      "firmware/${TARGET}/current"
}

(
  # Change working directory to gluon tree
  cd "${SITEDIR}/gluon"

  # Execute the selected command
  ${COMMAND}
)