#!/bin/sh
# Consume test requests from AMQP queue and feed them to debci-test
set -eu

short_options='t:'
long_options='tag:,do-request'

usage() {
  cat <<EOF
usage: debci-worker [OPTIONS]

Options:
  -t TAG, --tag TAG         listen to queues which require this platform tag
                            (can be specified multiple times)

$@
EOF
}

debci_base_dir=$(readlink -f $(dirname $(readlink -f $0))/..)
. $debci_base_dir/lib/environment.sh
. $debci_base_dir/lib/functions.sh

tags=''

# Process one request. Read the AMQP message from stdin.
do_request() {
  local request
  local pkg
  local suite
  local opts

  read request || true  # we expect EOF and thus read to fail
  set -- $request
  if [ $# -eq 0 ]; then
    return
  fi
  pkg="$1"
  suite="${2:-}"
  if [ -n "$suite" ]; then
    shift 2
  else
    suite="$debci_suite"
    shift 1
  fi

  releases=""
  opts=""
  run_id=0
  for param in $@; do
    case "$param" in
      trigger:*)
        opts="$opts --trigger=${param#trigger:}"
        ;;
      pin-packages:*)
        arg=${param#pin-packages:}
        opts="$opts --pin-packages=$arg"
        ;;
      run-id:*)
        arg=${param#run-id:}
        run_id="${arg}"
        opts="$opts --run-id=${run_id}"
        ;;
      extra-apt-source:*)
        arg=${param#extra-apt-source:}
        opts="$opts --extra-apt-source=$arg"
        ;;
      signing-key:*)
        arg=${param#signing-key:}
        opts="$opts --signing-key=$arg"
        ;;
      *)
        echo "Unknown test parameter: $param" >&2
        ;;
    esac
  done

  if ! (echo "$pkg" | grep -q '^[a-z0-9.+-]\+$'); then
    log "W: invalid package name: $pkg, ignoring"
    return
  fi

  log "$pkg $suite/$debci_arch/$debci_backend (${run_id}) started"

  tmp_dir=$(mktemp --directory --tmpdir debci-worker-${run_id}-XXXXXXXXXX)
  trap 'rm -rf ${tmp_dir}' INT TERM EXIT

  # run the test
  local result_dir="$(
    debci-test \
      --quiet \
      --data-dir "$tmp_dir" \
      --suite "$suite" \
      --arch "${debci_arch}" \
      --backend "${debci_backend}" \
      --print-output \
      $opts \
      "$pkg"
  )"

  if [ ! -s "$result_dir/exitcode" ]; then
    log_error "E: Test for package $pkg produced no exit code, aborting"
    exit 2
  fi

  # debci_suite has to passed in to report_status because the worker is running
  # using the "default" suite which is usually unstable, which might be
  # different from the suite in which the test has actually just been executed.
  case $(cat "$result_dir/exitcode") in
      0|2)
        status=pass
        ;;
      4|6|12|14)
        status=fail
        ;;
      8)
        status=neutral
        ;;
      *)
        status=tmpfail
        ;;
  esac
  log "$pkg $suite/$debci_arch/$debci_backend (${run_id}) ${status}"


  # move result into results dir and let debci-publisher send the results
  result_dir=${result_dir##$tmp_dir/}
  result_file="${tmp_dir}/${run_id}.${debci_backend}.tar.gz"
  ( cd $tmp_dir && tar czf "${result_file}" "$result_dir" )
  mkdir -p "${debci_results_dir}"
  mv "${result_file}" "${debci_results_dir}/"
  stamp_file="$(basename "${result_file}" .tar.gz).stamp"
  touch "${debci_results_dir}/${stamp_file}"
}

# parse CLI arguments
while true; do
  case "$1" in
    -t|--tag)
      tags="${tags}_$2"
      shift 2
      ;;
    --do-request)
      do_request
      exit 0
      ;;
    *)
      break
      ;;
  esac
done

amqp-declare-queue \
  --url="$debci_amqp_server" \
  $debci_amqp_tools_options \
  --durable \
  --queue="$debci_amqp_results_queue" > /dev/null

# if the user calls this, we run forever with consuming messages;
# amqp-consume calls ourselves with the (hidden) --do-request option
amqp_queue="${debci_amqp_queue}${tags}"
log "I: Connecting to AMQP queue $amqp_queue on ${debci_amqp_server_display}"
debci amqp declare-queue --arch="${debci_arch}" --backend="${debci_backend}"
exec amqp-consume \
  --url ${debci_amqp_server} \
  $debci_amqp_tools_options \
  --queue=$amqp_queue \
  --prefetch-count 1 \
  -- \
  $0 --do-request --arch="${debci_arch}" --backend="${debci_backend}"
