Bulk merge from repo:ci-managment

Change-Id: I7b733b43699b47deaaec2fe433987619b6928158
diff --git a/makefiles/commands/kail/README.md b/makefiles/commands/kail/README.md
new file mode 100644
index 0000000..470fd3c
--- /dev/null
+++ b/makefiles/commands/kail/README.md
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------
+# Workaround for godownloader disappearing:
+#   This is a complete hack to get bbsim and v-s-t functional again.
+#   A more permanent answer is needed, copy binaries into a *tool* repo
+#   and use directly from git clone w/o access or install overhead.
+# ----------------------------------------------------------------------
+
+1) Retrieve an archived copy of the script and place in v-s-t/etc.
+   https://searchcode.com/file/316605398/godownloader.sh
+2) A few script edits are needed:
+     o change download method from curl to wget.
+     o VERSION= variable requires a 'v' prefix.
+3) Update Makefile to install the new command.
+
+# [EOF]
diff --git a/makefiles/commands/kail/godownloader.sh b/makefiles/commands/kail/godownloader.sh
new file mode 100755
index 0000000..77ad5bf
--- /dev/null
+++ b/makefiles/commands/kail/godownloader.sh
@@ -0,0 +1,390 @@
+#!/bin/sh
+set -e
+# Code generated by godownloader on 2019-05-28T19:49:53Z. DO NOT EDIT.
+# Copyright 2019 - (disable makefiles/lint/license.mk)
+#
+
+usage() {
+  this=$1
+  cat <<EOF
+$this: download go binaries for boz/kail
+
+Usage: $this [-b] bindir [-d] [tag]
+  -b sets bindir or installation directory, Defaults to ./bin
+  -d turns on debug logging
+   [tag] is a tag from
+   https://github.com/boz/kail/releases
+   If tag is missing, then the latest will be used.
+
+ Generated by godownloader
+  https://github.com/goreleaser/godownloader
+
+EOF
+  exit 2
+}
+
+parse_args() {
+  #BINDIR is ./bin unless set be ENV
+  # over-ridden by flag below
+
+  BINDIR=${BINDIR:-./bin}
+  while getopts "b:dh?x" arg; do
+    case "$arg" in
+      b) BINDIR="$OPTARG" ;;
+      d) log_set_priority 10 ;;
+      h | \?) usage "$0" ;;
+      x) set -x ;;
+    esac
+  done
+  shift $((OPTIND - 1))
+  TAG=$1
+}
+# this function wraps all the destructive operations
+# if a curl|bash cuts off the end of the script due to
+# network, either nothing will happen or will syntax error
+# out preventing half-done work
+execute() {
+  tmpdir=$(mktemp -d)
+  log_debug "downloading files into ${tmpdir}"
+
+  # ---------------------------------------------------------
+  # [JOEY] - strange, curl fails to retrieve but wget is fine.
+  # ---------------------------------------------------------
+  #  http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
+  http_download_wget "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
+
+  http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
+  hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
+  srcdir="${tmpdir}"
+  (cd "${tmpdir}" && untar "${TARBALL}")
+  test ! -d "${BINDIR}" && install -d "${BINDIR}"
+# shellcheck disable=SC2043 
+  for binexe in "kail" ; do
+    if [ "$OS" = "windows" ]; then
+      binexe="${binexe}.exe"
+    fi
+    install "${srcdir}/${binexe}" "${BINDIR}/"
+    log_info "installed ${BINDIR}/${binexe}"
+  done
+  rm -rf "${tmpdir}"
+}
+is_supported_platform() {
+  platform=$1
+  found=1
+  case "$platform" in
+    darwin/amd64) found=0 ;;
+    linux/amd64) found=0 ;;
+  esac
+  return $found
+}
+check_platform() {
+  if is_supported_platform "$PLATFORM"; then
+    # optional logging goes here
+    true
+  else
+    log_crit "platform $PLATFORM is not supported.  Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
+    exit 1
+  fi
+}
+tag_to_version() {
+  if [ -z "${TAG}" ]; then
+    log_info "checking GitHub for latest tag"
+  else
+    log_info "checking GitHub for tag '${TAG}'"
+  fi
+  REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true
+  if test -z "$REALTAG"; then
+    log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details"
+    exit 1
+  fi
+  # if version starts with 'v', remove it
+  TAG="$REALTAG"
+  VERSION=${TAG#v}
+}
+adjust_format() {
+  # change format (tar.gz or zip) based on OS
+  true
+}
+adjust_os() {
+  # adjust archive name based on OS
+  true
+}
+adjust_arch() {
+  # adjust archive name based on ARCH
+  true
+}
+
+cat /dev/null <<EOF
+------------------------------------------------------------------------
+https://github.com/client9/shlib - portable posix shell functions
+Public domain - http://unlicense.org
+https://github.com/client9/shlib/blob/master/LICENSE.md
+but credit (and pull requests) appreciated.
+------------------------------------------------------------------------
+EOF
+is_command() {
+  command -v "$1" >/dev/null
+}
+echoerr() {
+  echo "$@" 1>&2
+}
+log_prefix() {
+  echo "$0"
+}
+_logp=6
+log_set_priority() {
+  _logp="$1"
+}
+log_priority() {
+  if test -z "$1"; then
+    echo "$_logp"
+    return
+  fi
+  [ "$1" -le "$_logp" ]
+}
+log_tag() {
+  case $1 in
+    0) echo "emerg" ;;
+    1) echo "alert" ;;
+    2) echo "crit" ;;
+    3) echo "err" ;;
+    4) echo "warning" ;;
+    5) echo "notice" ;;
+    6) echo "info" ;;
+    7) echo "debug" ;;
+    *) echo "$1" ;;
+  esac
+}
+log_debug() {
+  log_priority 7 || return 0
+  echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
+}
+log_info() {
+  log_priority 6 || return 0
+  echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
+}
+log_err() {
+  log_priority 3 || return 0
+  echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
+}
+log_crit() {
+  log_priority 2 || return 0
+  echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
+}
+uname_os() {
+  os=$(uname -s | tr '[:upper:]' '[:lower:]')
+  case "$os" in
+    msys_nt) os="windows" ;;
+  esac
+  echo "$os"
+}
+uname_arch() {
+  arch=$(uname -m)
+  case $arch in
+    x86_64) arch="amd64" ;;
+    x86) arch="386" ;;
+    i686) arch="386" ;;
+    i386) arch="386" ;;
+    aarch64) arch="arm64" ;;
+    armv5*) arch="armv5" ;;
+    armv6*) arch="armv6" ;;
+    armv7*) arch="armv7" ;;
+  esac
+  echo ${arch}
+}
+uname_os_check() {
+  os=$(uname_os)
+  case "$os" in
+    darwin) return 0 ;;
+    dragonfly) return 0 ;;
+    freebsd) return 0 ;;
+    linux) return 0 ;;
+    android) return 0 ;;
+    nacl) return 0 ;;
+    netbsd) return 0 ;;
+    openbsd) return 0 ;;
+    plan9) return 0 ;;
+    solaris) return 0 ;;
+    windows) return 0 ;;
+  esac
+  log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
+  return 1
+}
+uname_arch_check() {
+  arch=$(uname_arch)
+  case "$arch" in
+    386) return 0 ;;
+    amd64) return 0 ;;
+    arm64) return 0 ;;
+    armv5) return 0 ;;
+    armv6) return 0 ;;
+    armv7) return 0 ;;
+    ppc64) return 0 ;;
+    ppc64le) return 0 ;;
+    mips) return 0 ;;
+    mipsle) return 0 ;;
+    mips64) return 0 ;;
+    mips64le) return 0 ;;
+    s390x) return 0 ;;
+    amd64p32) return 0 ;;
+  esac
+  log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value.  Please file bug report at https://github.com/client9/shlib"
+  return 1
+}
+untar() {
+  tarball=$1
+  case "${tarball}" in
+    *.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
+    *.tar) tar -xf "${tarball}" ;;
+    *.zip) unzip "${tarball}" ;;
+    *)
+      log_err "untar unknown archive format for ${tarball}"
+      return 1
+      ;;
+  esac
+}
+http_download_curl() {
+  local_file=$1
+  source_url=$2
+  header=$3
+  if [ -z "$header" ]; then
+    code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
+  else
+    code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
+  fi
+  if [ "$code" != "200" ]; then
+    log_debug "http_download_curl received HTTP status $code"
+    return 1
+  fi
+  return 0
+}
+http_download_wget() {
+  local_file=$1
+  source_url=$2
+  header=$3
+  if [ -z "$header" ]; then
+    wget -q -O "$local_file" "$source_url"
+  else
+    wget -q --header "$header" -O "$local_file" "$source_url"
+  fi
+}
+http_download() {
+  log_debug "http_download $2"
+  if is_command curl; then
+    http_download_curl "$@"
+    return
+  elif is_command wget; then
+    http_download_wget "$@"
+    return
+  fi
+  log_crit "http_download unable to find wget or curl"
+  return 1
+}
+http_copy() {
+  tmp=$(mktemp)
+  http_download "${tmp}" "$1" "$2" || return 1
+  body=$(cat "$tmp")
+  rm -f "${tmp}"
+  echo "$body"
+}
+github_release() {
+  owner_repo=$1
+  version=$2
+  test -z "$version" && version="latest"
+  giturl="https://github.com/${owner_repo}/releases/${version}"
+  json=$(http_copy "$giturl" "Accept:application/json")
+  test -z "$json" && return 1
+  version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
+  test -z "$version" && return 1
+  echo "$version"
+}
+hash_sha256() {
+  TARGET=${1:-/dev/stdin}
+  if is_command gsha256sum; then
+    hash=$(gsha256sum "$TARGET") || return 1
+    echo "$hash" | cut -d ' ' -f 1
+  elif is_command sha256sum; then
+    hash=$(sha256sum "$TARGET") || return 1
+    echo "$hash" | cut -d ' ' -f 1
+  elif is_command shasum; then
+    hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
+    echo "$hash" | cut -d ' ' -f 1
+  elif is_command openssl; then
+    hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
+    echo "$hash" | cut -d ' ' -f a
+  else
+    log_crit "hash_sha256 unable to find command to compute sha-256 hash"
+    return 1
+  fi
+}
+hash_sha256_verify() {
+  TARGET=$1
+  checksums=$2
+  if [ -z "$checksums" ]; then
+    log_err "hash_sha256_verify checksum file not specified in arg2"
+    return 1
+  fi
+  BASENAME=${TARGET##*/}
+  want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
+  if [ -z "$want" ]; then
+    log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
+    return 1
+  fi
+  got=$(hash_sha256 "$TARGET")
+  if [ "$want" != "$got" ]; then
+    log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
+    return 1
+  fi
+}
+cat /dev/null <<EOF
+------------------------------------------------------------------------
+End of functions from https://github.com/client9/shlib
+------------------------------------------------------------------------
+EOF
+
+PROJECT_NAME="kail"
+OWNER=boz
+REPO="kail"
+# shellcheck disable=SC2034
+BINARY=kail
+FORMAT=tar.gz
+OS=$(uname_os)
+ARCH=$(uname_arch)
+PREFIX="$OWNER/$REPO"
+
+# use in logging routines
+log_prefix() {
+	echo "$PREFIX"
+}
+PLATFORM="${OS}/${ARCH}"
+GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download
+
+uname_os_check "$OS"
+uname_arch_check "$ARCH"
+
+parse_args "$@"
+
+check_platform
+
+tag_to_version
+
+adjust_format
+
+adjust_os
+
+adjust_arch
+
+log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}"
+
+# ---------------------------------------------------------
+# [JOEY] - as of v0.16.1, download name contains an embedded 'v'
+# ---------------------------------------------------------
+# NAME=${PROJECT_NAME}_${VERSION}_${OS}_${ARCH}
+NAME=${PROJECT_NAME}_v${VERSION}_${OS}_${ARCH}
+
+TARBALL=${NAME}.${FORMAT}
+TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
+CHECKSUM=checksums.txt
+CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM}
+
+execute
diff --git a/makefiles/commands/kail.mk b/makefiles/commands/kail/include.mk
similarity index 100%
rename from makefiles/commands/kail.mk
rename to makefiles/commands/kail/include.mk
diff --git a/makefiles/consts.mk b/makefiles/consts.mk
index 8961b3a..f1f717f 100644
--- a/makefiles/consts.mk
+++ b/makefiles/consts.mk
@@ -34,8 +34,11 @@
 HIDE           ?= @
 
 env-clean      ?= /usr/bin/env --ignore-environment
