Instead of using a full image name, use the repo and version to build the image to pull from. Removes building of the frontend for multiple platforms

This commit is contained in:
Trenton Holmes 2022-04-21 15:47:50 -07:00 committed by Trenton Holmes
parent 6179ca5668
commit d19015579c
No known key found for this signature in database
GPG Key ID: 4815A6E23A56B8D1
4 changed files with 67 additions and 63 deletions

View File

@ -63,10 +63,6 @@ jobs:
- -
name: Checkout name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
-
name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v5
- -
name: Login to Github Container Registry name: Login to Github Container Registry
uses: docker/login-action@v1 uses: docker/login-action@v1
@ -123,16 +119,14 @@ jobs:
name: Setup frontend image name: Setup frontend image
id: frontend-setup id: frontend-setup
run: | run: |
frontend_image=ghcr.io/${{ github.repository }}/ngx-frontend:${{ steps.branch-name.outputs.current_branch }} build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py frontend)
echo ${frontend_image} echo ${build_json}
echo ::set-output name=frontend-image-tag::${frontend_image} echo ::set-output name=frontend-json::${build_json}
outputs: outputs:
frontend-image-tag: ${{ steps.frontend-setup.outputs.frontend-image-tag }}
qpdf-json: ${{ steps.qpdf-setup.outputs.qpdf-json }} qpdf-json: ${{ steps.qpdf-setup.outputs.qpdf-json }}
pikepdf-json: ${{ steps.pikepdf-setup.outputs.pikepdf-json }} pikepdf-json: ${{ steps.pikepdf-setup.outputs.pikepdf-json }}
@ -141,6 +135,8 @@ jobs:
jbig2enc-json: ${{ steps.jbig2enc-setup.outputs.jbig2enc-json}} jbig2enc-json: ${{ steps.jbig2enc-setup.outputs.jbig2enc-json}}
frontend-json: ${{ steps.frontend-setup.outputs.frontend-json}}
build-qpdf-debs: build-qpdf-debs:
name: qpdf name: qpdf
needs: needs:
@ -185,14 +181,15 @@ jobs:
dockerfile: ./docker-builders/Dockerfile.pikepdf dockerfile: ./docker-builders/Dockerfile.pikepdf
build-json: ${{ needs.prepare-docker-build.outputs.pikepdf-json }} build-json: ${{ needs.prepare-docker-build.outputs.pikepdf-json }}
build-args: | build-args: |
QPDF_BASE_IMAGE=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).image_tag }} REPO=${{ github.repository }}
QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }}
GIT_TAG=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).git_tag }} GIT_TAG=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).git_tag }}
VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }} VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }}
build-frontend: build-frontend:
name: Compile frontend name: Compile frontend
concurrency: concurrency:
group: ${{ github.workflow }}-build-frontend-${{ github.ref }} group: ${{ github.workflow }}-build-frontend-${{ github.ref_name }}
cancel-in-progress: false cancel-in-progress: false
needs: needs:
- prepare-docker-build - prepare-docker-build
@ -222,7 +219,7 @@ jobs:
id: build-skip-check id: build-skip-check
# Skip building the frontend if the tag exists and no src-ui files changed # Skip building the frontend if the tag exists and no src-ui files changed
run: | run: |
if ! docker manifest inspect ${{ needs.prepare-docker-build.outputs.frontend-image-tag }} &> /dev/null ; then if ! docker manifest inspect ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }} &> /dev/null ; then
echo "Build required, no existing image" echo "Build required, no existing image"
echo ::set-output name=frontend-build-needed::true echo ::set-output name=frontend-build-needed::true
elif ${{ steps.changed-files-specific.outputs.any_changed }} == 'true' ; then elif ${{ steps.changed-files-specific.outputs.any_changed }} == 'true' ; then
@ -247,15 +244,18 @@ jobs:
with: with:
context: . context: .
file: ./docker-builders/Dockerfile.frontend file: ./docker-builders/Dockerfile.frontend
tags: ${{ needs.prepare-docker-build.outputs.frontend-image-tag }} tags: ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }}
platforms: linux/amd64,linux/arm64,linux/arm/v7 # The compilation is identical between different platforms
# The buildx and QEMU setup is left, just in case that ever changes
# But the platform is set to the runner's native for speedup
platforms: linux/amd64
push: true push: true
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
- -
name: Export frontend artifact from docker name: Export frontend artifact from docker
run: | run: |
docker create --name frontend-extract ${{ needs.prepare-docker-build.outputs.frontend-image-tag }} docker create --name frontend-extract ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }}
docker cp frontend-extract:/src/src/documents/static/frontend src/documents/static/frontend/ docker cp frontend-extract:/src/src/documents/static/frontend src/documents/static/frontend/
- -
name: Upload frontend artifact name: Upload frontend artifact
@ -271,7 +271,7 @@ jobs:
cancel-in-progress: true cancel-in-progress: true
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
concurrency: concurrency:
group: ${{ github.workflow }}-build-docker-image-${{ github.ref }} group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }}
cancel-in-progress: true cancel-in-progress: true
needs: needs:
- prepare-docker-build - prepare-docker-build
@ -317,11 +317,12 @@ jobs:
tags: ${{ steps.docker-meta.outputs.tags }} tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }} labels: ${{ steps.docker-meta.outputs.labels }}
build-args: | build-args: |
JBIG2ENC_BASE_IMAGE=${{ fromJSON(needs.prepare-docker-build.outputs.jbig2enc-json).image_tag }} REPO=${{ github.repository }}
QPDF_BASE_IMAGE=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).image_tag }} JBIG2ENC_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.jbig2enc-json).version }}
PIKEPDF_BASE_IMAGE=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).image_tag }} QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }}
PSYCOPG2_BASE_IMAGE=${{ fromJSON(needs.prepare-docker-build.outputs.psycopg2-json).image_tag }} PIKEPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }}
FRONTEND_BASE_IMAGE=${{ needs.prepare-docker-build.outputs.frontend-image-tag }} PSYCOPG2_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.psycopg2-json).version }}
FRONTEND_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).version }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
- -
@ -401,7 +402,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: needs:
- build-release - build-release
if: contains(github.ref, 'refs/tags/ngx-') || contains(github.ref, 'refs/tags/beta-') if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'ngx-') || startsWith(github.ref_name, 'beta-'))
steps: steps:
- -
name: Download release artifact name: Download release artifact

