Add a bazel based OCI image build to the oci.yaml workflow

This commit is contained in:
Rin Kuryloski 2022-07-22 12:57:10 +02:00
parent 9c7e421450
commit f8e141db63
13 changed files with 615 additions and 2 deletions

View File

@ -150,3 +150,132 @@ jobs:
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
build-publish-dev-bazel:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- image_tag_suffix: otp-min-bazel
otp_major: 24
- image_tag_suffix: otp-max-bazel
otp_major: 25
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Inject RabbitMQ Version
run: |
sed -i"_orig" -E '/APP_VERSION/ s/3\.[0-9]+\.[0-9]+/${{ github.event.pull_request.head.sha || github.sha }}/' rabbitmq.bzl
- name: Mount Bazel Cache
uses: actions/cache@v3.0.7
with:
path: "/home/runner/repo-cache/"
key: repo-cache
- name: Configure Bazel
run: |
if [ -n "${{ secrets.BUILDBUDDY_API_KEY }}" ]; then
cat << EOF >> user.bazelrc
build:buildbuddy --remote_header=x-buildbuddy-api-key=${{ secrets.BUILDBUDDY_API_KEY }}
EOF
fi
cat << EOF >> user.bazelrc
build:buildbuddy --build_metadata=ROLE=CI
build:buildbuddy --build_metadata=VISIBILITY=PRIVATE
build:buildbuddy --repository_cache=/home/runner/repo-cache/
build:buildbuddy --color=yes
build:buildbuddy --disk_cache=
build:buildbuddy --remote_download_toplevel
build --@io_bazel_rules_docker//transitions:enable=false
EOF
- name: Check OTP/Elixir versions used in RBE
id: load-info
run: |
bazelisk build :otp_version :elixir_version \
--config=rbe-${{ matrix.otp_major }}
echo "::set-output name=otp::$(cat bazel-bin/otp_version.txt)"
echo "::set-output name=elixir::$(cat bazel-bin/elixir_version.txt)"
- name: Configure OTP & Elixir
uses: erlef/setup-beam@v1.12
with:
otp-version: ${{ steps.load-info.outputs.otp }}
elixir-version: ${{ steps.load-info.outputs.elixir }}
- name: Further Configure Bazel
run: |
ERLANG_HOME="$(dirname $(dirname $(which erl)))"
ELIXIR_HOME="$(dirname $(dirname $(which iex)))"
cat << EOF >> user.bazelrc
build --@rules_erlang//:erlang_version=${{ matrix.otp_major }}
build --@rules_erlang//:erlang_home=${ERLANG_HOME}
build --//:elixir_home=${ELIXIR_HOME}
build --platforms=//bazel/platforms:erlang_external_platform
build --extra_execution_platforms=//bazel/platforms:erlang_external_platform
EOF
- name: Set the correct erlang source tar for the container
run: |
sudo npm install --global --silent @bazel/buildozer
buildozer 'set tars ["@otp_src_${{ matrix.otp_major }}//file"]' \
//packaging/docker-image:otp_source
git diff
- name: Build
run: |
ERLANG_HOME="$(dirname $(dirname $(which erl)))"
ELIXIR_HOME="$(dirname $(dirname $(which iex)))"
bazelisk build //packaging/docker-image:rabbitmq \
--config=buildbuddy
- name: Test
run: |
ERLANG_HOME="$(dirname $(dirname $(which erl)))"
ELIXIR_HOME="$(dirname $(dirname $(which iex)))"
bazelisk test //packaging/docker-image:all \
--config=buildbuddy
- name: Load
run: |
ERLANG_HOME="$(dirname $(dirname $(which erl)))"
ELIXIR_HOME="$(dirname $(dirname $(which iex)))"
bazelisk run //packaging/docker-image:rabbitmq \
--config=buildbuddy
- name: Check for Push Credentials
id: authorized
run: |
if [ -n "${{ secrets.DOCKERHUB_USERNAME }}" ]; then
echo "::set-output name=PUSH::true"
else
echo "::set-output name=PUSH::false"
fi
- name: Login to DockerHub
if: steps.authorized.outputs.PUSH == 'true'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Tag and Push
if: steps.authorized.outputs.PUSH == 'true'
run: |
TAG_1="${{ github.event.pull_request.head.sha || github.sha }}-${{ matrix.image_tag_suffix }}"
TAG_2="${GITHUB_REF##*/}-${{ matrix.image_tag_suffix }}"
docker tag bazel/packaging/docker-image:rabbitmq \
pivotalrabbitmq/rabbitmq:${TAG_1}
docker tag bazel/packaging/docker-image:rabbitmq \
pivotalrabbitmq/rabbitmq:${TAG_2}
docker push pivotalrabbitmq/rabbitmq:${TAG_1}
docker push pivotalrabbitmq/rabbitmq:${TAG_2}

