From 03370e0fe29201c897085d2d84ea9f965f76de1e Mon Sep 17 00:00:00 2001 From: guihkx <626206+guihkx@users.noreply.github.com> Date: Mon, 9 Sep 2024 04:07:29 -0300 Subject: [PATCH] chore(ci): Build/publish Docker images used to create DEB packages From now on, whenever we detect a modification to any of the 'ubuntu-*' Dockerfiles in the 'Dockerfiles' directory, a new image will be built first (with 'docker build'), and only then it will be used to actually build the app and generate DEB packages. If no changes to these Dockerfiles are detected, we'll simply 'docker pull' the already-existing image from the GitHub Container Registry to build the app, which will give us a faster build time. This new approach allows us to immediately test changes made to these Dockerfiles, without having to first build them locally, test them, push them to an OCI registry, and only then use them on GitHub Actions. Please note that these images will only be pushed to the GitHub Container Registry if _all_ three conditions below are met: - We _are not_ on a pull request - We _are_ on the master branch - We _are_ on the 'nuttyartist/notes' repository --- .github/workflows/linux.yml | 91 +++++++++++++++------------- Dockerfiles/ubuntu-20_04 | 23 +++++-- Dockerfiles/ubuntu-22_04 | 23 +++++-- Dockerfiles/ubuntu-23_10 | 23 +++++-- Dockerfiles/ubuntu_deb_entrypoint.sh | 91 ++++++++++++++++++++++++++++ 5 files changed, 192 insertions(+), 59 deletions(-) create mode 100755 Dockerfiles/ubuntu_deb_entrypoint.sh diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 6fce7331..3e358961 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -6,13 +6,15 @@ on: env: APP_ID: io.github.nuttyartist.notes + REGISTRY: ghcr.io jobs: deb: name: deb (${{ matrix.build-type }}, Qt ${{ matrix.qt-version-major }}, ${{ matrix.image }}) runs-on: ubuntu-latest - container: - image: zjeffer/notes:${{ matrix.image }} + permissions: + contents: read + packages: write strategy: fail-fast: false matrix: @@ -30,59 +32,45 @@ jobs: qt-version-major: 6 build-type: release steps: - - name: Setup git configuration - # workaround for "detected dubious ownership in repository" git error: https://github.com/actions/checkout/issues/1169 - run: git config --global --add safe.directory "${PWD}" - - name: Checkout code uses: actions/checkout@v4 with: submodules: recursive - - name: Set up variables - shell: bash - id: vars + - name: Check if Dockerfile has been modified + id: docker_image run: | - set -x - distro_id=$(grep -oPm1 '^ID="?\K[^"]+' /etc/os-release) - if [ -z "${distro_id}" ] + set -ex + git remote add upstream https://github.com/nuttyartist/notes.git + git fetch --depth=1 upstream master + if git diff --compact-summary --exit-code upstream/master -- 'Dockerfiles/${{ matrix.image }}' then - echo 'Fatal: Failed to extract distro ID from /etc/os-release' - exit 1 - fi - distro_codename=$(grep -oPm1 '^VERSION_CODENAME="?\K[^"]+' /etc/os-release) - if [ -z "${distro_codename}" ] - then - echo 'Fatal: Failed to extract distro codename from /etc/os-release' - exit 1 + needs_rebuild=false + else + needs_rebuild=true fi - echo "distro_name=${distro_id}-${distro_codename}" >> "${GITHUB_OUTPUT}" + echo "needs_rebuild=${needs_rebuild}" >> "${GITHUB_OUTPUT}" + + - name: Build and tag Docker image + if: steps.docker_image.outputs.needs_rebuild == 'true' + run: docker build -f 'Dockerfiles/${{ matrix.image }}' -t '${{ env.REGISTRY }}/nuttyartist/notes:${{ matrix.image }}' . - name: Setup GCC problem matcher uses: ammaraskar/gcc-problem-matcher@0.3.0 - - name: Build (${{ matrix.build-type }}) - env: - VERBOSE: 1 - run: | - cmake --warn-uninitialized --warn-unused-vars \ - -B build \ - -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ - -DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DPRO_VERSION=OFF - cmake --build build --parallel $(nproc) + - name: Build, package and lint + run: docker run --rm -v $(pwd):/src -t '${{ env.REGISTRY }}/nuttyartist/notes:${{ matrix.image }}' -t ${{ matrix.build-type }} ${{ github.ref_type == 'tag' && '-n' || ' ' }} - - name: Create deb package + - name: Grab distro name + id: vars run: | - cd build - cpack -G DEB + set -ex + echo "distro_name=$(cat build/distro_name)" >> "${GITHUB_OUTPUT}" - name: Grab deb package name id: deb - shell: bash run: | - set -x + set -ex if ! path=$(find build/ -maxdepth 1 -name '*.deb' -print -quit) then echo 'Fatal: Unable to find deb package' @@ -91,10 +79,6 @@ jobs: echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}" echo "path=${path}" >> "${GITHUB_OUTPUT}" - - name: Run lintian - run: | - lintian '${{ steps.deb.outputs.path }}' - - name: Upload deb package uses: actions/upload-artifact@v4 with: @@ -102,6 +86,31 @@ jobs: name: ${{ steps.deb.outputs.name }}-qt${{ matrix.qt-version-major }}-${{ steps.vars.outputs.distro_name }}-${{ matrix.build-type }} path: ${{ steps.deb.outputs.path }} + - name: Login to GitHub Container Registry + if: ${{ steps.docker_image.outputs.needs_rebuild == 'true' && github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' && github.ref_name == 'master' }} # FIXME + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + if: ${{ steps.docker_image.outputs.needs_rebuild == 'true' && github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' && github.ref_name == 'master' }} # FIXME + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/nuttyartist/notes:${{ matrix.image }} + + - name: Build and push Docker image + if: ${{ steps.docker_image.outputs.needs_rebuild == 'true' && github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' && github.ref_name == 'master' }} # FIXME + uses: docker/build-push-action@v6 + env: + DOCKER_BUILD_SUMMARY: false + with: + file: Dockerfiles/${{ matrix.image }} + push: true + tags: ${{ env.REGISTRY }}/nuttyartist/notes:${{ matrix.image }} + rpm: name: rpm (${{ matrix.build-type }}, Qt ${{ matrix.qt-version-major }}, ${{ matrix.image }}) runs-on: ubuntu-latest diff --git a/Dockerfiles/ubuntu-20_04 b/Dockerfiles/ubuntu-20_04 index b8639837..1e69333d 100644 --- a/Dockerfiles/ubuntu-20_04 +++ b/Dockerfiles/ubuntu-20_04 @@ -1,10 +1,21 @@ +# vim: set syntax=dockerfile: FROM ubuntu:20.04 -# fix for tzdata asking for input +LABEL org.opencontainers.image.description="Base image used to build and DEB-package Notes on Ubuntu 20.04" + +# Prevent tzdata from asking for input. ENV DEBIAN_FRONTEND=noninteractive -RUN apt update && \ - apt install -y git sudo \ - gcc cmake lintian \ - qtbase5-private-dev qtdeclarative5-dev -RUN apt clean \ No newline at end of file +# Install dependencies. +RUN apt-get update && \ + apt-get install -y --no-install-recommends cmake git g++ lintian make qtbase5-private-dev qtdeclarative5-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists + +# Prevent a fatal error from git: "detected dubious ownership in repository at '/src'". +RUN git config --global --add safe.directory /src + +ADD --chmod=755 ./Dockerfiles/ubuntu_deb_entrypoint.sh /usr/bin/entrypoint.sh + +WORKDIR /src +ENTRYPOINT ["entrypoint.sh"] diff --git a/Dockerfiles/ubuntu-22_04 b/Dockerfiles/ubuntu-22_04 index 6f7588c9..b45213cb 100644 --- a/Dockerfiles/ubuntu-22_04 +++ b/Dockerfiles/ubuntu-22_04 @@ -1,10 +1,21 @@ +# vim: set syntax=dockerfile: FROM ubuntu:22.04 -# fix for tzdata asking for input +LABEL org.opencontainers.image.description="Base image used to build and DEB-package Notes on Ubuntu 22.04" + +# Prevent tzdata from asking for input. ENV DEBIAN_FRONTEND=noninteractive -RUN apt update && \ - apt install -y git sudo \ - gcc cmake lintian \ - qt6-base-private-dev qt6-declarative-dev libgl-dev -RUN apt clean +# Install dependencies. +RUN apt-get update && \ + apt-get install -y --no-install-recommends cmake git g++ libgl-dev libqt6opengl6-dev lintian qt6-base-private-dev qt6-declarative-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists + +# Prevent a fatal error from git: "detected dubious ownership in repository at '/src'". +RUN git config --global --add safe.directory /src + +ADD --chmod=755 ./Dockerfiles/ubuntu_deb_entrypoint.sh /usr/bin/entrypoint.sh + +WORKDIR /src +ENTRYPOINT ["entrypoint.sh"] diff --git a/Dockerfiles/ubuntu-23_10 b/Dockerfiles/ubuntu-23_10 index 9d7d9fe1..40b197ed 100644 --- a/Dockerfiles/ubuntu-23_10 +++ b/Dockerfiles/ubuntu-23_10 @@ -1,10 +1,21 @@ +# vim: set syntax=dockerfile: FROM ubuntu:23.10 -# fix for tzdata asking for input +LABEL org.opencontainers.image.description="Base image used to build and DEB-package Notes on Ubuntu 23.10" + +# Prevent tzdata from asking for input. ENV DEBIAN_FRONTEND=noninteractive -RUN apt update && \ - apt install -y git sudo \ - gcc cmake lintian \ - qt6-base-private-dev qt6-declarative-dev libgl-dev -RUN apt clean \ No newline at end of file +# Install dependencies. +RUN apt-get update && \ + apt-get install -y --no-install-recommends cmake git g++ libgl-dev lintian qt6-base-private-dev qt6-declarative-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists + +# Prevent a fatal error from git: "detected dubious ownership in repository at '/src'". +RUN git config --global --add safe.directory /src + +ADD --chmod=755 ./Dockerfiles/ubuntu_deb_entrypoint.sh /usr/bin/entrypoint.sh + +WORKDIR /src +ENTRYPOINT ["entrypoint.sh"] diff --git a/Dockerfiles/ubuntu_deb_entrypoint.sh b/Dockerfiles/ubuntu_deb_entrypoint.sh new file mode 100755 index 00000000..1039f8f7 --- /dev/null +++ b/Dockerfiles/ubuntu_deb_entrypoint.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +# Note: This build script is meant to be used within the container image created by 'ubuntu-*' Dockerfiles. + +set -euo pipefail + +# Script options: +# +# -d : Set build directory (overrides $BUILD_DIR below). +# -t : Set build type (overrides $BUILD_TYPE below). +# -p: Enable 'Pro' features (overrides $PRO_VERSION below). +# -u: Enable the update checker feature (overrides $UPDATE_CHECKER below). +# -n: Do not add the current git revision to the app's version (overrides $GIT_REVISION below). +# -c : Options passed to CMake's configure stage (overrides $CMAKE_CONFIG_OPTIONS below). +# -b Options passed to CMake's build stage (overrides $CMAKE_BUILD_OPTIONS below). +# -o Options passed to CPack (overrides $CPACK_OPTIONS below). + +# Hint: Pre-existing environment variables with the same name as the variables below will take precedence. +BUILD_DIR="${BUILD_DIR:-build}" +BUILD_TYPE="${BUILD_TYPE:-release}" +PRO_VERSION="${PRO_VERSION:-OFF}" +UPDATE_CHECKER="${UPDATE_CHECKER:-OFF}" +GIT_REVISION="${GIT_REVISION:-ON}" +CMAKE_CONFIG_OPTIONS="${CMAKE_CONFIG_OPTIONS:---warn-uninitialized -B ${BUILD_DIR} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DGIT_REVISION=${GIT_REVISION} -DCMAKE_INSTALL_PREFIX=/usr -DPRO_VERSION=${PRO_VERSION} -DUPDATE_CHECKER=${UPDATE_CHECKER}}" +CMAKE_BUILD_OPTIONS="${CMAKE_BUILD_OPTIONS:---build build --parallel $(nproc)}" +CPACK_OPTIONS="${CPACK_OPTIONS:--G DEB}" + +SCRIPT_NAME="$(basename "${0}")" + +function msg() { + echo -e "\033[1m[${SCRIPT_NAME}] ${1}\033[0m" +} + +while getopts 'd:t:pnc:b:o:' OPTION; do + case "${OPTION}" in + d) + msg "Note: Overriding build directory: '${BUILD_DIR}' -> '${OPTARG}'" + BUILD_DIR="${OPTARG}" + ;; + t) + msg "Note: Overriding build type: '${BUILD_TYPE}' -> '${OPTARG}'" + BUILD_TYPE="${OPTARG}" + ;; + p) + msg "Note: Enabling 'Pro' features." + PRO_FEATURES='ON' + ;; + u) + msg "Note: Enabling the update checker feature." + UPDATE_CHECKER='ON' + ;; + n) + msg "Note: Not adding git revision to the app's version." + GIT_REVISION='OFF' + ;; + c) + msg "Note: Overriding CMake configure options: '${CMAKE_CONFIG_OPTIONS}' -> '${OPTARG}'" + CMAKE_CONFIG_OPTIONS="${OPTARG}" + ;; + b) + msg "Note: Overriding CMake build options: '${CMAKE_BUILD_OPTIONS}' -> '${OPTARG}'" + CMAKE_BUILD_OPTIONS="${OPTARG}" + ;; + o) + msg "Note: Overriding CPack options: '${CPACK_OPTIONS}' -> '${OPTARG}'" + CPACK_OPTIONS="${OPTARG}" + ;; + esac +done + +set -x + +# Needed for GitHub Actions CI/CD. +msg "Writing distro name to '${BUILD_DIR}/distro_name'..." +mkdir -p "${BUILD_DIR}" +distro_id=$(grep -oPm1 '^ID="?\K[^"]+' /etc/os-release) +distro_codename=$(grep -oPm1 '^VERSION_CODENAME="?\K[^"]+' /etc/os-release || echo '') +echo "${distro_id}${distro_codename:+-"$distro_codename"}" >"${BUILD_DIR}/distro_name" + +msg 'Running CMake (configure)...' +cmake ${CMAKE_CONFIG_OPTIONS} + +msg 'Running CMake (build)...' +cmake ${CMAKE_BUILD_OPTIONS} + +msg 'Running CPack...' +cd "${BUILD_DIR}" +cpack ${CPACK_OPTIONS} + +msg 'Running lintian...' +lintian *.deb