Skip to content

Commit

Permalink
Build .deb packages on CI
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekSi committed Jan 28, 2025
1 parent 82dc1aa commit b35414b
Show file tree
Hide file tree
Showing 11 changed files with 406 additions and 0 deletions.
68 changes: 68 additions & 0 deletions .github/workflows/ferretdb_packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
name: Packages
on:
pull_request:
types:
- labeled
- unlabeled
- opened
- reopened
- synchronize
push:
branches:
- "*"
tags:
- "*"
schedule:
- cron: "10 8 * * 1"

# Do not run this workflow in parallel for any PR change or branch/tag push
# to save some resources.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: false

jobs:
build:
name: Build .debs (${{ matrix.os }}, Pg${{ matrix.pg }})

# https://www.ubicloud.com/docs/about/pricing#github-actions
# https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates-for-larger-runners
runs-on: ubicloud-standard-4

timeout-minutes: 40

if: >
github.event_name != 'pull_request' ||
(
!contains(github.event.pull_request.labels.*.name, 'not ready') &&
contains(github.event.pull_request.labels.*.name, 'packages')
)
strategy:
fail-fast: false
matrix:
os: [deb11, deb12, ubuntu20.04, ubuntu22.04, ubuntu24.04]
pg: [15, 16]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Build
run: ./packaging/build_packages.sh --os ${{ matrix.os }} --pg ${{ matrix.pg }} --test-clean-install

- name: Upload
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-${{ matrix.pg }}-debs
path: packaging/*.deb
retention-days: 1
if-no-files-found: error
compression-level: 0
overwrite: false

- name: Check dirty
run: |
git status
git diff --exit-code
81 changes: 81 additions & 0 deletions ferretdb_packaging/Dockerfile_build_deb_packages
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
ARG BASE_IMAGE=debian:bookworm
FROM --platform=linux/amd64 ${BASE_IMAGE}
ARG DEBIAN_FRONTEND=noninteractive

ARG POSTGRES_VERSION=16

RUN apt-get update

RUN apt-get install -y --no-install-recommends \
wget \
gnupg2 \
lsb-release \
ca-certificates \
locales

RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen en_US.UTF-8

ENV LC_ALL=en_US.UTF-8
ENV LANGUAGE=en_US
ENV LC_COLLATE=en_US.UTF-8
ENV LC_CTYPE=en_US.UTF-8
ENV LANG=en_US.UTF-8

RUN echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main ${POSTGRES_VERSION}" > /etc/apt/sources.list.d/pgdg.list && \
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -

RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
tzdata \
build-essential \
pkg-config \
cmake \
git \
postgresql-${POSTGRES_VERSION} \
postgresql-server-dev-${POSTGRES_VERSION} \
libpq-dev \
libicu-dev \
libkrb5-dev \
postgresql-${POSTGRES_VERSION}-cron \
postgresql-${POSTGRES_VERSION}-pgvector \
postgresql-${POSTGRES_VERSION}-postgis-3 \
postgresql-${POSTGRES_VERSION}-rum \
devscripts \
debhelper \
dpkg-dev \
&& rm -rf /var/lib/apt/lists/*

COPY scripts /tmp/install_setup

RUN CLEAN_SETUP=1 INSTALL_DEPENDENCIES_ROOT=/tmp/install_setup /tmp/install_setup/install_setup_pcre2.sh
RUN CLEAN_SETUP=1 INSTALL_DEPENDENCIES_ROOT=/tmp/install_setup /tmp/install_setup/install_setup_intel_decimal_math_lib.sh
RUN CLEAN_SETUP=1 INSTALL_DEPENDENCIES_ROOT=/tmp/install_setup /tmp/install_setup/install_citus_indent.sh

RUN export CLEAN_SETUP=1 && \
export INSTALL_DEPENDENCIES_ROOT=/tmp/install_setup && \
MAKE_PROGRAM=cmake /tmp/install_setup/install_setup_libbson.sh && \
/tmp/install_setup/install_setup_pcre2.sh && \
/tmp/install_setup/install_setup_intel_decimal_math_lib.sh && \
/tmp/install_setup/install_citus_indent.sh

# Set the working directory inside the container
WORKDIR /build

# Copy the source code into the container
COPY . /build

RUN grep -E "^default_version" pg_documentdb_core/pg_documentdb_core.control | sed -E "s/.*'([0-9]+\.[0-9]+-[0-9]+)'.*/\1/" > DOCUMENTDB_VERSION