-xargs-n1       := xargs -0 -t -n1 --no-run-if-empty
-xargs-n1-clean := $(env-clean) $(xargs-n1)
+
+xargs-cmd       := xargs -0 -t --no-run-if-empty
+xargs-n1        := $(xargs-cmd) -n1
+xargs-n1-clean  := $(env-clean) $(xargs-n1)
+xargs-cmd-clean := $(env-clean) $(xargs-cmd)
 
 ## -----------------------------------------------------------------------
 ## Intent: NOP command for targets whose dependencies do all heavy lifting
diff --git a/makefiles/docker/config/voltha-lib-go.mk b/makefiles/docker/config/voltha-lib-go.mk
new file mode 100644
index 0000000..4379237
--- /dev/null
+++ b/makefiles/docker/config/voltha-lib-go.mk
@@ -0,0 +1,28 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.d
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## repo:voltha-lib-go values for docker use
+
+go-cobertura-docker-mount := /app/src/github.com/opencord/voltha-lib-go/v7#   #
+protoc-sh-docker-mount    := /go/src/github.com/opencord/voltha-protos/v5#    #
+# voltha-protos-v5          := /go/src/github.com/opencord/voltha-protos/v5
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/docker/config/voltha-openolt-adapter.mk b/makefiles/docker/config/voltha-openolt-adapter.mk
new file mode 100644
index 0000000..4e56be0
--- /dev/null
+++ b/makefiles/docker/config/voltha-openolt-adapter.mk
@@ -0,0 +1,25 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.d
+# -----------------------------------------------------------------------
+
+## repo:voltha-openolt-adapter values for docker use
+
+go-cobertura-docker-mount := /app/src/github.com/opencord/voltha-openolt-adapter
+protoc-sh-docker-mount    := /go/src/github.com/opencord/voltha-protos/v5
+# voltha-protos-v5          := /go/src/github.com/opencord/voltha-protos/v5
+
+# [EOF]
+
diff --git a/makefiles/docker/include.mk b/makefiles/docker/include.mk
index 6562631..cd02827 100644
--- a/makefiles/docker/include.mk
+++ b/makefiles/docker/include.mk
@@ -17,8 +17,20 @@
 
 $(if $(DEBUG),$(warning ENTER))
 
