diff --git a/.github/workflows/cache-base-image.yml b/.github/workflows/cache-base-image.yml index e0e28ed2..e0a5e250 100644 --- a/.github/workflows/cache-base-image.yml +++ b/.github/workflows/cache-base-image.yml @@ -1,8 +1,26 @@ name: Update base OS image -run-name: Updating the base OS and install necessary extra packages +run-name: Updating the base OS and install necessary extra packages (multiplatform) + +# This workflow builds the pgEdge base test image with full reproducibility metadata: +# - Captures build timestamp, git commit SHA, branch, and Rocky Linux version +# - Embeds build information in /etc/pgedge/build-info.txt within the image +# - Tags images with both :latest and :${GIT_COMMIT} for version tracking +# - Adds OCI labels for standard metadata inspection +# - Prints all build metadata to workflow output for issue reproduction on: workflow_dispatch: + inputs: + image_name: + description: 'Base image name (without registry/owner prefix)' + required: false + default: 'base-test-image' + type: string + image_tag: + description: 'Additional custom tag (besides :latest and :)' + required: false + default: '' + type: string permissions: contents: read @@ -32,9 +50,40 @@ jobs: env: OWNER: '${{ github.repository_owner }}' - - name: Set up Docker + # Capture build metadata for reproducibility + - name: Capture build metadata + id: meta + run: | + echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> ${GITHUB_ENV} + echo "GIT_COMMIT=$(git rev-parse HEAD)" >> ${GITHUB_ENV} + echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> ${GITHUB_ENV} + echo "ROCKYLINUX_VERSION=$(docker run --rm rockylinux:9 cat /etc/rocky-release)" >> ${GITHUB_ENV} + echo "IMAGE_NAME=${{ inputs.image_name || 'base-test-image' }}" >> ${GITHUB_ENV} + + # Print build information + echo "=========================================" + echo "pgEdge Base Image Build Information" + echo "=========================================" + echo "Image Name: ${{ inputs.image_name || 'base-test-image' }}" + echo "Custom Tag: ${{ inputs.image_tag }}" + echo "Build Date: $(date -u +'%Y-%m-%dT%H:%M:%SZ')" + echo "Git Commit: $(git rev-parse HEAD)" + echo "Git Branch: $(git rev-parse --abbrev-ref HEAD)" + echo "Rocky Linux: $(docker run --rm rockylinux:9 cat /etc/rocky-release)" + echo "Platforms: linux/amd64, linux/arm64" + echo "=========================================" + + # Set up QEMU for multiplatform builds + - name: Set up QEMU + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up Docker Buildx # Codacy wants us to use full commit SHA. This is for v3 uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3 + with: + platforms: linux/amd64,linux/arm64 # Login to GHCR - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef @@ -43,15 +92,85 @@ jobs: username: $OWNER_LC password: ${{ secrets.GITHUB_TOKEN }} - # Prepare cached version of the base image - - name: Build and push base system image + # Prepare cached version of the base image with build metadata + - name: Build and push multiplatform base system image uses: docker/build-push-action@c382f710d39a5bb4e430307530a720f50c2d3318 with: context: . file: tests/docker/Dockerfile-base.el9 + platforms: linux/amd64,linux/arm64 push: true - tags: ghcr.io/${{ env.OWNER_LC }}/base-test-image:latest + tags: | + ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:latest + ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:${{ env.GIT_COMMIT }} + ${{ inputs.image_tag && format('ghcr.io/{0}/{1}:{2}', env.OWNER_LC, env.IMAGE_NAME, inputs.image_tag) || '' }} + build-args: | + BUILD_DATE=${{ env.BUILD_DATE }} + GIT_COMMIT=${{ env.GIT_COMMIT }} + GIT_BRANCH=${{ env.GIT_BRANCH }} + ROCKYLINUX_VERSION=${{ env.ROCKYLINUX_VERSION }} cache-from: type=gha,scope=base cache-to: type=gha,mode=max,scope=base + provenance: false + sbom: false + + # Verify multiplatform manifest + - name: Inspect multiplatform manifest + run: | + docker buildx imagetools inspect ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:latest + + # Verify and display build information from the image + - name: Display build information + run: | + echo "" + echo "=========================================" + echo "Multiplatform Image Built Successfully!" + echo "=========================================" + echo "Image Name: ${{ env.IMAGE_NAME }}" + echo "Platforms: linux/amd64, linux/arm64" + echo "" + echo "Image Tags:" + echo " - ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:latest" + echo " - ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:${{ env.GIT_COMMIT }}" + if [ -n "${{ inputs.image_tag }}" ]; then + echo " - ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:${{ inputs.image_tag }}" + fi + echo "" + echo "To pull this specific build:" + echo " docker pull ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:${{ env.GIT_COMMIT }}" + echo "" + echo "Docker will automatically select the correct architecture:" + echo " - linux/amd64 for Intel/AMD systems" + echo " - linux/arm64 for Apple Silicon Macs (M1/M2/M3/M4)" + echo "" + echo "To view build info from the image:" + echo " docker run --rm ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:latest cat /etc/pgedge/build-info.txt" + echo "" + echo "To inspect image labels:" + echo " docker inspect ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}:latest | jq '.[0].Config.Labels'" + echo "=========================================" -# And we have a base image. Check: https://github.com/pgedge/spock/pkgs/container/base-test-image +# ============================================================================== +# Build Complete! +# ============================================================================== +# The base image is available at: +# https://github.com/pgedge/spock/pkgs/container/ +# +# Workflow Inputs (configurable through Actions UI): +# - image_name: Base image name (default: 'base-test-image') +# - image_tag: Optional custom tag in addition to :latest and : +# +# Each build includes comprehensive reproducibility metadata: +# 1. /etc/pgedge/build-info.txt - Embedded build information file +# 2. OCI image labels with build timestamp, commit SHA, and branch +# 3. Commit-specific tag (:) for immutable references +# 4. Optional custom tag (:) if provided +# 5. Workflow output with all build parameters +# +# To reproduce any build: +# 1. Check workflow output or image labels for git commit SHA +# 2. Checkout that commit: git checkout +# 3. Run the docker build command shown in /etc/pgedge/build-info.txt +# +# Documentation: tests/docker/Dockerfile-base.md +# ============================================================================== diff --git a/.github/workflows/spockbench.yml b/.github/workflows/spockbench.yml index cc0876a3..fa478b0f 100644 --- a/.github/workflows/spockbench.yml +++ b/.github/workflows/spockbench.yml @@ -6,7 +6,6 @@ on: pull_request: types: [opened, synchronize, reopened] - permissions: contents: read diff --git a/tests/docker/Dockerfile-base.el9 b/tests/docker/Dockerfile-base.el9 index b9068f9b..45b86be9 100644 --- a/tests/docker/Dockerfile-base.el9 +++ b/tests/docker/Dockerfile-base.el9 @@ -1,94 +1,148 @@ -# ############################################################################## -# -# Base test image for pgEdge Spock development and testing. +# syntax=docker/dockerfile:1 + +# ============================================================================== +# Base Test Image for pgEdge Products Development and Testing +# ============================================================================== # -# This image includes: -# - Rocky Linux 9 base with development tools -# - PostgreSQL build dependencies (LLVM, ICU, SSL, etc.) -# - Testing tools (Perl Test::More, SSH) -# - pgedge user with sudo access +# Description: +# This image provides a Rocky Linux 9 base with all necessary dependencies +# for building and testing PostgreSQL extensions, specifically pgEdge Spock. # -# Built and published to: ghcr.io/pgedge/base-test-image:latest +# Included Components: +# - Rocky Linux 9 base OS with development tools +# - PostgreSQL build dependencies (compilers, libraries, etc.) +# - Testing frameworks (Perl Test::More) +# - SSH server for testing connectivity +# - pgedge user with sudo privileges # -# ############################################################################## +# Build Target: ghcr.io/pgedge/base-test-image:latest +# ============================================================================== +# Use the latest Rocky Linux 9 base image FROM rockylinux:9 -# Update system and install base development tools -RUN dnf -y update && \ +# Define build arguments for customization and reproducibility +ARG PGEDGE_USER=pgedge +ARG BUILD_DATE +ARG GIT_COMMIT +ARG GIT_BRANCH +ARG ROCKYLINUX_VERSION + +# Set metadata labels for reproducibility +LABEL org.opencontainers.image.title="pgEdge Dev Base Test Image" \ + org.opencontainers.image.description="Base image for pgEdge development and testing" \ + org.opencontainers.image.vendor="pgEdge" \ + org.opencontainers.image.maintainer="andrei.lepikhov@pgedge.com" \ + org.opencontainers.image.licenses="BSD" \ + org.opencontainers.image.created="${BUILD_DATE}" \ + org.opencontainers.image.revision="${GIT_COMMIT}" \ + org.opencontainers.image.source="https://github.com/pgedge/spock" \ + com.pgedge.base-os.version="${ROCKYLINUX_VERSION}" \ + com.pgedge.git.branch="${GIT_BRANCH}" + +# ============================================================================== +# Build Information for Reproducibility +# ============================================================================== +RUN set -eux && \ + mkdir -p /etc/pgedge && \ + printf "pgEdge Base Test Image Build Information\n" > /etc/pgedge/build-info.txt && \ + printf "=========================================\n\n" >> /etc/pgedge/build-info.txt && \ + printf "Build Date: %s\n" "${BUILD_DATE:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf "Git Commit: %s\n" "${GIT_COMMIT:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf "Git Branch: %s\n" "${GIT_BRANCH:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf "Rocky Linux: %s\n" "${ROCKYLINUX_VERSION:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf "\nTo reproduce this exact build:\n" >> /etc/pgedge/build-info.txt && \ + printf " git clone https://github.com/pgedge/spock.git\n" >> /etc/pgedge/build-info.txt && \ + printf " git checkout %s\n" "${GIT_COMMIT:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf " docker build -f tests/docker/Dockerfile-base.el9 \\\\\n" >> /etc/pgedge/build-info.txt && \ + printf " --build-arg BUILD_DATE=%s \\\\\n" "${BUILD_DATE:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf " --build-arg GIT_COMMIT=%s \\\\\n" "${GIT_COMMIT:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf " --build-arg GIT_BRANCH=%s .\n" "${GIT_BRANCH:-unknown}" >> /etc/pgedge/build-info.txt && \ + printf "\n" >> /etc/pgedge/build-info.txt && \ + cat /etc/pgedge/build-info.txt + +# ============================================================================== +# System Update and Base Development Tools Installation +# ============================================================================== +RUN set -eux && \ dnf -y upgrade && \ dnf -y install sudo && \ - dnf -y groupinstall "Development Tools" - -# Create pgedge user with sudo privileges -RUN useradd -m pgedge -s /bin/bash && \ - echo pgedge:asdf | chpasswd && \ - echo "pgedge ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/pgedge && \ - chmod 0440 /etc/sudoers.d/pgedge && \ - chown -R pgedge:pgedge /home/pgedge + dnf -y groupinstall "Development Tools" && \ + dnf clean all && \ + rm -rf /var/cache/dnf/* -# Install PostgreSQL build dependencies and testing tools -# Note: List inlined to avoid requiring build context with external files -RUN dnf install --allowerasing --enablerepo=crb -y \ - bison \ - clang \ - curl \ - cyrus-sasl-gssapi \ - dnsutils \ - flex \ - jansson-devel \ - krb5-devel \ - libicu-devel \ - libpq \ - libpq-devel \ - libuuid \ - libuuid-devel \ - libxslt \ - libxslt-devel \ - llvm \ - llvm-devel \ - lz4 \ - lz4-devel \ - nc \ - openldap \ - openldap-devel \ - openssh-clients \ - openssh-server \ - openssl-devel \ - pam-devel \ - perl \ - perl-App-cpanminus \ - perl-devel \ - perl-IPC-Run \ - pkgconfig \ - procps \ - python3 \ - python3-devel \ - sudo \ - systemd-devel \ - unzip \ - uuid \ - uuid-devel \ - vim \ - zlib \ - zlib-devel && \ - dnf clean all +# ============================================================================== +# User Creation and Configuration +# ============================================================================== +RUN set -eux && \ + useradd -m -s /bin/bash ${PGEDGE_USER} && \ + echo "${PGEDGE_USER}:asdf" | chpasswd && \ + echo "${PGEDGE_USER} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${PGEDGE_USER} && \ + chmod 0440 /etc/sudoers.d/${PGEDGE_USER} && \ + chown -R ${PGEDGE_USER}:${PGEDGE_USER} /home/${PGEDGE_USER} -# Install Perl testing dependencies -RUN cpanm Test::More +# ============================================================================== +# PostgreSQL Build Dependencies and Testing Tools +# ============================================================================== +# Install all required packages in a single RUN to minimize layers +RUN set -eux && \ + dnf install --allowerasing --enablerepo=crb -y \ + bind-utils \ + bison \ + clang \ + curl \ + cyrus-sasl-gssapi \ + flex \ + gcc \ + git \ + jansson-devel \ + krb5-devel \ + libicu-devel \ + libpq \ + libpq-devel \ + libuuid-devel \ + libxml2-devel \ + libxslt-devel \ + llvm \ + llvm-devel \ + lz4-devel \ + make \ + nc \ + openldap-devel \ + openssh-clients \ + openssh-server \ + openssl-devel \ + pam-devel \ + perl \ + perl-devel \ + perl-IPC-Run \ + perl-Test-Simple \ + pkgconfig \ + procps \ + python3 \ + python3-devel \ + readline-devel \ + systemd-devel \ + unzip \ + uuid-devel \ + zlib-devel \ + libzstd-devel && \ + dnf clean all && \ + rm -rf /var/cache/dnf/* /tmp/* /var/tmp/* -# Setup SSH for pgedge user (not root!) -# This allows SSH-based testing as the pgedge user -USER pgedge -RUN mkdir -p ~/.ssh && \ - ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519 && \ - cat ~/.ssh/*.pub >> ~/.ssh/authorized_keys && \ +# ============================================================================== +# SSH Configuration for Testing +# ============================================================================== +# Switch to pgedge user for SSH setup (security best practice) +USER ${PGEDGE_USER} +RUN set -eux && \ + mkdir -p ~/.ssh && \ + ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519 -C "${PGEDGE_USER}@localhost" && \ + cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys && \ chmod 700 ~/.ssh && \ - chmod 600 ~/.ssh/authorized_keys - -# Set default working directory -WORKDIR /home/pgedge + chmod 600 ~/.ssh/authorized_keys ~/.ssh/id_ed25519 -# Metadata -LABEL maintainer="andrei.lepikhov@pgedge.com" -LABEL description="Base image for pgEdge Spock PostgreSQL extension development and testing" +# ============================================================================== +# Working Directory and Final Setup +# ============================================================================== +WORKDIR /home/${PGEDGE_USER} diff --git a/tests/docker/Dockerfile-base.md b/tests/docker/Dockerfile-base.md new file mode 100644 index 00000000..9fda6705 --- /dev/null +++ b/tests/docker/Dockerfile-base.md @@ -0,0 +1,310 @@ +# pgEdge Base Test Image + +## Overview + +This document describes the **pgEdge Base Test Image** (`ghcr.io/pgedge/base-test-image`), a foundational Docker image designed for building and testing PostgreSQL extensions, specifically the pgEdge Spock logical replication extension. + +**Image Registry**: `ghcr.io/pgedge/base-test-image:latest` +**Base OS**: Rocky Linux 9 +**Platforms**: linux/amd64 (x86_64), linux/arm64 (Apple Silicon) +**Purpose**: Development and testing environment for PostgreSQL extension development + +## Purpose + +This image provides a **complete, reproducible build environment** for PostgreSQL and its extensions. It eliminates the need to manually install dozens of dependencies and ensures consistent builds across different development machines and CI/CD environments. + +### Key Use Cases + +1. **PostgreSQL Extension Development**: Build and test custom PostgreSQL extensions with all necessary compilation tools and libraries +2. **CI/CD Integration**: Use as a base image for automated testing pipelines +3. **Multi-version Testing**: Easily test extensions against different PostgreSQL versions +4. **Consistent Build Environment**: Reproducible builds across different systems and CI/CD platforms + +## What This Image Provides + +### 1. Complete Development Toolchain + +- **Compilers**: GCC, Clang, LLVM with LLVM-dev support +- **Build Tools**: GNU Make, CMake, Autoconf, Automake, Bison, Flex +- **Version Control**: Git for cloning PostgreSQL and extension sources +- **Debugging Tools**: GDB and debugging symbols support + +### 2. PostgreSQL Build Dependencies + +The image includes **all** libraries required to build PostgreSQL with maximum feature set: + +| Library | Purpose | Configure Flag | +|---------|---------|----------------| +| `zstd-devel` | Zstandard compression | `--with-zstd` | +| `lz4-devel` | LZ4 compression | `--with-lz4` | +| `libicu-devel` | Unicode and internationalization | `--with-icu` | +| `libxml2-devel` | XML support | `--with-libxml` | +| `libxslt-devel` | XSLT transformations | `--with-libxslt` | +| `openssl-devel` | SSL/TLS connections | `--with-openssl` | +| `krb5-devel` | Kerberos authentication | `--with-gssapi` | +| `openldap-devel` | LDAP authentication | `--with-ldap` | +| `pam-devel` | PAM authentication | `--with-pam` | +| `systemd-devel` | Systemd integration | `--with-systemd` | +| `python3-devel` | PL/Python language | `--with-python` | +| `readline-devel` | Enhanced psql CLI | Built-in | +| `llvm-devel` | JIT compilation | `--with-llvm` | +| `libuuid-devel` | UUID generation | `--with-uuid=ossp` | + +### 3. Testing Infrastructure + +- **Perl Testing Framework**: `perl-IPC-Run`, `Test::More` for PostgreSQL TAP tests +- **SSH Configuration**: Pre-configured SSH keys for multi-node testing scenarios +- **Network Tools**: `nc` (netcat), `bind-utils` (dig, nslookup) for connectivity testing +- **Process Tools**: `procps` for monitoring and debugging + +### 4. User Configuration + +- **Non-root user**: `pgedge` user with sudo privileges (password: `asdf`) +- **Home directory**: `/home/pgedge` +- **SSH keys**: Ed25519 key pair pre-generated and authorized for localhost +- **Working directory**: Set to `/home/pgedge` by default + +## Build Inputs + +### Required at Build Time + +- **Base Image**: `rockylinux:9` (pulled from Docker Hub) +- **Build Arguments**: + - `PGEDGE_USER` (default: `pgedge`) - Name of the non-root user + +### Downloaded During Build + +1. **System Packages** (~500MB compressed): + - Rocky Linux 9 base system updates + - Development Tools group install + - 40+ development packages and their dependencies + +2. **Perl Modules** (via CPAN): + - `Test::More` - PostgreSQL TAP test framework + +## Image Size and Optimization + +**Expected Size**: ~1.5-2GB uncompressed + +This large size is **intentional and appropriate** for a development/testing base image because: +- Contains complete compilation toolchain (LLVM alone is ~300MB) +- Includes headers and development libraries for all PostgreSQL features +- Prioritizes developer convenience over minimal size +- Enables building PostgreSQL with all features without additional dependencies + +**Optimization**: The image performs aggressive cleanup: +```dockerfile +dnf clean all +rm -rf /var/cache/dnf/* /tmp/* /var/tmp/* +rm -rf /root/.cpanm +``` + +## Usage Examples + +### Basic Usage: Interactive Development + +```bash +# Pull the image +docker pull ghcr.io/pgedge/base-test-image:latest + +# Start an interactive session +docker run -it --rm ghcr.io/pgedge/base-test-image:latest /bin/bash + +# Now inside the container as 'pgedge' user +git clone https://github.com/postgres/postgres.git +cd postgres +./configure --prefix=/home/pgedge/pg17 --enable-debug +make -j4 +make install +``` + +### Use as Base Image for Extension Development + +```dockerfile +FROM ghcr.io/pgedge/base-test-image:latest + +# Switch to root for installation +USER root + +# Copy your extension source +COPY . /home/pgedge/my-extension +RUN chown -R pgedge:pgedge /home/pgedge/my-extension + +# Clone and build PostgreSQL +RUN git clone --branch REL_16_STABLE --depth 1 \ + https://github.com/postgres/postgres /home/pgedge/postgres && \ + cd /home/pgedge/postgres && \ + ./configure --prefix=/home/pgedge/pg16 && \ + make -j4 && make install + +# Build your extension +WORKDIR /home/pgedge/my-extension +RUN make PG_CONFIG=/home/pgedge/pg16/bin/pg_config && \ + make install PG_CONFIG=/home/pgedge/pg16/bin/pg_config + +# Switch back to non-root +USER pgedge +``` + +### CI/CD Integration + +```yaml +# .github/workflows/test.yml +jobs: + test: + runs-on: ubuntu-latest + container: + image: ghcr.io/pgedge/base-test-image:latest + steps: + - uses: actions/checkout@v4 + - name: Build and test + run: | + cd /home/pgedge + make PG_CONFIG=/path/to/pg_config + make installcheck PG_CONFIG=/path/to/pg_config +``` + +## Platform Support + +The image is built as a **multiplatform manifest** supporting: +- **linux/amd64** - Intel/AMD x86_64 systems +- **linux/arm64** - Apple Silicon Macs (M1/M2/M3/M4), AWS Graviton + +Docker automatically selects the appropriate architecture when pulling the image: + +```bash +# Docker automatically selects correct architecture +docker pull ghcr.io/pgedge/base-test-image:latest + +# On Apple Silicon Mac → pulls linux/arm64 (native performance) +# On Intel/AMD → pulls linux/amd64 (native performance) +docker run -it ghcr.io/pgedge/base-test-image:latest /bin/bash +``` + +To explicitly pull a specific platform: + +```bash +# Force ARM64 variant +docker pull --platform linux/arm64 ghcr.io/pgedge/base-test-image:latest + +# Force AMD64 variant +docker pull --platform linux/amd64 ghcr.io/pgedge/base-test-image:latest +``` + +## Build Reproducibility + +Every image build includes comprehensive metadata for exact reproduction: + +### Build Information Embedded in Image + +Each image contains a `/etc/pgedge/build-info.txt` file with: +- Build timestamp (ISO 8601 format) +- Git commit SHA used to build the image +- Git branch name +- Rocky Linux version +- Exact reproduction commands + +View this information from any image: +```bash +docker run --rm ghcr.io/pgedge/base-test-image:latest cat /etc/pgedge/build-info.txt +``` + +### OCI Image Labels + +Images include standard OCI labels and custom metadata: +```bash +docker inspect ghcr.io/pgedge/base-test-image:latest | jq '.[0].Config.Labels' +``` + +Labels include: +- `org.opencontainers.image.created` - Build timestamp +- `org.opencontainers.image.revision` - Git commit SHA +- `org.opencontainers.image.source` - Source repository URL +- `com.pgedge.base-os.version` - Rocky Linux version +- `com.pgedge.git.branch` - Git branch name + +### Commit-Tagged Images + +Each build is tagged with both: +- `:latest` - Always points to the most recent build +- `:${GIT_COMMIT}` - Immutable tag referencing the exact git commit + +Pull a specific build: +```bash +# Replace with actual commit SHA from build output +docker pull ghcr.io/pgedge/base-test-image:a1b2c3d4e5f6... +``` + +### Reproducing a Build + +To reproduce an image exactly: + +1. **Find the git commit** from the image: + ```bash + docker inspect ghcr.io/pgedge/base-test-image:latest | \ + jq -r '.[0].Config.Labels."org.opencontainers.image.revision"' + ``` + +2. **Checkout that commit**: + ```bash + git clone https://github.com/pgedge/spock.git + cd spock + git checkout + ``` + +3. **Build with the same parameters**: + ```bash + docker build -f tests/docker/Dockerfile-base.el9 \ + --build-arg BUILD_DATE= \ + --build-arg GIT_COMMIT= \ + --build-arg GIT_BRANCH= \ + --build-arg ROCKYLINUX_VERSION= . + ``` + +The exact build command is also printed in `/etc/pgedge/build-info.txt` within the image. + +## Maintenance and Updates + +### Rebuild Strategy + +The base image should be rebuilt when: + +1. **Security Updates**: Critical CVEs in Rocky Linux 9 base packages +2. **Dependency Updates**: New versions of PostgreSQL require updated libraries +3. **Tool Updates**: Major LLVM or compiler version updates +4. **Monthly**: Regular rebuild for non-critical updates + +### Workflow + +The image is built using GitHub Actions workflow: +- **Workflow**: `.github/workflows/cache-base-image.yml` +- **Trigger**: Manual dispatch (`workflow_dispatch`) +- **Cache**: Uses GitHub Actions cache for layer caching +- **Registry**: Published to GitHub Container Registry (GHCR) + +To trigger a rebuild: +1. Navigate to Actions tab in GitHub +2. Select "Update base OS image" workflow +3. Click "Run workflow" + +## Downstream Images + +This base image is used by: + +1. **Dockerfile-step-1.el9**: Builds PostgreSQL with Spock patches and compiles Spock extension +2. **CI/CD pipelines**: Automated testing workflows +3. **Developer environments**: Local development containers + +## References + +- **Source**: `tests/docker/Dockerfile-base.el9` +- **Registry**: https://github.com/pgedge/spock/pkgs/container/base-test-image +- **Rocky Linux**: https://rockylinux.org/ +- **PostgreSQL Build Requirements**: https://www.postgresql.org/docs/current/install-requirements.html +- **Docker Multiplatform**: https://docs.docker.com/build/building/multi-platform/ + +--- + +**Maintained by**: pgEdge Team +**Contact**: andrei.lepikhov@pgedge.com +**License**: BSD