# Convert the version to the format expected by the debian packaging
RUN sed -i "s/-/\./g" DOCUMENTDB_VERSION

# Setup the debian packaging
COPY packaging/debian_files /build/debian
RUN sed -i "s/POSTGRES_VERSION/${POSTGRES_VERSION}/g" /build/debian/control
RUN sed -i "s/DOCUMENTDB_VERSION/$(cat DOCUMENTDB_VERSION)/g" /build/debian/changelog

COPY packaging/packaging-entrypoint.sh /usr/local/bin/packaging-entrypoint.sh

# Set the entrypoint
ENTRYPOINT ["packaging-entrypoint.sh"]
10 changes: 10 additions & 0 deletions ferretdb_packaging/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# To Build Your Own Debian Packages With Docker
Run `./packaging/build_packages.sh -h` and follow the instructions.
E.g. to build for Debian 12 and PostgreSQL 16, run:
```
./packaging/build_packages.sh --os deb12 --pg 16
```

Packages can be found at the `packages` directory by default, but that can be configured with the `--output-dir` option.

**Note:** The packages do not include pg_documentdb_distributed in the `internal` directory.
142 changes: 142 additions & 0 deletions ferretdb_packaging/build_packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash

set -euo pipefail

# Function to display help message
function show_help {
echo "Usage: $0 --os <OS> --pg <PG_VERSION> [--test-clean-install] [--output-dir <DIR>] [-h|--help]"
echo ""
echo "Description:"
echo " This script builds extension packages using Docker."
echo ""
echo "Mandatory Arguments:"
echo " --os OS to build packages for. Possible values: [deb11, deb12, ubuntu20.04, ubuntu22.04, ubuntu24.04]"
echo " --pg PG version to build packages for. Possible values: [15, 16]"
echo ""
echo "Optional Arguments:"
echo " --test-clean-install Test installing the packages in a clean Docker container."
echo " --output-dir Relative path from the repo root of the directory where to drop the packages. The directory will be created if it doesn't exist. Default: packaging"
echo " -h, --help Display this help message."
exit 0
}

# Initialize variables
OS=""
PG=""
TEST_CLEAN_INSTALL=false
OUTPUT_DIR="packaging" # Default value for output directory

# Process arguments to convert long options to short ones
while [[ $# -gt 0 ]]; do
case "$1" in
--os)
shift
case $1 in
deb11|deb12|ubuntu20.04|ubuntu22.04|ubuntu24.04)
OS=$1
;;
*)
error_exit "Invalid --os value. Allowed values are [deb11, deb12, ubuntu20.04, ubuntu22.04, ubuntu24.04]"
;;
esac
;;
--pg)
shift
case $1 in
15|16)
PG=$1
;;
*)
error_exit "Invalid --pg value. Allowed values are [15, 16]"
;;
esac
;;
--test-clean-install)
TEST_CLEAN_INSTALL=true
;;
--output-dir)
shift
OUTPUT_DIR=$1
;;
-h|--help)
show_help
;;
*)
echo "Unknown argument: $1"
show_help
exit 1
;;
esac
shift
done

# Check mandatory arguments
if [[ -z "$OS" ]]; then
echo "Error: --os is required."
show_help
exit 1
fi

if [[ -z "$PG" ]]; then
echo "Error: --pg is required."
show_help
exit 1
fi