+# Per-repository
+include $(ONF_MAKEDIR)/docker/config/$(--repo-name--).mk
+
+# ------------------- ##
+# ---]  GLOBALS  [--- ##
+# ------------------- ##
 VOLTHA_TOOLS_VERSION ?= 2.4.0
 
+# ---------------------------------
+# Induce error for misconfiguration
+# ---------------------------------
+go-cobertura-docker-mount ?= $(error go-cobertura-docker-mount= is required)
+protoc-sh-docker-mount    ?= $(error protoc-sh-docker-mount= is required)
+
 # ---------------------------
 # Macros: command refactoring
 # ---------------------------
@@ -34,8 +46,6 @@
 is-stdin       = $(shell test -t 0 && { echo '--interactive'; })
 is-stdin       += --tty
 
-voltha-protos-v5 ?= /go/src/github.com/opencord/voltha-protos/v5
-
 # Docker volume mounts: container:/app/release <=> localhost:{pwd}/release
 vee-golang     = -v gocache-${VOLTHA_TOOLS_VERSION}:/go/pkg
 vee-citools    = voltha/voltha-ci-tools:${VOLTHA_TOOLS_VERSION}
@@ -45,43 +55,105 @@
 # ---------------
 docker-go-stem = $(docker-run-app) -v gocache:/.cache $(vee-golang) $(vee-citools)-golang
 
-# Usage: GO := $(call get-docker-go,./my.env.temp)
-get-docker-go = $(docker-go-stem) go
-GO            ?= $(call get-docker-go)
+# -----------------------------------------------------------------------
+# Usage: GO := $(call get-cmd-docker-go)
+# -----------------------------------------------------------------------
+get-cmd-docker-go = $(docker-go-stem) go
+GO                ?= $(call get-cmd-docker-go)
 