View File

@ -1,4 +1,4 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
http_archive(
name = "bazel_skylib",
@ -26,6 +26,63 @@ load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")
rules_pkg_dependencies()
http_archive(
name = "io_bazel_rules_docker",
sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
)
load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)
container_repositories()
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
container_deps()
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_pull",
)
container_pull(
name = "ubuntu2004",
registry = "index.docker.io",
repository = "pivotalrabbitmq/ubuntu",
tag = "20.04",
)
http_file(
name = "openssl-1.1.1g",
downloaded_file_path = "openssl-1.1.1g.tar.gz",
sha256 = "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46",
urls = ["https://www.openssl.org/source/openssl-1.1.1g.tar.gz"],
)
http_file(
name = "otp_src_23",
downloaded_file_path = "OTP-23.3.4.16.tar.gz",
# sha256 = "",
urls = ["https://github.com/erlang/otp/archive/OTP-23.3.4.16.tar.gz"],
)
http_file(
name = "otp_src_24",
downloaded_file_path = "OTP-24.3.4.2.tar.gz",
# sha256 = "",
urls = ["https://github.com/erlang/otp/archive/OTP-24.3.4.2.tar.gz"],
)
http_file(
name = "otp_src_25",
downloaded_file_path = "OTP-25.0.3.tar.gz",
# sha256 = "",
urls = ["https://github.com/erlang/otp/archive/OTP-25.0.3.tar.gz"],
)
http_archive(
name = "io_buildbuddy_buildbuddy_toolchain",
sha256 = "a2a5cccec251211e2221b1587af2ce43c36d32a42f5d881737db3b546a536510",

0
packaging/BUILD.bazel Normal file
View File

View File

@ -10,7 +10,6 @@ RUN set -eux; \
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list; \
apt-get update; \
apt-get install -y --no-install-recommends \
# grab gosu for easy step-down from root
libc6-dbg \
libgcc-s1-dbgsym \
libstdc++6-dbgsym \

View File

@ -0,0 +1,253 @@
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_image",
"container_layer",
)
load(
"@io_bazel_rules_docker//contrib:test.bzl",
"container_test",
)
load(
"@io_bazel_rules_docker//docker/util:run.bzl",
"container_run_and_commit_layer",
)
load(
"@io_bazel_rules_docker//docker/package_managers:download_pkgs.bzl",
"download_pkgs",
)
load(
"@io_bazel_rules_docker//docker/package_managers:install_pkgs.bzl",
"install_pkgs",
)
BUILD_DEPS_PACKAGES = [
"autoconf",
"ca-certificates",
"dpkg-dev",
"g++",
"gcc",
"libncurses5-dev",
"make",
]
REQUIRED_PACKAGES = [
"gosu",
]
CONVENIENCE_PACKAGES = [
"python3",
"dstat",
"sysstat",
"htop",
"nmon",
"tmux",
"neovim",
]
download_pkgs(
name = "otp_pkgs",
image_tar = "@ubuntu2004//image",
packages = BUILD_DEPS_PACKAGES,
)
download_pkgs(
name = "rabbitmq_pkgs",
image_tar = "@ubuntu2004//image",
packages = REQUIRED_PACKAGES + CONVENIENCE_PACKAGES,
)
install_pkgs(
name = "otp_pkgs_image",
image_tar = "@ubuntu2004//image",
installables_tar = ":otp_pkgs.tar",
installation_cleanup_commands = "rm -rf /var/lib/apt/lists/*",
output_image_name = "otp_pkgs_image",
)
install_pkgs(
name = "rabbitmq_pkgs_image",
image_tar = "@ubuntu2004//image",
installables_tar = ":rabbitmq_pkgs.tar",
installation_cleanup_commands = "rm -rf /var/lib/apt/lists/*",
output_image_name = "rabbitmq_pkgs_image",
)
container_layer(
name = "openssl_source_layer",
directory = "/usr/local/src",
env = {
"OPENSSL_VERSION": "1.1.1g",
},
files = [
"build_install_openssh.sh",
],
tars = [
"@openssl-1.1.1g//file",
],
)
container_image(
name = "openssl_source",
base = ":otp_pkgs_image",
layers = [":openssl_source_layer"],
)
container_run_and_commit_layer(
name = "openssl_layer",
commands = [
"/usr/local/src/build_install_openssh.sh",
"rm /usr/local/src/build_install_openssh.sh",
],
image = ":openssl_source.tar",
)
container_image(
name = "otp_source",
base = ":otp_pkgs_image",
directory = "/usr/local/src",
files = [
"build_install_otp.sh",
],
layers = [
":openssl_layer",
],
tars = select({
"@rules_erlang//platforms:erlang_23": ["@otp_src_23//file"],
"@rules_erlang//platforms:erlang_24": ["@otp_src_24//file"],
"@rules_erlang//platforms:erlang_25": ["@otp_src_25//file"],
"@rules_erlang//platforms:erlang_external": ["@otp_src_25//file"],
}),
)
container_run_and_commit_layer(
name = "otp_layer",
commands = [
"/usr/local/src/build_install_otp.sh",
"rm /usr/local/src/build_install_otp.sh",
],
image = ":otp_source.tar",
)
container_layer(
name = "rabbitmq_tarball_layer",
directory = "/opt",
files = [
"10-default-guest-user.conf",
"docker-entrypoint.sh",
"install_rabbitmq.sh",
],
tars = [
"//:package-generic-unix",
],
)
RABBITMQ_DATA_DIR = "/var/lib/rabbitmq"
RABBITMQ_HOME = "/opt/rabbitmq"
container_image(
name = "rabbitmq_tarball",
base = ":rabbitmq_pkgs_image",
env = {
"RABBITMQ_DATA_DIR": RABBITMQ_DATA_DIR,
"RABBITMQ_HOME": RABBITMQ_HOME,
"RABBITMQ_LOGS": "-",
},
layers = [
":otp_layer",
":rabbitmq_tarball_layer",
],
)
container_run_and_commit_layer(
name = "rabbitmq_layer",
commands = [
"/opt/install_rabbitmq.sh",
"rm /opt/install_rabbitmq.sh",
],
image = ":rabbitmq_tarball.tar",
)
C_UTF8 = "C.UTF-8"
container_image(
name = "rabbitmq",
base = ":rabbitmq_pkgs_image",
cmd = ["rabbitmq-server"],
entrypoint = ["docker-entrypoint.sh"],
env = {
"RABBITMQ_DATA_DIR": RABBITMQ_DATA_DIR,
"RABBITMQ_HOME": RABBITMQ_HOME,
"RABBITMQ_LOGS": "-",
"HOME": RABBITMQ_DATA_DIR,
"PATH": "%s/sbin:$$PATH" % RABBITMQ_HOME,
"LANG": C_UTF8,
"LANGUAGE": C_UTF8,
"LC_ALL": C_UTF8,
},
layers = [
":otp_layer",
":rabbitmq_layer",
],
ports = [
"4369/tcp", # epmd
"5671/tcp", # amqp-tls
"5672/tcp", # amqp
"25672/tcp", # erlang
"15671/tcp", # management-tls
"15672/tcp", # management
"15691/tcp", # prometheus-tls
"15692/tcp", # prometheus
"5551/tcp", # stream-tls
"5552/tcp", # stream
"8883/tcp", # mqtt-tls
"1883/tcp", # mqtt
"15676/tcp", # web-mqtt-tls
"15675/tcp", # web-mqtt
"61614/tcp", # stomp-tls
"61613/tcp", # stomp
"15673/tcp", # web-stomp-tls
"15674/tcp", # web-stomp
"15670/tcp", # examples
],
tags = ["manual"],
volumes = [
RABBITMQ_DATA_DIR,
],
)
# Wrapper targets for the tarred images are required in order to be able to run
# commandTests in container_test targets.
container_image(
name = "openssl_install_wrapper",
base = ":otp_source",
)
container_image(
name = "otp_install_wrapper",
base = ":rabbitmq_pkgs_image",
layers = [
":otp_layer",
],
)
# Tests
container_test(
name = "openssl_test",
configs = ["//packaging/docker-image/test_configs:openssl_ubuntu.yaml"],
image = ":openssl_install_wrapper",
)
container_test(
name = "otp_test",
configs = ["//packaging/docker-image/test_configs:otp_ubuntu.yaml"],
image = ":otp_install_wrapper",
)
container_test(
name = "rabbitmq_test",
configs = ["//packaging/docker-image/test_configs:rabbitmq_ubuntu.yaml"],
image = ":rabbitmq",
)

