diff --git a/.github/workflows/glpi-development-env.yml b/.github/workflows/glpi-development-env.yml index eab86ac..3d8bc6f 100644 --- a/.github/workflows/glpi-development-env.yml +++ b/.github/workflows/glpi-development-env.yml @@ -1,5 +1,8 @@ name: "GLPI development environment image" +env: + GHCR_IMAGE: "ghcr.io/glpi-project/glpi-development-env" + on: push: branches: @@ -18,47 +21,151 @@ on: jobs: build: - runs-on: "ubuntu-latest" + name: "Build PHP ${{ matrix.php.php-version }} [${{ matrix.platform.suffix }}]" + runs-on: "${{ matrix.platform.runner }}" + env: + PUSH: ${{ github.ref == 'refs/heads/main' && github.repository == 'glpi-project/docker-images' }} strategy: fail-fast: false matrix: - include: + php: - {base-image: "php:8.2-apache-trixie", php-version: "8.2", latest: "false"} - {base-image: "php:8.3-apache-trixie", php-version: "8.3", latest: "false"} - {base-image: "php:8.4-apache-trixie", php-version: "8.4", latest: "false"} - {base-image: "php:8.5-apache-trixie", php-version: "8.5", latest: "true"} - {base-image: "php:8.6-rc-apache-trixie", php-version: "8.6", latest: "false"} + platform: + - { arch: "linux/amd64", runner: "ubuntu-24.04", suffix: "amd64" } + - { arch: "linux/arm64", runner: "ubuntu-24.04-arm", suffix: "arm64" } steps: - - name: "Set variables" - run: | - OUTPUTS="type=image" - if [[ "${{ github.ref }}" = 'refs/heads/main' && "${{ github.repository }}" = 'glpi-project/docker-images' ]]; then - OUTPUTS="$OUTPUTS,push=true" - fi - echo "OUTPUTS=$OUTPUTS" >> $GITHUB_ENV - name: "Checkout" uses: "actions/checkout@v7" + + - name: "Docker metadata" + id: "meta" + uses: "docker/metadata-action@v6" + with: + images: | + ${{ env.GHCR_IMAGE }} + + - name: "Set up QEMU" + uses: "docker/setup-qemu-action@v4" + - name: "Set up Docker Buildx" uses: "docker/setup-buildx-action@v4" + - name: "Login to DockerHub" + if: ${{ env.PUSH == 'true' }} uses: "docker/login-action@v4" with: username: "${{ secrets.DOCKER_HUB_USERNAME }}" password: "${{ secrets.DOCKER_HUB_TOKEN }}" + - name: "Login to Github container registry" + if: ${{ env.PUSH == 'true' }} uses: "docker/login-action@v4" with: registry: "ghcr.io" username: "${{ secrets.GHCR_USERNAME }}" password: "${{ secrets.GHCR_ACCESS_TOKEN }}" - - name: "Build and push" + + - name: "Build and push by digest" + id: "build" uses: "docker/build-push-action@v7" + env: + DOCKER_BUILD_SUMMARY: ${{ runner.debug == '1' }} with: build-args: | - BASE_IMAGE=${{ matrix.base-image }} - cache-from: "type=gha" - cache-to: "type=gha,mode=max" + BASE_IMAGE=${{ matrix.php.base-image }} + cache-from: "type=gha,scope=glpi-development-env-${{ matrix.php.php-version }}-${{ matrix.platform.suffix }}" + cache-to: "type=gha,mode=max,scope=glpi-development-env-${{ matrix.php.php-version }}-${{ matrix.platform.suffix }}" context: "glpi-development-env" - outputs: "${{ env.OUTPUTS }}" + labels: "${{ steps.meta.outputs.labels }}" + platforms: "${{ matrix.platform.arch }}" pull: true - tags: "ghcr.io/glpi-project/glpi-development-env:${{ matrix.php-version }}${{ matrix.latest == 'true' && ',ghcr.io/glpi-project/glpi-development-env:latest' || '' }}" + sbom: ${{ env.PUSH == 'true' }} + provenance: ${{ env.PUSH == 'true' && 'mode=max' || 'false' }} + outputs: "type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=${{ env.PUSH }}" + + - name: "Export digest" + if: ${{ env.PUSH == 'true' }} + run: | + mkdir -p ${{ runner.temp }}/digests + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}-${{ matrix.platform.suffix }}" + + - name: "Upload digest" + if: ${{ env.PUSH == 'true' }} + uses: "actions/upload-artifact@v7" + with: + name: "digests-glpi-development-env-${{ matrix.php.php-version }}-${{ matrix.platform.suffix }}" + path: "${{ runner.temp }}/digests/*" + if-no-files-found: "error" + retention-days: 1 + + merge-manifests: + name: "Merge manifests [PHP ${{ matrix.php.php-version }}]" + runs-on: "ubuntu-latest" + needs: [build] + if: ${{ github.ref == 'refs/heads/main' && github.repository == 'glpi-project/docker-images' }} + strategy: + fail-fast: false + matrix: + php: + - {php-version: "8.2", latest: "false"} + - {php-version: "8.3", latest: "false"} + - {php-version: "8.4", latest: "false"} + - {php-version: "8.5", latest: "true"} + - {php-version: "8.6", latest: "false"} + steps: + - name: "Download digests" + uses: "actions/download-artifact@v8" + with: + path: "${{ runner.temp }}/digests" + pattern: "digests-glpi-development-env-${{ matrix.php.php-version }}-*" + merge-multiple: true + - name: "Verify digests" + run: | + mkdir -p "${{ runner.temp }}/digests" + if [ -z "$(ls --almost-all ${{ runner.temp }}/digests)" ]; then + echo "::error::No digest files found for PHP ${{ matrix.php.php-version }}! Build jobs may have failed or artifacts expired." + exit 1 + fi + - name: "Set up Docker Buildx" + uses: "docker/setup-buildx-action@v4" + - name: "Login to Github container registry" + uses: "docker/login-action@v4" + with: + registry: "ghcr.io" + username: "${{ secrets.GHCR_USERNAME }}" + password: "${{ secrets.GHCR_ACCESS_TOKEN }}" + - name: "Docker metadata" + id: "meta" + uses: "docker/metadata-action@v6" + with: + images: | + ${{ env.GHCR_IMAGE }} + flavor: | + latest=false + tags: | + type=raw,value=${{ matrix.php.php-version }} + type=raw,value=latest,enable=${{ matrix.php.latest == 'true' }} + - name: "Create and push manifest" + working-directory: "${{ runner.temp }}/digests" + env: + TAGS: ${{ steps.meta.outputs.tags }} + run: | + # Read digest files (named like -) and prepare source array + GHCR_SOURCES="" + for file_path in "$PWD"/*; do + file_name="${file_path##*/}" + hash="${file_name%%-*}" + GHCR_SOURCES="$GHCR_SOURCES ${{ env.GHCR_IMAGE }}@sha256:$hash" + done + + # Create manifest for GHCR + GHCR_TAGS=$(echo "$TAGS" | grep "^${{ env.GHCR_IMAGE }}" | xargs --replace={} echo "-t {}" | tr '\n' ' ') + if [[ -n "$GHCR_TAGS" ]]; then + echo "Creating GHCR manifest..." + docker buildx imagetools create $GHCR_TAGS $GHCR_SOURCES + fi diff --git a/glpi-development-env/Dockerfile b/glpi-development-env/Dockerfile index dc4819b..7982844 100644 --- a/glpi-development-env/Dockerfile +++ b/glpi-development-env/Dockerfile @@ -46,7 +46,7 @@ RUN --mount=type=bind,from=ghcr.io/php/pie:bin,source=/pie,target=/usr/local/bin \ # Install ldap PHP extension. && apt install --assume-yes --no-install-recommends --quiet libldap2-dev \ - && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \ + && docker-php-ext-configure ldap --with-libdir="lib/$(dpkg-architecture --query DEB_HOST_MULTIARCH)/" \ && docker-php-ext-install ldap \ \ # Install mbstring PHP extension (not installed by default since PHP 8.6).