Skip to content

Commit

Permalink
Artifact builds upon release (#302)
Browse files Browse the repository at this point in the history
These changes will allow Github Actions to build Debian packages to be created and attached to releases whenever releases are made.
  • Loading branch information
BradyBonnette authored May 9, 2023
1 parent f8a9718 commit b821159
Show file tree
Hide file tree
Showing 14 changed files with 648 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ cmake*/
.direnv
plrust/postgrestd
.git
Dockerfile.try
Dockerfile.*
186 changes: 186 additions & 0 deletions .github/docker/Dockerfile.debian-artifact-build
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# NOTE: This Dockerfile will require a more recent version of Docker that has heredoc support.
#
# Example of how to build this Dockerfile (requires being launched from the root of checkout):
# docker build --build-arg PG_VER=15 --build-arg PLRUST_VER=1.0.2 -f .github/docker/Dockerfile.debian-artifact-build -t plrust-debian .
#
# Example of how to run an image after it has been built (assuming previous step has been done):
# docker run -it --rm plrust-debian /bin/bash
#
# Any artifacts produced will be in the /out directory of the running Docker container. With a container running, an example
# of how to copy out artifacts:
# docker cp container_name:/out .
# which will copy the container's /out directory to the current directory of the host

FROM debian:bullseye

# Args to pass in at build-time. Note that these are defaulted.
ARG PG_VER=15
ARG PLRUST_VER=0.0.0

# Change this value if the entire build cache needs to be busted for any reason.
# Any random value can work here. UUIDs seemed to be a good choice.
ARG CACHE_KEY=2d912233-4423-48f9-b7ba-afc6b2ef3a44

SHELL ["/bin/bash", "-c"]

# Install system-level dependencies. Prefer to install Postgres from the official
# Postgres Debian packages
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections && \
apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
gnupg \
lsb-release \
wget && \
sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg >/dev/null && \
apt-get update -y -qq --fix-missing && \
apt-get install -y --no-install-recommends \
build-essential \
clang \
clang-11 \
gcc \
git \
jq \
libssl-dev \
llvm-11 \
make \
postgresql-${PG_VER} \
postgresql-server-dev-${PG_VER} \
pkg-config \
ruby && \
rm -rf /var/lib/apt/lists/*

# Install fpm for the creation of the .deb file,
# and install toml so TOML files can be parsed later
RUN gem install --no-document fpm toml

# Set up permissions so that the postgres user can install the plrust plugin
RUN chmod a+rwx `$(which pg_config) --pkglibdir` `$(which pg_config) --sharedir`/extension

# Create the directory for the outgoing .deb package
RUN mkdir /out && chmod 777 /out

# The 'postgres' user is the default user that the official Postgres Debian packages create and set up
USER postgres
ENV USER postgres

# Copy in plrust source
COPY --chown=${USER} . src/
WORKDIR /src

# Obtain the toolchain version from rust-toolchain.toml and store that into a file.
RUN ruby <<EOF
require 'toml'
toml=TOML.load_file('/src/rust-toolchain.toml')
if ver=toml['toolchain']['channel']
File.open('/tmp/.toolchain-ver', 'w') { |file| file.write(ver) }
else
raise 'Could not determine toolchain channel version. Is rust-toolchain.toml missing or malformed?'
end
EOF

# Install Rust
RUN TOOLCHAIN_VER=$(</tmp/.toolchain-ver) && wget -qO- https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain=$TOOLCHAIN_VER
ENV PATH="/var/lib/postgresql/.cargo/bin:${PATH}"

# Install the version of PGRX that is dictated by Cargo.toml for this project
RUN PGRX_VERSION=$(cargo metadata --format-version 1 | jq -r '.packages[]|select(.name=="pgrx")|.version') && \
cargo install cargo-pgrx --force --version "$PGRX_VERSION"

# Necessary to build plrustc and company
RUN rustup component add llvm-tools-preview rustc-dev

# Build and install plrstuc
RUN cd /src/plrustc && ./build.sh && cp ../build/bin/plrustc ~/.cargo/bin

# Init cargo pgrx
RUN cargo pgrx init --pg${PG_VER} $(which pg_config)

# Build plrust with postgrestd. Architecture is determined by the host running this Dockerfile
# (i.e. no cross-compiling)
RUN cd /src/plrust && STD_TARGETS="$(uname -m)-postgres-linux-gnu" ./build

# Use cargo pgrx package to create everything necessary, placed into RELEASE_DIR below
RUN cd /src/plrust && cargo pgrx package --features trusted

# This is the root of all the files necessary to package up into the .deb file. This specific path is generated by
# 'cargo pgrx package' above
ENV RELEASE_DIR /src/target/release/plrust-pg${PG_VER}

# Create the plrustc location for our distribution, then copy in the plrustc program into the correct spot
RUN mkdir -p ${RELEASE_DIR}$HOME/.cargo/bin && \
cp $HOME/.cargo/bin/plrustc ${RELEASE_DIR}$HOME/.cargo/bin

# The .deb file distribution needs to include the correct postgrestd toolchain files.
RUN cd $HOME/.rustup && \
export TOOLCHAIN_DIR="$(pwd)/$(find * -type d -name '*postgres*' | head -n 1)" && \
mkdir -p "${RELEASE_DIR}$TOOLCHAIN_DIR" && \
cp -r "$TOOLCHAIN_DIR/." "${RELEASE_DIR}$TOOLCHAIN_DIR"

# Creates a PGRX configuration Toml file, as it is required to build plrust user-defined functions
RUN mkdir -p ${RELEASE_DIR}$HOME/.pgrx && \
echo '[configs]' >> ${RELEASE_DIR}$HOME/.pgrx/config.toml && \
echo "pg${PG_VER}='$(command -v pg_config)'" >> ${RELEASE_DIR}$HOME/.pgrx/config.toml

# Create a Debian preinst script that will run before the installation of the pl/Rust package.
# This will check to be sure the proper Rust toolchain and components are set up beforehand.
RUN TOOLCHAIN_VER=$(</tmp/.toolchain-ver) && cat <<EOF > /tmp/preinst
#!/usr/bin/env bash

if ! id -u postgres 2&> /dev/null; then
echo "[!] User 'postgres' does not exist. Have the official Postgres packages been installed yet?"
exit 1
fi

if ! runuser -l postgres -c 'command -v rustup'; then
echo "[!] The 'postgres' user does not have rustup installed. Please see package installation instructions on how to do this.";
exit 1
fi

if ! runuser -l postgres -c 'command -v rustc'; then
echo "[!] The 'postgres' user does not have Rust installed. Please see package installation instructions on how to do this.";
exit 1
fi

if ! runuser -l postgres -c 'rustup toolchain list | grep -q "^$TOOLCHAIN_VER-$(uname -m)\b"'; then
echo "[!] The 'postgres' user does not have the Rust toolchain $TOOLCHAIN_VER-$(uname -m) installed. Please see package installation instructions on how to do this.";
exit 1
fi

if ! runuser -l postgres -c 'rustup component list | grep -q "^rustc-dev-$(uname -m)\b.*(installed)$"'; then
echo "[!] The 'postgres' user does not have the Rust component 'rustc-dev' installed. Please see package installation instructions on how to do this.";
exit 1
fi

if ! runuser -l postgres -c 'rustup toolchain list | grep -q "^$TOOLCHAIN_VER-$(uname -m)\b.*(default)$"'; then
echo "[!] The 'postgres' user does not have the default toolchain set to $TOOLCHAIN_VER. Please see package installation instructions on how to do this.";
exit 1
fi

EOF

# Package everything up based on whatever's in RELEASE_DIR, and send the resulting
# .deb file to the /out directory
RUN TOOLCHAIN_VER=$(</tmp/.toolchain-ver) && \
DEB_FILENAME="plrust-trusted-${PLRUST_VER}_$TOOLCHAIN_VER-debian-pg${PG_VER}-$(dpkg --print-architecture).deb" && \
cd ${RELEASE_DIR} && fpm \
-s dir \
-t deb \
-n plrust \
--deb-pre-depends "postgresql-${PG_VER}" \
-d "postgresql-${PG_VER}" \
-d "postgresql-server-dev-${PG_VER}" \
-m 'Technology Concepts & Design, Inc. <support@tcdi.com>' \
--description 'PL/Rust is a loadable procedural language that enables writing PostgreSQL functions in the Rust programming language.' \
-v ${PLRUST_VER} \
--url 'https://github.com/tcdi/plrust' \
--license 'The PostgreSQL License' \
--category 'Databases' \
--deb-no-default-config-files \
--before-install /tmp/preinst \
-p /out/$DEB_FILENAME \
--deb-user postgres \
--deb-group postgres \
-a native \
.
10 changes: 6 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install mdbook
- name: Install Rust
run: |
mkdir mdbook
curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.14/mdbook-v0.4.14-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
echo `pwd`/mdbook >> $GITHUB_PATH
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "PATH=$HOME/.cargo/bin:$PATH" >> $GITHUB_ENV
- name: Install mdbook and other preprocessors
run: |
cargo install mdbook mdbook-variables
- name: Deploy GitHub Pages
run: |
# This assumes your book is in the root of your repository.
Expand Down
Loading

0 comments on commit b821159

Please sign in to comment.