diff --git a/contrib/herokuish-build.Dockerfile b/contrib/herokuish-build.Dockerfile new file mode 100644 index 000000000..50b5ed002 --- /dev/null +++ b/contrib/herokuish-build.Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:14.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get -y install gcc git build-essential wget ruby-dev ruby1.9.1 lintian rpm help2man man-db +RUN command -v fpm > /dev/null || sudo gem install fpm --no-ri --no-rdoc + +ARG WORKDIR=/go/src/github.com/dokku/dokku + +WORKDIR ${WORKDIR} + +COPY . ${WORKDIR} + +RUN make deb-herokuish rpm-herokuish + +RUN mkdir -p /data \ + && cp /tmp/*.deb /data \ + && cp /tmp/*.rpm /data \ + && ls -lha /data/ diff --git a/contrib/release-herokuish b/contrib/release-herokuish new file mode 100755 index 000000000..e6f4bbe03 --- /dev/null +++ b/contrib/release-herokuish @@ -0,0 +1,156 @@ +#!/usr/bin/env bash +set -eo pipefail +[[ $TRACE ]] && set -x + +readonly ROOT_DIR="$(cd "$(dirname "$(dirname "${BASH_SOURCE[0]}")")" && pwd)" +readonly TMP_WORK_DIR="$(mktemp -d "/tmp/dokku-release.XXXX")" +readonly DOKKU_GIT_REV="$(git rev-parse HEAD)" + +trap 'rm -rf "$TMP_WORK_DIR" > /dev/null' RETURN INT TERM EXIT + +log-info() { + # shellcheck disable=SC2034 + declare desc="Log info formatter" + echo "$*" +} + +log-error() { + # shellcheck disable=SC2034 + declare desc="Log error formatter" + echo "! $*" 1>&2 +} + +log-fail() { + # shellcheck disable=SC2034 + declare desc="Log fail formatter" + log-error "$*" + exit -1 +} + +fn-build-dokku() { + declare desc="Builds dokku packages within a docker container" + + pushd "$ROOT_DIR" >/dev/null + docker build \ + -f "contrib/herokuish-build.Dockerfile" \ + -t herokuish:build . + return "$?" +} + +fn-extract-package() { + declare desc="Extract packages from a docker container to the root directory" + declare PACKAGE_NAME="$1" + + if [[ -z "$PACKAGE_NAME" ]]; then + log-error "Invalid deb file specified" + return 1 + fi + + log-info "(extract-package) writing ${PACKAGE_NAME} to correct path" + docker run --rm --entrypoint cat herokuish:build "/data/${PACKAGE_NAME}" > "${ROOT_DIR}/${PACKAGE_NAME}" + return "$?" +} + +fn-publish-package() { + declare desc="Publishes a package to packagecloud" + declare IS_RELEASE="$1" RELEASE_TYPE="$2" PACKAGE_NAME="$3" + local REPOSITORY=dokku/dokku-betafish DIST=ubuntu + local OS_ID ex EXIT_CODE=0 + + [[ "$IS_RELEASE" == "true" ]] && REPOSITORY=dokku/dokku + [[ "$RELEASE_TYPE" == "rpm" ]] && DIST=el/7 + + if [[ "$DIST" == "ubuntu" ]]; then + OS_IDS=("trusty" "utopic" "vivid" "wily" "xenial" "yakkety" "zesty" "artful" "bionic") + for OS_ID in "${OS_IDS[@]}"; do + log-info "(release-herokuish) pushing ${RELEASE_TYPE} to packagecloud.com/${REPOSITORY}/${DIST}" + package_cloud push "${REPOSITORY}/${DIST}/${OS_ID}" "$PACKAGE_NAME" + ex="$?" + if [[ "$ex" -ne "0" ]]; then + EXIT_CODE="$ex" + fi + done + + DIST=debian + OS_IDS=("wheezy" "jessie" "stretch" "buster") + for OS_ID in "${OS_IDS[@]}"; do + log-info "(release-herokuish) pushing ${RELEASE_TYPE} to packagecloud.com/${REPOSITORY}/${DIST}" + package_cloud push "${REPOSITORY}/${DIST}/${OS_ID}" "$PACKAGE_NAME" + ex="$?" + if [[ "$ex" -ne "0" ]]; then + EXIT_CODE="$ex" + fi + done + else + log-info "(release-herokuish) pushing ${RELEASE_TYPE} to packagecloud.com/${REPOSITORY}/${DIST}" + package_cloud push "${REPOSITORY}/${DIST}" "$PACKAGE_NAME" + EXIT_CODE="$?" + fi + return "$EXIT_CODE" +} + +fn-in-array() { + declare desc="return true if value ($1) is in list (all other arguments)" + + local e + for e in "${@:2}"; do + [[ "$e" == "$1" ]] && return 0 + done + return 1 +} + +fn-is-release() { + declare desc="Checks if a given run is a release run" + declare RELEASE="$1" + local IS_RELEASE=false + if [[ "$RELEASE" == "major" ]] || [[ "$RELEASE" == "minor" ]] || [[ "$RELEASE" == "patch" ]]; then + IS_RELEASE=true + fi + + echo "$IS_RELEASE" +} + +fn-require-bin() { + declare desc="Checks that a binary exists" + declare BINARY="$1" + if ! command -v "$BINARY" &>/dev/null; then + log-fail "Missing ${BINARY}, please install it" + fi +} + +main() { + declare RELEASE="$1" + local NEXT_VERSION + local VALID_RELEASE_LEVELS=("major" "minor" "patch" "betafish") + + if [[ "$RELEASE" == '--trace' ]]; then + shift 1 + RELEASE="$1" + TRACE=1 && set -x + fi + + if [[ -z "$RELEASE" ]]; then + log-fail "Argument 1 must be one of [major, minor, patch, betafish], none given" + fi + + if ! fn-in-array "$RELEASE" "${VALID_RELEASE_LEVELS[@]}"; then + log-fail "Argument 1 must be one of [major, minor, patch, betafish], '${RELEASE}' given" + fi + + fn-require-bin "docker" + fn-require-bin "package_cloud" + [[ -n "$PACKAGECLOUD_API_TOKEN" ]] || log-fail "Missing PACKAGECLOUD_API_TOKEN environment variable" + + NEXT_VERSION="$(grep HEROKUISH_VERSION deb.mk | head -n1 | cut -d'=' -f2 | xargs)" + IS_RELEASE="$(fn-is-release "$RELEASE")" + + fn-build-dokku || log-fail "Error building package" + + fn-extract-package "herokuish_${NEXT_VERSION}_amd64.deb" || log-fail "Error extracting deb package" + fn-extract-package "herokuish-${NEXT_VERSION}-1.x86_64.rpm" || log-fail "Error extracting rpm package" + + fn-publish-package "$IS_RELEASE" "deb" "herokuish_${NEXT_VERSION}_amd64.deb" || log-fail "Error publishing deb package" + fn-publish-package "$IS_RELEASE" "rpm" "herokuish-${NEXT_VERSION}-1.x86_64.rpm" || log-fail "Error publishing rpm package" +} + +main "$@"