View File

@ -1,16 +1,19 @@
# Default to pulling from the main repo registry when manually building
ARG REPO="paperless-ngx/paperless-ngx"
# These are all built previously in the pipeline # These are all built previously in the pipeline
# They provide either a .deb, .whl or whatever npm outputs # They provide either a .deb, .whl or whatever npm outputs
ARG JBIG2ENC_BASE_IMAGE ARG JBIG2ENC_VERSION
ARG QPDF_BASE_IMAGE ARG QPDF_VERSION
ARG PIKEPDF_BASE_IMAGE ARG PIKEPDF_VERSION
ARG PSYCOPG2_BASE_IMAGE ARG PSYCOPG2_VERSION
ARG FRONTEND_BASE_IMAGE ARG FRONTEND_VERSION
FROM ${JBIG2ENC_BASE_IMAGE} AS jbig2enc-builder FROM ghcr.io/${REPO}/builder/jbig2enc:${JBIG2ENC_VERSION} as jbig2enc-builder
FROM ${QPDF_BASE_IMAGE} as qpdf-builder FROM ghcr.io/${REPO}/builder/qpdf:${QPDF_VERSION} as qpdf-builder
FROM ${PIKEPDF_BASE_IMAGE} as pikepdf-builder FROM ghcr.io/${REPO}/builder/pikepdf:${PIKEPDF_VERSION} as pikepdf-builder
FROM ${PSYCOPG2_BASE_IMAGE} as psycopg2-builder FROM ghcr.io/${REPO}/builder/psycopg2:${PSYCOPG2_VERSION} as psycopg2-builder
FROM ${FRONTEND_BASE_IMAGE} as compile-frontend FROM ghcr.io/${REPO}/builder/frontend:${FRONTEND_VERSION} as compile-frontend
FROM python:3.9-slim-bullseye as main-app FROM python:3.9-slim-bullseye as main-app

View File

