Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use docker image build cache in github actions #764

Draft
wants to merge 8 commits into
base: 3.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 31 additions & 6 deletions .github/workflows/deliver.yml
Expand Up @@ -34,10 +34,23 @@ jobs:
run: |
echo "FARMOS_VERSION=${GITHUB_HEAD_REF}" >> $GITHUB_ENV
echo "FARMOS_REPO=${{ github.event.pull_request.head.repo.full_name }}" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and save farmOS Docker image
run: |
docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:3.x docker
docker save farmos/farmos:3.x > /tmp/farmos.tar
uses: docker/build-push-action@v5
with:
push: false
context: docker
build-args: |
FARMOS_REPO=https://github.com/${{ env.FARMOS_REPO }}
FARMOS_VERSION=${{ env.FARMOS_VERSION }}
GIT_COMMIT=${{ github.sha }}
tags: farmos/farmos:3.x
cache-from: type=gha,scope=prod
cache-to: type=gha,scope=prod
outputs: type=docker,dest=/tmp/farmos.tar
- name: Cache farmOS Docker image
uses: actions/cache@v3
with:
Expand All @@ -47,9 +60,21 @@ jobs:
# but notably it does NOT override the default PROJECT_VERSION, so the
# farmOS Composer project 3.x branch is always used.
- name: Build and save farmOS dev Docker image
run: |
docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:3.x-dev docker/dev
docker save farmos/farmos:3.x-dev > /tmp/farmos-dev.tar
uses: docker/build-push-action@v5
with:
push: false
context: docker
target: dev
build-args: |
FARMOS_REPO=https://github.com/${{ env.FARMOS_REPO }}
FARMOS_VERSION=${{ env.FARMOS_VERSION }}
GIT_COMMIT=${{ github.sha }}
tags: farmos/farmos:3.x-dev
cache-from: |
type=gha,scope=prod
type=gha,scope=dev
cache-to: type=gha,scope=dev
outputs: type=docker,dest=/tmp/farmos-dev.tar
- name: Cache farmOS dev Docker image
uses: actions/cache@v3
with:
Expand Down
139 changes: 111 additions & 28 deletions docker/Dockerfile
@@ -1,7 +1,14 @@
# Use the official Drupal 10 image to build GEOS PHP extension.
FROM drupal:10.1 as php-dependencies
# Use the official Drupal 10 as base image.
FROM drupal:10.1 as baseimage

# Define common paths.
ENV FARMOS_PATH=/var/farmOS
ENV DRUPAL_PATH=/opt/drupal

##
# Build PHP extensions, GEOS and bcmath.
FROM baseimage as php-dependencies

# Build and install the GEOS PHP extension.
# See https://git.osgeo.org/gitea/geos/php-geos
ARG PHP_GEOS_VERSION=e77d5a16abbf89a59d947d1fe49381a944762c9d
ADD https://github.com/libgeos/php-geos/archive/${PHP_GEOS_VERSION}.tar.gz /opt/php-geos.tar.gz
Expand All @@ -17,51 +24,127 @@ RUN apt-get update && apt-get install -y libgeos-dev \
# Install the BCMath PHP extension.
RUN docker-php-ext-install bcmath

# Inherit from the official Drupal 10 image.
FROM drupal:10.1
# Setup dependencies and sources for composer installations.
FROM baseimage as composer-file

# Set the farmOS and composer project repository URLs and versions.
ARG FARMOS_REPO=https://github.com/farmOS/farmOS.git
ARG FARMOS_VERSION=3.x
ARG PROJECT_REPO=https://github.com/farmOS/composer-project.git
ARG PROJECT_VERSION=3.x
ARG PROJECT_REPO=https://github.com/farmOS/composer-project/raw/${PROJECT_VERSION}/composer.json

# Set the COMPOSER_MEMORY_LIMIT environment variable to unlimited.
ENV COMPOSER_MEMORY_LIMIT=-1
# Allow root to install plugins.
ENV COMPOSER_ALLOW_SUPERUSER=1
ENV COMPOSER_NO_INTERACTION=1

# Install apt dependencies.
RUN apt-get update && apt-get install -y --no-install-recommends\
# Install git and unzip (needed by Composer).
git unzip

# Add the build-farmOS.sh script.
COPY build-farmOS.sh /usr/local/bin/

# Setup composer file for non interactive installation.
WORKDIR ${FARMOS_PATH}
RUN build-farmOS.sh

##
# Create layer with farmOS sources.
FROM composer-file as farmos-sources

# Declare the git commit hash argument used for build cache invalidation between
# different commits on the same branch in GitHub actions.
ARG GIT_COMMIT=unknown

# Install sources.
RUN composer install --no-dev

# Set the version in farm.info.yml.
RUN sed -i "s|version: 3.x|version: ${FARMOS_VERSION}|g" ${FARMOS_PATH}/web/profiles/farm/farm.info.yml

##
# Create layer with farmOS dev sources.
FROM farmos-sources as farmos-dev-sources

# Install sources.
RUN composer update

##
# Dependencies layer.
FROM baseimage as farmos-baseimage