+# -----------------------------------------------------------------------
 # Usage: GO_SH := $(call get-docker-go-sh,./my.env.temp)
-get-docker-go-sh = $(docker-go-stem) $(if $(1),--env-file $(1)) sh -c
-GO_SH            ?= $(call get-docker-go-sh,./my.env.temp)
+#    - populate my.env.temp with shell content to pass in
+# -----------------------------------------------------------------------
+get-cmd-docker-go-sh = $(docker-go-stem) $(if $(1),--env-file $(1)) sh -c
+GO_SH                ?= $(call get-cmd-docker-go-sh,./my.env.temp)
 
-# Usage: PROTOC := $(call get-docker-protoc)
-get-docker-protoc = $(docker-run-app) $(vee-citools)-protoc protoc
-PROTOC            ?= $(call get-docker-protoc)
+# -----------------------------------------------------------------------
+# Usage: PROTOC := $(call get-cmd-docker-protoc)
+# -----------------------------------------------------------------------
+get-cmd-docker-protoc = $(docker-run-app) $(vee-citools)-protoc protoc
+PROTOC                ?= $(call get-cmd-docker-protoc)
+
+# -----------------------------------------------------------------------
+# Usage: PROTOC_SH := $(call get-cmd-docker-protoc-sh)
+# -----------------------------------------------------------------------
+get-cmd-docker-protoc-sh =\
+  $(strip \
+	$(docker-run-is) \
+	  $(if $(protc-sh-docker-mount),               \
+		-v ${CURDIR}:$(protoc-sh-docker-mount) \
+		--workdir=$(protoc-sh-docker-mount)    \
+	  ) \
+	  $(vee-citools)-protoc \
+	  sh -c \
+  )
+PROTOC_SH ?= $(call get-cmd-docker-protoc-sh)
 
 # get-docker-protoc-sh = $(strip )
-PROTOC_SH = $(docker-run-is)
-ifdef voltha-protos-v5
-   PROTOC_SH += -v ${CURDIR}:$(voltha-protos-v5)
-   PROTOC_SH += --workdir=$(voltha-protos-v5)
-endif
-PROTOC_SH += $(vee-citools)-protoc sh -c
+#PROTOC_SH = $(docker-run-is)
+#ifdef protc-sh-docker-mount
+#   PROTOC_SH += -v ${CURDIR}:$(protoc-sh-docker-mount)
+#   PROTOC_SH += --workdir=$(protoc-sh-docker-mount)
+#endif # protoc-sh-docker-mount
+#PROTOC_SH += $(vee-citools)-protoc sh -c
 
 # Usage: GO_JUNIT_REPORT := $(call get-docker-go-junit-repo)
 # get-docker-go-junit-repo = $(docker-run-app) $(vee-citools)-go-junit-report go-junit-report
 # GO_JUNIT_REPORT   ?= $(call get-docker-go-junit-repo)
 
-# Usage: GOCOVER_COBERTURA := $(call get-docker-gocover-cobertura)
+# -----------------------------------------------------------------------
 # get-docker-gocover-cobertura = $(docker-run-app)/src/github.com/opencord/voltha-openolt-adapter $(vee-citools)-gocover-cobertura gocover-cobertura
 # GOCOVER_COBERTURA ?= $(call get-docker-gocover-cobertura)
 
-GO_JUNIT_REPORT   = $(docker-run) -v ${CURDIR}:/app -i $(vee-citools)-go-junit-report go-junit-report
-GOCOVER_COBERTURA = $(docker-run) -v ${CURDIR}:/app/src/github.com/opencord/voltha-openolt-adapter -i $(vee-citools)-gocover-cobertura gocover-cobertura
+## -----------------------------------------------------------------------
+## Coverage report: junit
+## -----------------------------------------------------------------------
+## Usage: GO_JUNIT_REPORT ?= $(call get-go-junit-report-cmd)
+## -----------------------------------------------------------------------
+get-go-junit-report-cmd =\
+  $(strip \
+	$(docker-run) \
+	  -v ${CURDIR}:/app \
+	  -i $(vee-citools)-go-junit-report go-junit-report \
+  )
+GO_JUNIT_REPORT ?= $(call get-go-junit-report-cmd)
 
+## -----------------------------------------------------------------------
+## Coverage report: cobertura
+## -----------------------------------------------------------------------
+## Usage: GOCOVER_COBERTURA ?= $(call get-docker-gocover-cobertura-cmd)
+## -----------------------------------------------------------------------
+get-docker-go-cobertura-cmd =\
+  $(strip \
+	$(docker-run)\
+	  -v ${CURDIR}:$(go-cobertura-docker-mount)\
+	  -i $(vee-citools)-gocover-cobertura gocover-cobertura\
+  )
+GOCOVER_COBERTURA ?= $(call get-docker-go-cobertura-cmd)
 
-get-golangci-lint = $(docker-run-app) -v gocache:/.cache $(vee-golang) $(vee-citools)-golangci-lint golangci-lint
-GOLANGCI_LINT     ?= $(call get-golangci-lint)
+## -----------------------------------------------------------------------
+##
+## -----------------------------------------------------------------------
+get-cmd-docker-golangci-lint =\
+  $(strip \
+	$(docker-run-app) \
+	  -v gocache:/.cache \
+	  $(vee-golang)\
+	  $(vee-citools)-golangci-lint\
+	  golangci-lint\
+  )
+GOLANGCI_LINT ?= $(call get-cmd-docker-golangci-lint)
 