@ -1,11 +1,15 @@
# This Dockerfile builds the pikepdf wheel # This Dockerfile builds the pikepdf wheel
# Inputs: # Inputs:
# - QPDF_BASE_IMAGE - The image to copy built qpdf .ded files from # - REPO - Docker repository to pull qpdf from
# - QPDF_VERSION - The image qpdf version to copy .deb files from
# - GIT_TAG - The Git tag to clone and build from # - GIT_TAG - The Git tag to clone and build from
# - VERSION - Used to force the built pikepdf version to match # - VERSION - Used to force the built pikepdf version to match
ARG QPDF_BASE_IMAGE # Default to pulling from the main repo registry when manually building
FROM ${QPDF_BASE_IMAGE} as qpdf-builder ARG REPO="paperless-ngx/paperless-ngx"
ARG QPDF_VERSION
FROM ghcr.io/${REPO}/builder/qpdf:${QPDF_VERSION} as qpdf-builder
# This does nothing, except provide a name for a copy below # This does nothing, except provide a name for a copy below

View File

@ -1,8 +1,18 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
This is a helper script to either parse the JSON of the Pipfile.lock This is a helper script for the mutli-stage Docker image builder.
or otherwise return a JSON object detailing versioning and image tags It provides a single point of configuration for package version control.
for the packages we build seperately, then copy into the final Docker image The output JSON object is used by the CI workflow to determine what versions
to build and pull into the final Docker image.
Python package information is obtained from the Pipfile.lock. As this is
kept updated by dependabot, it usually will need no further configuration.
The sole exception currently is pikepdf, which has a dependency on qpdf,
and is configured here to use the latest version of qpdf built by the workflow.
Other package version information is configured directly below, generally by
setting the version and Git information, if any.
""" """
import argparse import argparse
import json import json
@ -14,11 +24,13 @@ CONFIG: Final = {
# All packages need to be in the dict, even if not configured further # All packages need to be in the dict, even if not configured further
# as it is used for the possible choices in the argument # as it is used for the possible choices in the argument
"psycopg2": {}, "psycopg2": {},
"frontend": {},
# Most information about Python packages comes from the Pipfile.lock # Most information about Python packages comes from the Pipfile.lock
# Excpetion being pikepdf, which needs a specific qpdf
"pikepdf": { "pikepdf": {
"qpdf_version": "10.6.3", "qpdf_version": "10.6.3",
}, },
# For other packages, it is directly configured, for now # For other packages, version and Git information are directly configured
# These require manual updates to this file for version updates # These require manual updates to this file for version updates
"qpdf": { "qpdf": {
"version": "10.6.3", "version": "10.6.3",
@ -59,11 +71,9 @@ def _main():
output = {"name": args.package} output = {"name": args.package}
# Read Pipfile.lock file # Read Pipfile.lock file
pipfile_data = json.loads(pip_lock.read_text()) pipfile_data = json.loads(pip_lock.read_text())
# Read the version from Pipfile.lock # Read the version from Pipfile.lock
if args.package in pipfile_data["default"]: if args.package in pipfile_data["default"]:
pkg_data = pipfile_data["default"][args.package] pkg_data = pipfile_data["default"][args.package]
@ -73,7 +83,6 @@ def _main():
output["version"] = pkg_version output["version"] = pkg_version
# Based on the package, generate the expected Git tag name # Based on the package, generate the expected Git tag name
if args.package == "pikepdf": if args.package == "pikepdf":
git_tag_name = f"v{pkg_version}" git_tag_name = f"v{pkg_version}"
elif args.package == "psycopg2": elif args.package == "psycopg2":
@ -81,31 +90,18 @@ def _main():
output["git_tag"] = git_tag_name output["git_tag"] = git_tag_name
# Based on the package and environment, generate the Docker image tag # Use the basic ref name, minus refs/heads or refs/tags for frontend builder image
elif args.package == "frontend":
output["version"] = os.environ["GITHUB_REF_NAME"]
image_tag = _get_image_tag(repo_name, args.package, pkg_version) # Add anything special from the config
output.update(CONFIG[args.package])
output["image_tag"] = image_tag # Based on the package and environment, generate the Docker image tag
output["image_tag"] = _get_image_tag(repo_name, args.package, output["version"])
# Check for any special configuration, based on package
if args.package in CONFIG:
output.update(CONFIG[args.package])
elif args.package in CONFIG:
# This is not a Python package
output.update(CONFIG[args.package])
output["image_tag"] = _get_image_tag(repo_name, args.package, output["version"])
else:
raise NotImplementedError(args.package)
# Output the JSON info to stdout # Output the JSON info to stdout
print(json.dumps(output))
print(json.dumps(output, indent=2))
if __name__ == "__main__": if __name__ == "__main__":