# Set Apache ServerName directive globally to suppress AH00558 message.
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf

# Install and enable geos.
# Enable PHP dependencies.
COPY --from=php-dependencies /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
RUN docker-php-ext-enable geos bcmath

# Add custom PHP configurations.
COPY conf.d/ /usr/local/etc/php/conf.d

# Install apt dependencies.
RUN apt-get update && apt-get install -y \
# Install git and unzip (needed by Composer).
git unzip \
# Install apt dependencies and clean up.
RUN apt-get update && apt-get install -y --no-install-recommends\
# Install postgresql-client so Drush can connect to the database.
postgresql-client \
# Install libgeos-c1v5 so geos php extension can use libgeos_c.so.1.
libgeos-c1v5 \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean

# Set the COMPOSER_MEMORY_LIMIT environment variable to unlimited.
ENV COMPOSER_MEMORY_LIMIT=-1

# Add the build-farmOS.sh script.
COPY build-farmOS.sh /usr/local/bin/
RUN chmod a+x /usr/local/bin/build-farmOS.sh

# Build the farmOS codebase in /var/farmoS with the --no-dev flag.
# Change the ownership of the sites directory and copy the farmOS codebase into /opt/drupal.
RUN mkdir /var/farmOS \
&& /usr/local/bin/build-farmOS.sh --no-dev \
&& chown -R www-data:www-data /var/farmOS/web/sites \
&& rm -r /opt/drupal && cp -rp /var/farmOS /opt/drupal
# Install git and unzip (needed by Composer).
git unzip \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean \
# Clean up ${DRUPAL_PATH}.
&& rm -r ${DRUPAL_PATH} \
&& mkdir ${DRUPAL_PATH}

# Set the entrypoint.
COPY docker-entrypoint.sh /usr/local/bin/
COPY --chown=www-data docker-entrypoint.sh /usr/local/bin/

# Set the working directory, entrypoint and command.
WORKDIR ${DRUPAL_PATH}
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["apache2-foreground"]

##
# Development base image.
FROM farmos-baseimage as farmos-dev-baseimage

# Change the user/group IDs of www-data inside the image to match the ID of the
# developer's user on the host machine. This allows Composer to create files
# owned by www-data inside the container, while keeping those files editable by
# the developer outside of the container.
# This defaults to 1000, based on the assumption that the developer is running
# as UID 1000 on the host machine. It can be overridden at image build time with:
# --build-arg WWW_DATA_ID=$(id -u)
ARG WWW_DATA_ID=1000
RUN usermod -u ${WWW_DATA_ID} www-data && groupmod -g ${WWW_DATA_ID} www-data

# Install and configure XDebug.
RUN yes | pecl install xdebug \
&& docker-php-ext-enable xdebug

# Add opcache revalidation frequency configuration.
COPY dev/conf.d/ /usr/local/etc/php/conf.d

# Add Configurations for PHP CodeSniffer, PHPStan
COPY --chown=www-data:www-data ./dev/files/ ${FARMOS_PATH}

##
# Development image.
FROM farmos-dev-baseimage as dev

# Add farmOS dev sources.
COPY --from=farmos-dev-sources --chown=www-data:www-data ${FARMOS_PATH} ${FARMOS_PATH}

# Configure PHPUnit.
RUN ${FARMOS_PATH}/phpunit.sh

##
# Production image.
FROM farmos-baseimage

# Add farmOS sources.
COPY --from=farmos-sources --chown=www-data:www-data ${FARMOS_PATH} ${DRUPAL_PATH}
35 changes: 7 additions & 28 deletions docker/build-farmOS.sh
100644 → 100755
Expand Up @@ -2,26 +2,18 @@
set -e

###
# This script will build the farmOS codebase in /var/farmOS.
# This script will build the farmOS codebase in ${FARMOS_PATH},
# by default it is /var/farmOS.
###

# If /var/farmOS is not empty, bail.
if [ "$(ls -A /var/farmOS/)" ]; then
# If ${FARMOS_PATH} is not empty, bail.
if [ "$(ls -A ${FARMOS_PATH})" ]; then
echo "The ${FARMOS_PATH} is not empty, terminate."
exit 1
fi

# Make /var/farmOS the working directory.
cd /var/farmOS

# Generate an empty Composer project project and checkout a specific version.
git clone ${PROJECT_REPO} project
mv project/.git ./.git
rm -rf project
git checkout ${PROJECT_VERSION}
git reset --hard

# Create a temporary Composer cache directory.
export COMPOSER_HOME="$(mktemp -d)"
# Fetch composer template
curl -L ${PROJECT_REPO} -o composer.json