-get-docker-hadolint = $(docker-run-app) $(vee-citools)-hadolint hadolint
-HADOLINT          ?= $(call get-docker-hadolint)
+## -----------------------------------------------------------------------
+##
+## -----------------------------------------------------------------------
+get-docker-hadolint =\
+  $(strip \
+	$(docker-run-app)         \
+	  $(vee-citools)-hadolint \
+	  hadolint                \
+  )
+HADOLINT ?= $(call get-docker-hadolint)
 
 $(if $(DEBUG),$(warning LEAVE))
 
diff --git a/makefiles/etc/features.mk b/makefiles/etc/features.mk
new file mode 100644
index 0000000..a48b42c
--- /dev/null
+++ b/makefiles/etc/features.mk
@@ -0,0 +1,48 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation
+#
+# 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.
+#
+# SPDX-FileCopyrightText: 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+# Usage:
+#
+# mytarget:
+#     $(call banner-enter,target $@)
+#     @echo "Hello World"
+#     $(call banner-leave,target $@)
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+target-banner = ** ---------------------------------------------------------------------------
+
+## -----------------------------------------------------------------------
+## Intent: Return a command line able to display a banner hilighting
+##         make target processing within a logfile.
+## -----------------------------------------------------------------------
+banner-enter=\
+    @echo -e \
+    "\n"\
+    "$(target-banner)\n"\
+    "** $(MAKE) ENTER: $(1)\n"\
+    "$(target-banner)"\
+
+banner-leave=\
+    @echo -e "** $(MAKE) LEAVE: $(1)"
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/git-submodules.mk b/makefiles/git-submodules.mk
new file mode 100644
index 0000000..373dc23
--- /dev/null
+++ b/makefiles/git-submodules.mk
@@ -0,0 +1,80 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+GIT ?= git
+
+## -----------------------------------------------------------------------
+## Intent: Checkout submodules required by ci-management
+## -----------------------------------------------------------------------
+submodule-repos := $(null)
+submodule-repos += global-jjb
+submodule-repos += lf-ansible
+submodule-repos += packer
+
+submodule-deps := $(null)
+submodule-deps += submodules#     # named pseudo target
+submodule-deps += $(submodule-repos)
+
+.PHONY: $(submodule-deps)
+$(submodule-deps):
+	@echo
+	@echo "Checkout dependent submodules"
+	$(GIT) submodule init
+	$(GIT) submodule update
+
+# Abstraction: named target for submodule checkout
+checkout-ci-management-sub-modules: $(submodule-repos)
+
+## -----------------------------------------------------------------------
+## Intent: Revert sandbox to a pristine state.
+## -----------------------------------------------------------------------
+sterile ::
+	$(RM) -r $(submodule-repos)
+
+        # FIXME:
+        #   o restore hierarchy to avoid git status 'deleted:'
+        #   o remove: externals should not be under revision control
+	$(GIT) co $(submodule-repos)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help ::
+	@echo
+	@echo '[GIT-SUBMODULES: docs]'
+	@echo '  reload              Setup to auto-reload sphinx doc changes in browser'
+	@echo
+	@echo '[GIT-SUBMODULES: deps]'
+	@echo '  submodules          Checkout dependent git submodules'
+  ifdef VERBOSE
+	@echo '  global-jjb          Checkout ci-management submodule global-jjb'
+	@echo '  lf-ansible          Checkout ci-management submodule lf-ansible'
+	@echo '  packer              Checkout ci-management submodule packer'
+  endif
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+todo ::
+	@echo "Generalize logc, update to depend on .git/ rather than named targets."
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/git/byrepo/ci-management.mk b/makefiles/git/byrepo/ci-management.mk
new file mode 100644
index 0000000..373dc23
--- /dev/null
+++ b/makefiles/git/byrepo/ci-management.mk
@@ -0,0 +1,80 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+GIT ?= git
+
+## -----------------------------------------------------------------------
+## Intent: Checkout submodules required by ci-management
+## -----------------------------------------------------------------------
+submodule-repos := $(null)
+submodule-repos += global-jjb
+submodule-repos += lf-ansible
+submodule-repos += packer
+
+submodule-deps := $(null)
+submodule-deps += submodules#     # named pseudo target
+submodule-deps += $(submodule-repos)
+
+.PHONY: $(submodule-deps)
+$(submodule-deps):
+	@echo
+	@echo "Checkout dependent submodules"
+	$(GIT) submodule init
+	$(GIT) submodule update
+
+# Abstraction: named target for submodule checkout
+checkout-ci-management-sub-modules: $(submodule-repos)
+
+## -----------------------------------------------------------------------
+## Intent: Revert sandbox to a pristine state.
+## -----------------------------------------------------------------------
+sterile ::
+	$(RM) -r $(submodule-repos)
+
+        # FIXME:
+        #   o restore hierarchy to avoid git status 'deleted:'
+        #   o remove: externals should not be under revision control
+	$(GIT) co $(submodule-repos)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help ::
+	@echo
+	@echo '[GIT-SUBMODULES: docs]'
+	@echo '  reload              Setup to auto-reload sphinx doc changes in browser'
+	@echo
+	@echo '[GIT-SUBMODULES: deps]'
+	@echo '  submodules          Checkout dependent git submodules'
+  ifdef VERBOSE
+	@echo '  global-jjb          Checkout ci-management submodule global-jjb'
+	@echo '  lf-ansible          Checkout ci-management submodule lf-ansible'
+	@echo '  packer              Checkout ci-management submodule packer'
+  endif
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+todo ::
+	@echo "Generalize logc, update to depend on .git/ rather than named targets."
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/git/include.mk b/makefiles/git/include.mk
index 9d2558c..7b51532 100644
--- a/makefiles/git/include.mk
+++ b/makefiles/git/include.mk
@@ -30,8 +30,8 @@
 -include $(ONF_MAKEDIR)/git/$(--repo-name--).mk
 
 ifdef USE-ONF-GIT-MK