View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euxo pipefail
OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"
OPENSSL_CONFIG_DIR=/usr/local/etc/ssl
cd "$OPENSSL_PATH"
# OpenSSL's "config" script uses a lot of "uname"-based target detection...
MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \
RELEASE="4.x.y-z" \
SYSTEM='Linux' \
BUILD='???' \
./config \
--openssldir="$OPENSSL_CONFIG_DIR" \
-Wl,-rpath=/usr/local/lib # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/lib is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364)
# Compile, install OpenSSL, verify that the command-line works & development headers are present
make -j "$(getconf _NPROCESSORS_ONLN)"
make install_sw install_ssldirs
cd ..
rm -rf "$OPENSSL_PATH"*
ldconfig
# use Debian's CA certificates
rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"
ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"
# smoke test
openssl version

View File

@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -euxo pipefail
OTP_PATH="$(cd /usr/local/src/otp-OTP-* && pwd)"
# Configure Erlang/OTP for compilation, disable unused features & applications
# https://erlang.org/doc/applications.html
# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation
cd "$OTP_PATH"
export ERL_TOP="$OTP_PATH"
./otp_build autoconf
CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS
# add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/lib is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364)
export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"
hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"
buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"
dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"
./configure \
--host="$hostArch" \
--build="$buildArch" \
--disable-dynamic-ssl-lib \
--disable-hipe \
--disable-sctp \
--disable-silent-rules \
--enable-jit \
--enable-clock-gettime \
--enable-hybrid-heap \
--enable-kernel-poll \
--enable-shared-zlib \
--enable-smp-support \
--enable-threads \
--with-microstate-accounting=extra \
--without-common_test \
--without-debugger \
--without-dialyzer \
--without-diameter \
--without-edoc \
--without-erl_docgen \
--without-et \
--without-eunit \
--without-ftp \
--without-hipe \
--without-jinterface \
--without-megaco \
--without-observer \
--without-odbc \
--without-reltool \
--without-ssh \
--without-tftp \
--without-wx
# Compile & install Erlang/OTP
make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"
make install
cd ..
rm -rf \
"$OTP_PATH"* \
/usr/local/lib/erlang/lib/*/examples \
/usr/local/lib/erlang/lib/*/src
# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly
erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'