# Set the appropriate Docker image based on the OS
case $OS in
deb11)
DOCKER_IMAGE="debian:bullseye"
;;
deb12)
DOCKER_IMAGE="debian:bookworm"
;;
ubuntu20.04)
DOCKER_IMAGE="ubuntu:20.04"
;;
ubuntu22.04)
DOCKER_IMAGE="ubuntu:22.04"
;;
ubuntu24.04)
DOCKER_IMAGE="ubuntu:24.04"
;;
esac

repo_root=$(git rev-parse --show-toplevel)
abs_output_dir="$repo_root/$OUTPUT_DIR"
cd $repo_root

echo "Building packages for OS: $OS and PostgreSQL version: $PG"
echo "Output directory: $abs_output_dir"

# Create the output directory if it doesn't exist
mkdir -p $abs_output_dir

# Build the Docker image while showing the output to the console
docker build --platform linux/amd64 -t documentdb-build-packages:latest -f packaging/Dockerfile_build_deb_packages \
--build-arg BASE_IMAGE=$DOCKER_IMAGE --build-arg POSTGRES_VERSION=$PG .

# Run the Docker container to build the packages
docker run --platform linux/amd64 --rm -v $abs_output_dir:/output documentdb-build-packages:latest

echo "Packages built successfully!!"

if [[ $TEST_CLEAN_INSTALL == true ]]; then
echo "Testing clean installation in a Docker container..."

deb_package_name=$(ls $abs_output_dir | grep -E "postgresql-$PG-documentdb.*\.deb" | grep -v "dbg" | head -n 1)
deb_package_rel_path="$OUTPUT_DIR/$deb_package_name"

echo "Debian package path: $deb_package_rel_path"

# Build the Docker image while showing the output to the console
docker build --platform linux/amd64 -t documentdb-test-packages:latest -f packaging/test_packages/Dockerfile_test_install_deb_packages \
--build-arg BASE_IMAGE=$DOCKER_IMAGE --build-arg POSTGRES_VERSION=$PG --build-arg DEB_PACKAGE_REL_PATH=$deb_package_rel_path .

# Run the Docker container to test the packages
docker run --platform linux/amd64 --rm documentdb-test-packages:latest

echo "Clean installation test successful!!"
fi

echo "Packages are available in $abs_output_dir"
5 changes: 5 additions & 0 deletions ferretdb_packaging/debian_files/changelog
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
documentdb (DOCUMENTDB_VERSION) unstable; urgency=low

* Initial release.

-- FerretDB Packages <[email protected]> Fri, 24 Jan 2025 12:00:00 +0000
1 change: 1 addition & 0 deletions ferretdb_packaging/debian_files/compat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
12
10 changes: 10 additions & 0 deletions ferretdb_packaging/debian_files/control
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Source: documentdb
Section: database
Priority: optional
Build-Depends: debhelper (>= 11), postgresql-server-dev-POSTGRES_VERSION
Maintainer: FerretDB Packages <[email protected]>

Package: postgresql-POSTGRES_VERSION-documentdb
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, postgresql-POSTGRES_VERSION, postgresql-POSTGRES_VERSION-cron, postgresql-POSTGRES_VERSION-pgvector, postgresql-POSTGRES_VERSION-postgis-3, postgresql-POSTGRES_VERSION-rum
Description: DOCUMENTDB
10 changes: 10 additions & 0 deletions ferretdb_packaging/debian_files/rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/make -f

%:
dh $@

override_dh_auto_test:
make install
adduser --disabled-password --gecos "" documentdb
chown -R documentdb:documentdb .
su documentdb -c "make check"
20 changes: 20 additions & 0 deletions ferretdb_packaging/packaging-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
set -e

# Change to the build directory
cd /build

# Keep the internal directory out of the Debian package
sed -i '/internal/d' Makefile

# Build the Debian package
debuild -us -uc

# Create the output directory if it doesn't exist
mkdir -p /output

# Copy the built packages to the output directory
cp ../*.deb /output/

# Change ownership of the output files to match the host user's UID and GID
chown -R $(stat -c "%u:%g" /output) /output
Loading

0 comments on commit b35414b

Please sign in to comment.