-  # Dynamic loading when targets are requested by name
-  include $(ONF_MAKEDIR)/git/submodules.mk
+    # Dynamic loading when targets are requested by name
+    include $(ONF_MAKEDIR)/git/submodules.mk
 endif
 
 # [EOF]
diff --git a/makefiles/include.mk b/makefiles/include.mk
index df50ca4..97ea39a 100644
--- a/makefiles/include.mk
+++ b/makefiles/include.mk
@@ -18,7 +18,7 @@
 # SPDX-License-Identifier: Apache-2.0
 # -----------------------------------------------------------------------
 # https://gerrit.opencord.org/plugins/gitiles/onf-make
-# ONF.makefile.version = 1.0
+# ONF.makefiles.include.version = 1.1
 # -----------------------------------------------------------------------
 
 ifndef mk-include--onf-make # single-include guard macro
@@ -42,6 +42,7 @@
 include $(ONF_MAKEDIR)/commands/include.mk   # Tools and local installers
 
 include $(ONF_MAKEDIR)/virtualenv.mk#        # lint-{jjb,python} depends on venv
+# include $(ONF_MAKEDIR)/patches/include.mk#   # Patch when python 3.10+ in use
 include $(ONF_MAKEDIR)/lint/include.mk
 
 include $(ONF_MAKEDIR)/gerrit/include.mk
diff --git a/makefiles/lint/doc8/include.mk b/makefiles/lint/doc8/include.mk
index 56b5e49..4764fa2 100644
--- a/makefiles/lint/doc8/include.mk
+++ b/makefiles/lint/doc8/include.mk
@@ -41,18 +41,15 @@
 lint-doc8-modified : lint-doc8
 
 ## -----------------------------------------------------------------------
-## https://github.com/pycqa/doc8
-##   create .config/doc8.ini
 ## -----------------------------------------------------------------------
 lint-doc8-excl := $(foreach dir,$(onf-excl-dirs),--ignore-path "$(dir)")
-lint-doc8-excl += --ignore-path $(venv-name)
 lint-doc8: lint-doc8-cmd-version
 
 	$(call banner-enter,Target $@)
 	$(activate) && doc8 --version
 	@echo
 	$(activate) && doc8 $(lint-doc8-excl)
-	$(call banner-leave,Target $@)
+	$(call banner-enter,Target $@)
 
 ## -----------------------------------------------------------------------
 ## Intent: Display command usage
diff --git a/makefiles/python/include.mk b/makefiles/python/include.mk
index f46aea0..70b5ca1 100644
--- a/makefiles/python/include.mk
+++ b/makefiles/python/include.mk
@@ -1,6 +1,6 @@
 # -*- makefile -*-
 # -----------------------------------------------------------------------
-# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# Copyright 2022 Open Networking Foundation (ONF) and the ONF Contributors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# SPDX-FileCopyrightText: 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
 # SPDX-License-Identifier: Apache-2.0
 # -----------------------------------------------------------------------
 
diff --git a/makefiles/python/test/include.mk b/makefiles/python/test/include.mk
index 026fe68..12afc3e 100644
--- a/makefiles/python/test/include.mk
+++ b/makefiles/python/test/include.mk
@@ -1,6 +1,6 @@
 # -*- makefile -*-
 # -----------------------------------------------------------------------
-# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# Copyright 2022 Open Networking Foundation (ONF) and the ONF Contributors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# SPDX-FileCopyrightText: 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
 # SPDX-License-Identifier: Apache-2.0
 # -----------------------------------------------------------------------
 
diff --git a/makefiles/release/help.mk b/makefiles/release/help.mk
new file mode 100644
index 0000000..72af6be
--- /dev/null
+++ b/makefiles/release/help.mk
@@ -0,0 +1,38 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+## ---------------------------------------------------------------------------
+## Intent: Display supported targets
+## ---------------------------------------------------------------------------
+help-voltha-release :
+	@echo
+	@echo '[RELEASE] - Create branch driven testing pipelines'
+	@echo '  create-jobs-release'
+	@echo '  create-jobs-release-bat            Build and test jobs'
+	@echo '  create-jobs-release-e2e            End-to-End testing'
+	@echo '  create-jobs-release-certification  Certification testing'
+	@echo '  create-jobs-release-nightly        Nightly testing'
+	@echo '  create-jobs-release-units          Unit testing'
+
+	@echo '  sterile-create-jobs-release        Purge pipeline job content'
+
+help ::
+	@echo '  help-voltha-release Display voltha release targets'
+
+# [EOF]
diff --git a/makefiles/release/include.mk b/makefiles/release/include.mk
new file mode 100644
index 0000000..8891df1
--- /dev/null
+++ b/makefiles/release/include.mk
@@ -0,0 +1,36 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+include $(ONF_MAKEDIR)/release/help.mk
+include $(ONF_MAKEDIR)/release/required.mk
+
+ifdef USE_VOLTHA_RELEASE_MK
+  # Dynamic loading when targets are requested by name
+  include $(ONF_MAKEDIR)/release/targets.mk
+endif
+
+# [EOF]
+
+
diff --git a/makefiles/release/required.mk b/makefiles/release/required.mk
new file mode 100644
index 0000000..620b827
--- /dev/null
+++ b/makefiles/release/required.mk
@@ -0,0 +1,36 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Conditionally load when named targets are requested.
+#   var ?= $(error ...) definitions are fatal to "make help" and others
+# -----------------------------------------------------------------------
+
+voltha-release-mk-targets := $(NULL)
+voltha-release-mk-targets += create-jobs-release
+voltha-release-mk-targets += create-jobs-release-certification
+voltha-release-mk-targets += create-jobs-release-nightly
+voltha-release-mk-targets += create-jobs-release-units
+voltha-release-mk-targets += sterile-create-jobs-release
+
+# -----------------------------------------------------------------------
+# Define a flag to only load release targets when mentioned by name
+# Makefile can also explicitly define the flag to force always loading.
+# -----------------------------------------------------------------------
+$(foreach tgt,$(voltha-release-mk-targets),\
+  $(if $(findstring $(tgt),$(MAKECMDGOALS)),$(eval USE_VOLTHA_RELEASE_MK := true))\
+)
+
+# [EOF]
diff --git a/makefiles/release/targets.mk b/makefiles/release/targets.mk
new file mode 100644
index 0000000..b201998
--- /dev/null
+++ b/makefiles/release/targets.mk
@@ -0,0 +1,86 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+
+# TODO: Library function  $(call mk-path,makefiles/release/targets.mk)
+release-mk-top := $(abspath $(lastword $(MAKEFILE_LIST)))
+release-mk-top := $(subst /makefiles/release/targets.mk,$(null),$(release-mk-top))
+
+GIT	?= /usr/bin/env git
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+include $(ONF_MAKEDIR)/release/voltha-versions.mk
+include $(ONF_MAKEDIR)/release/targets/voltha-certification.mk
+include $(ONF_MAKEDIR)/release/targets/voltha-e2e.mk
+include $(ONF_MAKEDIR)/release/targets/voltha-nightly-jobs.mk
+
+# last-release  := voltha-2.11
+last-release := $(voltha-release-last)
+
+
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+all: help
+
+## ---------------------------------------------------------------------------
+## Intent: Build these deps to create a new branch/release area
+## ---------------------------------------------------------------------------
+create-jobs-release += create-jobs-release-bat
+create-jobs-release += create-jobs-release-certification
+create-jobs-release += create-jobs-release-nightly
+create-jobs-release += create-jobs-release-units
+create-jobs-release += create-jobs-release-e2e
+
+create-jobs-release : $(create-jobs-release)
+
+	@echo
+	$(GIT) status
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven pipeline test jobs.
+## ---------------------------------------------------------------------------
+units-yaml := $(release-mk-top)/jjb/pipeline/voltha/$(voltha-version)
+units-root := $(subst /$(voltha-version),$(null),$(units-yaml))
+create-jobs-release-units : $(units-yaml)
+$(units-yaml):
+
+	@echo
+	@echo "** Create branch driven pipeline: unit tests"
+	$(HIDE)mkdir -vp $@
+	rsync -r --checksum $(units-root)/master/. $@/.
+	$(HIDE)/bin/ls -l $(units-root)
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+## ---------------------------------------------------------------------------
+sterile-create-jobs-release := $(addprefix sterile-,$(create-jobs-release))
+sterile-create-jobs-release : $(sterile-create-jobs-release)
+	$(RM) -r $(units-yaml)
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/release/targets/voltha-certification.mk b/makefiles/release/targets/voltha-certification.mk
new file mode 100644
index 0000000..55e4f1a
--- /dev/null
+++ b/makefiles/release/targets/voltha-certification.mk
@@ -0,0 +1,56 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+##   o Clone config for the last nightly release
+##   o In-place edit to the latest version.
+## ---------------------------------------------------------------------------
+## NOTE: WIP - nightly jobs have not yet migrated from the mega job config file
+## ---------------------------------------------------------------------------
+certification-dir  := $(release-mk-top)/jjb/voltha-test/voltha-certification
+certification-yaml := $(certification-dir)/$(voltha-version).yaml
+certification-tmpl := $(certification-dir)/$(voltha-release-last).yaml
+
+create-jobs-release-certification : $(certification-yaml)
+$(certification-yaml) : $(certification-tmpl)
+
+	@echo
+	@echo "** Create branch driven pipeline: nightly tests"
+	sed -e 's/$(last-release)/$(voltha-version)/g' $< > $@
+	$(HIDE)/bin/ls -l $(dir $@)
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+## ---------------------------------------------------------------------------
+$(certification-tmpl):
+	@echo "ERROR: Yaml template branch does not exist: $@"
+	@echo 1
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+## ---------------------------------------------------------------------------
+sterile-create-jobs-release-certification :
+	$(RM) $(certification-yaml)
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/release/targets/voltha-e2e.mk b/makefiles/release/targets/voltha-e2e.mk
new file mode 100644
index 0000000..40e7c5d
--- /dev/null
+++ b/makefiles/release/targets/voltha-e2e.mk
@@ -0,0 +1,56 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+##   o Clone config for the last nightly release
+##   o In-place edit to the latest version.
+## ---------------------------------------------------------------------------
+## NOTE: WIP - nightly jobs have not yet migrated from the mega job config file
+## ---------------------------------------------------------------------------
+voltha-e2e-dir  := $(release-mk-top)/jjb/voltha-e2e
+voltha-e2e-yaml := $(voltha-e2e-dir)/$(voltha-version).yaml
+voltha-e2e-tmpl := $(voltha-e2e-dir)/$(voltha-release-last).yaml
+
+create-jobs-release-e2e : $(voltha-e2e-yaml)
+$(voltha-e2e-yaml) : $(voltha-e2e-tmpl)
+
+	@echo
+	@echo "** Create branch driven pipeline: nightly tests"
+	sed -e 's/$(last-release)/$(voltha-version)/g' $< > $@
+	$(HIDE)/bin/ls -l $(dir $@)
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+## ---------------------------------------------------------------------------
+$(voltha-e2e-tmpl):
+	@echo "ERROR: Yaml template branch does not exist: $@"
+	@echo 1
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+## ---------------------------------------------------------------------------
+sterile-create-jobs-release-e2e :
+	$(RM) $(voltha-e2e-yaml)
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/release/targets/voltha-nightly-jobs.mk b/makefiles/release/targets/voltha-nightly-jobs.mk
new file mode 100644
index 0000000..20e37de
--- /dev/null
+++ b/makefiles/release/targets/voltha-nightly-jobs.mk
@@ -0,0 +1,54 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+##   o Clone config for the last nightly release
+##   o In-place edit to the latest version.
+## ---------------------------------------------------------------------------
+## NOTE: WIP - nightly jobs have not yet migrated from the mega job config file
+## ---------------------------------------------------------------------------
+voltha-nightly-dir  := $(release-mk-top)/jjb/voltha-test/voltha-nightly-jobs
+voltha-nightly-yaml := $(voltha-nightly-dir)/$(voltha-version).yaml
+voltha-nightly-tmpl := $(voltha-nightly-dir)/$(voltha-release-last).yaml
+
+create-jobs-release-nightly : $(voltha-nightly-yaml)
+$(voltha-nightly-yaml) : $(voltha-nightly-tmpl)
+
+	@echo
+	@echo "** Create branch driven pipeline: nightly tests"
+	sed -e 's/$(last-release)/$(voltha-version)/g' $< > $@
+	$(HIDE)/bin/ls -l $(dir $@)
+
+## ---------------------------------------------------------------------------
+## Intent: Create branch driven nightly test jobs.
+## ---------------------------------------------------------------------------
+$(voltha-nightly-tmpl):
+	@echo "ERROR: Yaml template branch does not exist: $@"
+	@echo 1
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/release/voltha-versions.mk b/makefiles/release/voltha-versions.mk
new file mode 100644
index 0000000..a6ab7b6
--- /dev/null
+++ b/makefiles/release/voltha-versions.mk
@@ -0,0 +1,44 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+voltha-versions += master
+voltha-versions += voltha-2.12
+voltha-versions += voltha-2.11
+voltha-versions += voltha-2.8
+voltha-versions += playground
+
+# VOLTHA: release
+#   active : $(words 0,$(voltha-versions))
+#     next : $(words 1,$(voltha-versions))
+#     last : $(words 2,$(voltha-versions))
+
+# fatal to make help (param is null)
+voltha-version ?= $(error $(MAKE) voltha-verison=voltha-x.yy is required)\
+
+voltha-release-this := $(word 1,$(voltha-versions)) 
+voltha-release-last := $(word 2,$(voltha-versions))
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/targets/sterile.mk b/makefiles/targets/sterile.mk
index c661f53..f5922ee 100644
--- a/makefiles/targets/sterile.mk
+++ b/makefiles/targets/sterile.mk
@@ -31,6 +31,7 @@
 ## -----------------------------------------------------------------------
 .PHONY: sterile
 sterile :: clean