# If FARMOS_VERSION is a valid semantic versioning string, we assume that it is
# a tagged version.
Expand Down Expand Up @@ -61,16 +53,3 @@ allowedPlugins=(
for plugin in ${allowedPlugins[@]}; do
composer config --no-plugins allow-plugins.$plugin true
done

# Run composer install with optional arguments passed into this script.
if [ $# -eq 0 ]; then
composer install
else
composer install "$*"
fi

# Set the version in farm.info.yml.
sed -i "s|version: 3.x|version: ${FARMOS_VERSION}|g" /var/farmOS/web/profiles/farm/farm.info.yml

# Remove the Composer cache directory.
rm -rf "$COMPOSER_HOME"
63 changes: 0 additions & 63 deletions docker/dev/Dockerfile

This file was deleted.

19 changes: 19 additions & 0 deletions docker/dev/files/phpunit.sh
@@ -0,0 +1,19 @@
#!/usr/bin/env sh

cp -p ${FARMOS_PATH}/web/core/phpunit.xml.dist ${FARMOS_PATH}/phpunit.xml
sed -i 's|bootstrap="tests/bootstrap.php"|bootstrap="web/core/tests/bootstrap.php"|g' ${FARMOS_PATH}/phpunit.xml
sed -i '/failOnWarning="true"/a \ failOnIncomplete="true"' ${FARMOS_PATH}/phpunit.xml
sed -i '/failOnWarning="true"/a \ failOnSkipped="true"' ${FARMOS_PATH}/phpunit.xml
sed -i 's|name="SIMPLETEST_BASE_URL" value=""|name="SIMPLETEST_BASE_URL" value="http://www"|g' ${FARMOS_PATH}/phpunit.xml
sed -i 's|name="SIMPLETEST_DB" value=""|name="SIMPLETEST_DB" value="pgsql://farm:farm@db/farm"|g' ${FARMOS_PATH}/phpunit.xml
sed -i 's|name="BROWSERTEST_OUTPUT_DIRECTORY" value=""|name="BROWSERTEST_OUTPUT_DIRECTORY" value="/var/www/html/sites/simpletest/browser_output"|g' ${FARMOS_PATH}/phpunit.xml
sed -i 's|name="MINK_DRIVER_ARGS_WEBDRIVER" value='\'''\''|name="MINK_DRIVER_ARGS_WEBDRIVER" value='\''["chrome", { "chromeOptions": { "w3c": false, "args": ["--disable-gpu","--headless", "--no-sandbox"] } }, "http://chrome:4444/wd/hub"]'\''|g' ${FARMOS_PATH}/phpunit.xml
sed -i 's|\./|\./web/core/|g' ${FARMOS_PATH}/phpunit.xml
sed -i 's|\.\./web/core/|\./web/|g' ${FARMOS_PATH}/phpunit.xml
sed -i 's| </php>| <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>'"\n"' </php>|g' ${FARMOS_PATH}/phpunit.xml

# Create output directory for phpunit tests and permissions for testing user.
mkdir -p ${FARMOS_PATH}/web/sites/simpletest/browser_output
chown -R www-data:www-data ${FARMOS_PATH}/web/sites/simpletest

rm ${FARMOS_PATH}/phpunit.sh
8 changes: 4 additions & 4 deletions docker/docker-entrypoint.sh
Expand Up @@ -8,15 +8,15 @@ set -e
###

# If the Drupal directory is empty, populate it from pre-built files.
if [ -d /opt/drupal ] && ! [ "$(ls -A /opt/drupal/)" ]; then
if [ -d ${DRUPAL_PATH} ] && ! [ "$(ls -A ${DRUPAL_PATH}/)" ]; then
echo "farmOS codebase not detected. Copying from pre-built files in the Docker image."
cp -rp /var/farmOS/. /opt/drupal
cp -rp ${FARMOS_PATH}/. ${DRUPAL_PATH}
fi

# If the sites directory is empty, populate it from pre-built files.
if [ -d /opt/drupal/web/sites ] && ! [ "$(ls -A /opt/drupal/web/sites/)" ]; then
if [ -d ${DRUPAL_PATH}/web/sites ] && ! [ "$(ls -A ${DRUPAL_PATH}/web/sites/)" ]; then
echo "farmOS sites directory not detected. Copying from pre-built files in the Docker image."
cp -rp /var/farmOS/web/sites/. /opt/drupal/web/sites
cp -rp ${FARMOS_PATH}/web/sites/. ${DRUPAL_PATH}/web/sites
fi

if [ -n "$FARMOS_FS_READY_SENTINEL_FILENAME" ]; then
Expand Down
9 changes: 8 additions & 1 deletion docs/development/environment/docker.md
Expand Up @@ -17,7 +17,9 @@ Available arguments and their default values are described below:
check out.
- Default: `3.x`

The `3.x-dev` image also provides the following:
## Development image

The `3.x-dev` image also provides the following build arguments:

- `WWW_DATA_ID` - The ID to use for the `www-data` user and group inside the
image. Setting this to the ID of the developer's user on the host machine
Expand All @@ -26,3 +28,8 @@ The `3.x-dev` image also provides the following:
container. If your user ID is not `1000`, build the image with:
`--build-arg WWW_DATA_ID=$(id -u)`
- Default: `1000`

To build the development image, you will have to define the target dev,
for example:

`docker build --build-arg WWW_DATA_ID=$(id -u) -t farmos/farmos:3.x-dev --target dev docker`