From d028b0404c8a8acd8dd081597db5cffd2e0b9a7d Mon Sep 17 00:00:00 2001 From: Kasper Marstal Date: Fri, 16 Feb 2024 09:17:30 +0100 Subject: [PATCH] Add .deb packaging (#16) --- .github/docker/Dockerfile.debian | 68 +++++++++++++++++++++++++--- .github/docker/run-docker.sh | 34 -------------- .github/workflows/ci.yml | 14 +++--- .github/workflows/package.yml | 77 +++++++++++++++++++++++++++----- 4 files changed, 133 insertions(+), 60 deletions(-) delete mode 100644 .github/docker/run-docker.sh diff --git a/.github/docker/Dockerfile.debian b/.github/docker/Dockerfile.debian index f893a81..b9611f1 100644 --- a/.github/docker/Dockerfile.debian +++ b/.github/docker/Dockerfile.debian @@ -1,21 +1,75 @@ FROM debian:bullseye -ARG PG_MAJOR_VER +ARG PG_MAJOR_VERSION +ARG PLPRQL_VERSION +# Install PostgreSQL RUN apt-get update RUN apt-get install -y wget gnupg RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" >> /etc/apt/sources.list.d/pgdg.list RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - RUN apt-get update -RUN apt-get install -y build-essential postgresql-server-dev-${PG_MAJOR_VER} postgresql-${PG_MAJOR_VER} +RUN apt-get install -y build-essential postgresql-server-dev-${PG_MAJOR_VERSION} postgresql-${PG_MAJOR_VERSION} +# Install utilities +RUN apt-get install -y jq git ruby + +# 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 + +# Install rust RUN apt-get install -y curl pkg-config RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" -RUN cargo install --locked cargo-pgrx --version 0.11.2 -RUN cargo pgrx init --pg${PG_MAJOR_VER} /usr/bin/pg_config +# Prepare source directory +COPY ./ /src +WORKDIR /src/plprql + +# Install pgrx using the version in Cargo.toml +RUN PGRX_VERSION=$(cargo metadata --format-version 1 | jq -r '.packages[]|select(.name=="pgrx")|.version') && \ + cargo install cargo-pgrx --force --version "${PGRX_VERSION}" +RUN cargo pgrx init --pg${PG_MAJOR_VERSION} $(which pg_config) + +# Package the extension. This command will create all the files necessary to package up in a .deb file. +# We know the directory in which this command will create the files, and we save it in the RELEASE_DIR env variable. +RUN cargo pgrx package --features pg${PG_MAJOR_VERSION} +ENV RELEASE_DIR /src/target/release/plprql-pg${PG_MAJOR_VERSION} + +# Create the directory for the outgoing .deb package +RUN mkdir /artifacts && chmod 777 /artifacts + +# Create the --before-install script +RUN echo $'#!/bin/bash\n\ +\n\ +if ! id -u postgres 2>&1 > /dev/null; then\n\ + echo "[!] User 'postgres' does not exist. Have the official Postgres packages been installed yet?"\n\ + exit 1\n\ +fi' >> /tmp/before-install.sh + +# Package everything up based on whatever's in RELEASE_DIR, and send the resulting +# .deb file to the /artifact directory. We don't check if PostgreSQL is installed +# (e.g. via -d "postgresql-${PG_MAJOR_VERSION}") because it could have been compiled +# from source or installed in a myriad of other ways. We simply check for the postgres +# user and let the install fail and hard if the required directories do not exist. +RUN DEB_FILENAME="plprql-${PLPRQL_VERSION}-postgresql-${PG_MAJOR_VERSION}-debian-$(dpkg --print-architecture).deb" && \ + cd ${RELEASE_DIR} && fpm \ + -s dir \ + -t deb \ + -n plprql \ + -m 'Kasper Marstal, kaspermarstal@gmail.com' \ + --description 'PL/PRQL is a PostgreSQL extension that lets you write functions with PRQL.' \ + -v ${PLPRQL_VERSION} \ + --url 'https://github.com/kaspermarstal/plprql' \ + --license 'Apache 2.0 License' \ + --category 'Databases' \ + --deb-no-default-config-files \ + --before-install /tmp/before-install.sh \ + -p /artifacts/$DEB_FILENAME \ + --deb-user postgres \ + --deb-group postgres \ + -a native \ + . -COPY ./ /plprql -WORKDIR /plprql -RUN cargo pgrx install --release -c "/usr/bin/pg_config" +RUN ls /artifacts diff --git a/.github/docker/run-docker.sh b/.github/docker/run-docker.sh deleted file mode 100644 index c397bd3..0000000 --- a/.github/docker/run-docker.sh +++ /dev/null @@ -1,34 +0,0 @@ -#! /usr/bin/env bash - -# Environment variables: -# PG_MAJOR_VER: The major version of Postgres in which to build/run. E.g. 14, 12, 15 -# DOCKERFILE_ID: The Dockerfile identifier to be built, included in this repo, -# e.g. debian:bullseye or amazon:2 -# CARGO_LOCKED_OPTION: Set to '--locked' to use "cargo --locked", or set to -# blank '' to use "cargo" without "--locked" - -# Examples of running this script in CI (currently Github Actions): -# ./.github/docker/run-docker.sh 14 debian_bullseye -# ./.github/docker/run-docker.sh 12 fedora - -set -x - -PG_MAJOR_VER=$1 -DOCKERFILE_ID=$2 - -echo "Building docker container for Postgres version $PG_MAJOR_VER on $DOCKERFILE_ID" -echo "Cargo lock flag set to: '$CARGO_LOCKED_OPTION'" - -docker build \ - --build-arg PG_MAJOR_VER="$PG_MAJOR_VER" \ - -t plprql \ - -f ".github/docker/Dockerfile.$DOCKERFILE_ID" \ - . - -echo "Packaging PL/PRQL for Postgres version $PG_MAJOR_VER on $DOCKERFILE_ID" - -docker run plprql \ - cargo test \ - --no-default-features \ - --features "pg$PG_MAJOR_VER" \ - "$CARGO_LOCKED_OPTION" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a17c75b..2488ac6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false # We want all of them to run, even if one fails matrix: os: [ ubuntu-latest, macos-latest ] - pg: [ "pg12", "pg13", "pg14", "pg15", "pg16" ] + pg: [ "12", "13", "14", "15", "16" ] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -27,11 +27,11 @@ jobs: run: | PGRX_VERSION=$(cargo metadata --format-version 1 | jq -r '.packages[]|select(.name=="pgrx")|.version') cargo install --locked --version=$PGRX_VERSION cargo-pgrx --debug --force - cargo pgrx init --${{ matrix.pg }} download + cargo pgrx init --pg${{ matrix.pg }} download - name: Run unit tests - run: cd plprql && echo "\q" | cargo pgrx run ${{ matrix.pg }} && cargo test --no-default-features --features ${{ matrix.pg }} + run: cd plprql && echo "\q" | cargo pgrx run pg${{ matrix.pg }} && cargo test --no-default-features --features pg${{ matrix.pg }} - name: Run integration tests - run: cd plprql && echo "\q" | cargo pgrx run ${{ matrix.pg }} && cd ../plprql-tests && cargo test --no-default-features --features ${{ matrix.pg }} + run: cd plprql && echo "\q" | cargo pgrx run pg${{ matrix.pg }} && cd ../plprql-tests && cargo test --no-default-features --features pg${{ matrix.pg }} Install: runs-on: ubuntu-latest steps: @@ -69,7 +69,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - pg: [ "pg16" ] + pg: [ "16" ] steps: - name: Checkout code uses: actions/checkout@v4 @@ -77,7 +77,7 @@ jobs: run: | PGRX_VERSION=$(cargo metadata --format-version 1 | jq -r '.packages[]|select(.name=="pgrx")|.version') cargo install --locked --version=$PGRX_VERSION cargo-pgrx --debug --force - cargo pgrx init --${{ matrix.pg }} download + cargo pgrx init --pg${{ matrix.pg }} download - name: Run clippy - run: cargo clippy --all-targets --no-default-features --features ${{ matrix.pg }} -- -D warnings + run: cargo clippy --all-targets --no-default-features --features pg${{ matrix.pg }} -- -D warnings diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 599fc0f..7b92d44 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -4,11 +4,6 @@ on: push: branches: - main - pull_request: - branches: - - main - # schedule: - # - cron: '0 7 * * MON-FRI' workflow_dispatch: env: @@ -16,21 +11,79 @@ env: CARGO_INCREMENTAL: "false" jobs: - Deb: - if: false + Debian: runs-on: ubuntu-latest strategy: fail-fast: false # We want all of them to run, even if one fails matrix: pg: [ "12", "13", "14", "15", "16" ] - os: [ "debian" ] + os: [ { distribution: "debian", release: "bullseye" }, { distribution: "debian", release: "bookworm" } ] steps: - uses: actions/checkout@v4 - - name: Package PL/PRQL for PostgreSQL ${{ matrix.pg }} (${{ matrix.os }}) - shell: bash + with: + fetch-depth: 0 # Ensure all history for tags and branches is fetched + - name: Extract PL/PRQL version + run: | + # Find the latest tag + LATEST_TAG=$(git describe --tags --abbrev=0) + + # Get the short SHA of the current commit + COMMIT_SHORT_SHA=$(git rev-parse --short=8 HEAD) + + # Determine if the latest push is exactly the latest tag + if [[ "refs/tags/$LATEST_TAG" == "$GITHUB_REF" ]]; then + # If the push is for the latest tag, use the tag as the version + PLPRQL_VERSION=${LATEST_TAG#v} + else + # If the push is not for a tag, append the current commit's short SHA to the latest tag + PLPRQL_VERSION="${LATEST_TAG#v}-$COMMIT_SHORT_SHA" + fi + + echo "PLPRQL_VERSION=$PLPRQL_VERSION" >> $GITHUB_ENV + echo "Version is $PLPRQL_VERSION" + - name: Package PL/PRQL .deb for PostgreSQL ${{ matrix.pg }} on ${{ matrix.os.distribution }} ${{ matrix.os.release }} + run: | + docker build \ + --build-arg PG_MAJOR_VERSION=${{ matrix.pg }} \ + --build-arg PLPRQL_VERSION=$PLPRQL_VERSION \ + -t "plprql-$PLPRQL_VERSION-pg-${{ matrix.pg }}-${{ matrix.os.distribution }}-${{ matrix.os.release }}" \ + -f ".github/docker/Dockerfile.${{ matrix.os.distribution }}" \ + . + - name: Extract .deb + run: | + CONTAINER_ID=$(docker create plprql-$PLPRQL_VERSION-pg-${{ matrix.pg }}-${{ matrix.os.distribution }}-${{ matrix.os.release }}) + docker cp $CONTAINER_ID:/artifacts /home/runner + docker rm -v $CONTAINER_ID + - name: Verify Install run: | - docker build --build-arg PG_MAJOR_VERSION="${{ matrix.pg }}" -t plprql -f ".github/docker/Dockerfile.${{ matrix.os }}" . - docker run plprql cargo test --no-default-features --features "pg${{ matrix.pg }}" + CONTAINER_ID=$(docker run -d -e POSTGRES_HOST_AUTH_METHOD=trust postgres:${{ matrix.pg }}-${{ matrix.os.release }}) + docker cp /home/runner/artifacts $CONTAINER_ID:/tmp + ls -R /home/runner/artifacts + docker exec $CONTAINER_ID ls -R /tmp + docker exec $CONTAINER_ID bash -c 'dpkg -i /tmp/artifacts/plprql*.deb' + + max_tries=30 + count=0 + + until docker exec $CONTAINER_ID pg_isready -U postgres; do + count=$((count+1)) + echo "Waiting for PostgreSQL to start (attempt $count of $max_tries)" + sleep 1 + if [ $count -ge $max_tries ]; then + echo "PostgreSQL failed to start" + exit 1 + fi + done + + docker exec $CONTAINER_ID psql -U postgres -c "create extension plprql;" + docker exec $CONTAINER_ID psql -U postgres -c "select prql_to_sql('from table');" + docker stop $CONTAINER_ID + docker rm -v $CONTAINER_ID + - name: Upload .deb + if: startsWith(github.ref, 'refs/tags/v') + uses: softprops/action-gh-release@v1 + with: + files: /home/runner/artifacts/plprql*.deb Bash: runs-on: ubuntu-latest steps: