build #111
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-License-Identifier: MIT | |
| # Copyright (c) 2026 Netresearch DTT GmbH | |
| name: build | |
| on: | |
| # Daily rebuild — picks up Alpine / PHP base-image CVE fixes for the same | |
| # pinned GLPI release. (GLPI bundles its vendor/ in the release tarball, so | |
| # there is no Composer "rolling" variant; the daily rebuild IS the GLPI- | |
| # appropriate equivalent — fresh base, same app.) | |
| schedule: | |
| - cron: '0 4 * * *' # 04:00 UTC | |
| push: | |
| branches: [main] | |
| paths-ignore: | |
| - 'docs/**' | |
| - '**.md' | |
| - 'examples/**' | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| glpi_version: | |
| description: 'Override GLPI version (default: read .glpi-version)' | |
| required: false | |
| default: '' | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository_owner }}/glpi-php-fpm | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: build-${{ github.workflow }}-${{ github.ref }} | |
| # Don't cancel the daily multi-arch rebuild mid-flight (half-attached | |
| # manifests); do supersede an older push/PR build with a newer commit. | |
| cancel-in-progress: ${{ github.event_name != 'schedule' }} | |
| jobs: | |
| # ─ Resolve version / tarball digest / facts once, upstream of the build ─ | |
| resolve: | |
| name: resolve | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| version: ${{ steps.r.outputs.version }} | |
| major: ${{ steps.r.outputs.major }} | |
| major_minor: ${{ steps.r.outputs.major_minor }} | |
| glpi_sha256: ${{ steps.r.outputs.glpi_sha256 }} | |
| build_date: ${{ steps.r.outputs.build_date }} | |
| date_tag: ${{ steps.r.outputs.date_tag }} | |
| is_release_from_file: ${{ steps.r.outputs.is_release_from_file }} | |
| is_main_ref: ${{ steps.r.outputs.is_main_ref }} | |
| push_artifacts: ${{ steps.r.outputs.push_artifacts }} | |
| # Registry + image name are passed through resolve because a reusable | |
| # workflow's `with:` block cannot read the caller's `env:` context. | |
| registry: ${{ steps.r.outputs.registry }} | |
| image_name: ${{ steps.r.outputs.image_name }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Resolve version, tarball sha256, and facts | |
| id: r | |
| env: | |
| # All ${{ }} interpolation flows through env vars, never straight | |
| # into the run-script body — sonarcloud githubactions:S7630 | |
| # (shell injection); matters most for the user-supplied override. | |
| INPUT_VERSION: ${{ inputs.glpi_version }} | |
| EVENT: ${{ github.event_name }} | |
| REF_FULL: ${{ github.ref }} | |
| REGISTRY: ${{ env.REGISTRY }} | |
| IMAGE_NAME: ${{ env.IMAGE_NAME }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "$INPUT_VERSION" ]; then | |
| VERSION="$INPUT_VERSION" | |
| IS_RELEASE_FROM_FILE=false | |
| else | |
| VERSION=$(tr -d '[:space:]' < .glpi-version) | |
| IS_RELEASE_FROM_FILE=true | |
| fi | |
| # GLPI release tags have no 'v' prefix; strip one defensively anyway. | |
| VERSION="${VERSION#v}" | |
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | |
| MAJOR_MINOR=$(echo "$VERSION" | cut -d. -f1-2) | |
| # Resolve the bundled-tarball sha256 once and pin the build to it — | |
| # a swapped release asset can't slip into the image (supply chain). | |
| URL="https://github.com/glpi-project/glpi/releases/download/${VERSION}/glpi-${VERSION}.tgz" | |
| GLPI_SHA256=$(curl -fsSL "$URL" | sha256sum | cut -d' ' -f1) | |
| [ -n "$GLPI_SHA256" ] || { echo "could not hash $URL" >&2; exit 1; } | |
| IS_MAIN_REF=false | |
| [ "$REF_FULL" = "refs/heads/main" ] && IS_MAIN_REF=true | |
| PUSH_ARTIFACTS=true | |
| [ "$EVENT" = "pull_request" ] && PUSH_ARTIFACTS=false | |
| { | |
| echo "version=$VERSION" | |
| echo "major=$MAJOR" | |
| echo "major_minor=$MAJOR_MINOR" | |
| echo "glpi_sha256=$GLPI_SHA256" | |
| echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" | |
| echo "date_tag=$(date -u +'%Y%m%d')" | |
| echo "is_release_from_file=$IS_RELEASE_FROM_FILE" | |
| echo "is_main_ref=$IS_MAIN_REF" | |
| echo "push_artifacts=$PUSH_ARTIFACTS" | |
| echo "registry=$REGISTRY" | |
| echo "image_name=$IMAGE_NAME" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "─ resolved ─ GLPI $VERSION sha256=${GLPI_SHA256:0:16}… push=$PUSH_ARTIFACTS" | |
| # ─ Build: per-arch build → digest → multi-arch merge → SLSA + cosign ─── | |
| build: | |
| name: build | |
| needs: resolve | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| uses: ./.github/workflows/_build-cell.yml | |
| with: | |
| version: ${{ needs.resolve.outputs.version }} | |
| major: ${{ needs.resolve.outputs.major }} | |
| major_minor: ${{ needs.resolve.outputs.major_minor }} | |
| glpi_sha256: ${{ needs.resolve.outputs.glpi_sha256 }} | |
| build_date: ${{ needs.resolve.outputs.build_date }} | |
| date_tag: ${{ needs.resolve.outputs.date_tag }} | |
| registry: ${{ needs.resolve.outputs.registry }} | |
| image_name: ${{ needs.resolve.outputs.image_name }} | |
| is_main_ref: ${{ needs.resolve.outputs.is_main_ref == 'true' }} | |
| is_release_from_file: ${{ needs.resolve.outputs.is_release_from_file == 'true' }} | |
| push_artifacts: ${{ needs.resolve.outputs.push_artifacts == 'true' }} |