+	$(if $(sterile-dirs),$(RM) -r $(sterile-dirs))
 
 ## -----------------------------------------------------------------------
 ## -----------------------------------------------------------------------
diff --git a/makefiles/targets/test.mk b/makefiles/targets/test.mk
new file mode 100644
index 0000000..d70fa4a
--- /dev/null
+++ b/makefiles/targets/test.mk
@@ -0,0 +1,41 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+.PHONY: test
+test: $(venv-activate-script) $(JOBCONFIG_DIR)
+	$(activate) \
+	&& pipdeptree \
+	&& jenkins-jobs -l DEBUG test --recursive --config-xml -o "$(JOBCONFIG_DIR)" jjb/ ;
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help-verbose += help-test
+help-test ::
+	@echo
+	@echo '[MAKE: test]'
+	@echo '  test                Perform testing that a jenkins job pull request will invoke'
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/targets/tox.mk b/makefiles/targets/tox.mk
new file mode 100644
index 0000000..9d50962
--- /dev/null
+++ b/makefiles/targets/tox.mk
@@ -0,0 +1,44 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## -----------------------------------------------------------------------
+## Intent: Sanity check incoming JJB config changes.
+##   Todo: Depend on makefiles/lint/jjb.mk :: lint-jjb
+## -----------------------------------------------------------------------
+# lint : lint-jjb
+lint-tox: lint-jjb
+	tox -e py310
+
+sterile ::
+	$(RM) -r .tox#       # $(TOP)/.tox
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help-verbose += help-tox
+help-tox ::
+	@echo
+	@echo '[MAKE: tox]'
+	@echo '  lint-tox            Python unit testing, sanity check incoming JJB changes.'
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/todo.mk b/makefiles/todo.mk
index ab7400d..d8b5e03 100644
--- a/makefiles/todo.mk
+++ b/makefiles/todo.mk
@@ -21,6 +21,7 @@
 $(if $(DEBUG),$(warning ENTER))
 
 todo ::
+	@echo
 	@echo '[TODO]'
 	@echo '  o item 1'
 	@echo '  o item 2'