View File

@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -euxo pipefail
mv /opt/rabbitmq_server-* $RABBITMQ_HOME
groupadd --gid 999 --system rabbitmq
useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq
mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq
chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq
chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq
ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie
export PATH="$RABBITMQ_HOME/sbin:$PATH"
# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty
grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"
sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"
grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"
chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"
# verify assumption of no stale cookies
[ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]
# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user
# If they all succeed, it's safe to assume that things have been set up correctly
gosu rabbitmq rabbitmqctl help
gosu rabbitmq rabbitmqctl list_ciphers
gosu rabbitmq rabbitmq-plugins list
# no stale cookies
rm "$RABBITMQ_DATA_DIR/.erlang.cookie"
# Added for backwards compatibility - users can simply COPY custom plugins to /plugins
ln -sf /opt/rabbitmq/plugins /plugins
# move default config and docker entrypoint into place
mv /opt/10-default-guest-user.conf /etc/rabbitmq/conf.d/
chown rabbitmq:rabbitmq /etc/rabbitmq/conf.d/10-default-guest-user.conf
mv /opt/docker-entrypoint.sh /usr/local/bin
# rabbitmq_management
rabbitmq-plugins enable --offline rabbitmq_management && \
rabbitmq-plugins is_enabled rabbitmq_management --offline
# extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile
# see https://github.com/docker-library/rabbitmq/issues/207
# RabbitMQ 3.9 onwards uses uncompressed plugins by default, in which case extraction is
# unnecesary
cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin
[ -s /usr/local/bin/rabbitmqadmin ]
chmod +x /usr/local/bin/rabbitmqadmin
rabbitmqadmin --version
# rabbitmq_prometheus
rabbitmq-plugins enable --offline rabbitmq_prometheus && \
rabbitmq-plugins is_enabled rabbitmq_prometheus --offline
# enable all plugins for dev
rabbitmq-plugins enable --all

View File

@ -0,0 +1 @@
exports_files(glob(["*.yaml"]))

View File

@ -0,0 +1,7 @@
schemaVersion: 2.0.0
commandTests:
- name: "openssl version"
command: "openssl"
args: ["version"]
expectedOutput: ["OpenSSL 1\\.1\\.1g"]

View File

@ -0,0 +1,10 @@
schemaVersion: 2.0.0
commandTests:
- name: "otp version"
command: "erl"
args:
- -noshell
- -eval
- '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().'
expectedOutput: ["2\\d\\.\\d+\\.\\d+"]

View File

@ -0,0 +1,7 @@
schemaVersion: 2.0.0
commandTests:
- name: "rabbitmq-plugins"
command: "rabbitmq-plugins"
args: ["list"]
expectedOutput: ["\\[E \\] rabbitmq_management"]

View File

@ -20,3 +20,5 @@ build:buildbuddy --remote_header=x-buildbuddy-api-key=YOUR_API_KEY
# cross compile for linux (if on macOS) with rbe
# build:rbe --host_cpu=k8
# build:rbe --cpu=k8
build --@io_bazel_rules_docker//transitions:enable=false