From 32b2cc1bc574ab1d7e5e834385653c720e2607d8 Mon Sep 17 00:00:00 2001 From: Keigh Rim Date: Fri, 20 Feb 2026 18:23:45 -0500 Subject: [PATCH 1/2] QEMU emulation now replaced with native arm64 VM for container builds --- .github/workflows/container.yml | 135 ++++++++++++++++++++++++-------- container/opencv4.containerfile | 3 +- 2 files changed, 105 insertions(+), 33 deletions(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 5e91033..2296743 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -11,6 +11,10 @@ on: required: true type: string description: 'name of the container build file to use' + ref: + required: false + type: string + description: 'git ref to checkout (defaults to version)' workflow_dispatch: inputs: version: @@ -21,30 +25,45 @@ on: required: true type: string description: 'name of the container build file to use' + ref: + required: false + type: string + description: 'git ref to checkout (defaults to version)' env: REGISTRY: ghcr.io jobs: - build-and-push-image: - name: "🐳 Build and push image" - runs-on: ubuntu-latest + build: + name: "🐳 Build (${{ matrix.platform }})" + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm permissions: contents: read packages: write steps: + - name: "🔧 Prepare" + id: prepare + run: | + platform=${{ matrix.platform }} + echo "pair=${platform//\//-}" >> $GITHUB_OUTPUT + slug=$(echo "${{ inputs.buildfilename }}" | sed 's|[^a-zA-Z0-9]|-|g; s/^-*//; s/-*$//') + echo "slug=${slug}" >> $GITHUB_OUTPUT + - name: "🛍️ Checkout repository" uses: actions/checkout@v4 with: - ref: ${{ inputs.version }} - fetch-depth: 0 - - - name: "🎛 Set up QEMU" - uses: docker/setup-qemu-action@v3 + ref: ${{ inputs.ref || inputs.version }} - name: "👷 Set up Docker Buildx" - id: buildx uses: docker/setup-buildx-action@v3 - name: "🏷 Prepare OCI annotations" @@ -68,23 +87,11 @@ jobs: export nameonly="${filename%.*}" if [ ${nameonly} == ${filename} ]; then echo "SUFFIX=" >> $GITHUB_ENV ; else echo "SUFFIX=-${nameonly}" >> $GITHUB_ENV; fi - - name: "🏷 Get SDK version from latest tag" - id: sdkversion - run: | - export version=$(git describe --tags --abbrev=0) - echo "CLAMS_VERSION=${version}" >> $GITHUB_OUTPUT - - - name: "🏷 Prepare docker tags, labels" + - name: "🏷 Prepare docker labels" id: meta uses: docker/metadata-action@v5 - env: - CLAMS_VERSION: ${{ steps.sdkversion.outputs.CLAMS_VERSION }} with: images: ${{ env.REGISTRY }}/${{ github.repository }}${{ env.SUFFIX }} - tags: | - type=pep440,pattern={{version}},value=${{ env.CLAMS_VERSION }} - type=ref,event=tag - type=ref,event=pr labels: | ${{ env.EXISTING_LABELS }} @@ -95,18 +102,84 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: "🏗 Build and push image" - uses: docker/build-push-action@v5 - env: - CLAMS_VERSION: ${{ steps.sdkversion.outputs.CLAMS_VERSION }} + - name: "🏗 Build and push by digest" + id: build + uses: docker/build-push-action@v6 with: context: ${{ env.CONTEXT }} - platforms: linux/amd64,linux/arm64 + platforms: ${{ matrix.platform }} file: ${{ inputs.buildfilename }} - tags: ${{ steps.meta.outputs.tags }} - # using {{ steps.meta.outputs.labels }} doesn't work with multi-line variable ($EXISTING_LABLES) labels: ${{ env.DOCKER_METADATA_OUTPUT_LABELS }} build-args: | - clams_version=${{ env.CLAMS_VERSION }} - push: true + clams_version=${{ inputs.version }} + outputs: type=image,"name=${{ env.REGISTRY }}/${{ github.repository }}${{ env.SUFFIX }}",push-by-digest=true,name-canonical=true,push=true + + - name: "📤 Export digest" + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + - name: "📦 Upload digest" + uses: actions/upload-artifact@v4 + with: + name: digests-${{ steps.prepare.outputs.slug }}-${{ steps.prepare.outputs.pair }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + name: "🔗 Create multi-platform manifest" + runs-on: ubuntu-latest + needs: build + permissions: + contents: read + packages: write + + steps: + - name: "🔧 Prepare" + id: prepare + run: | + slug=$(echo "${{ inputs.buildfilename }}" | sed 's|[^a-zA-Z0-9]|-|g; s/^-*//; s/-*$//') + echo "slug=${slug}" >> $GITHUB_OUTPUT + + - name: "🏷 Get image name suffix" + id: getsuffix + run: | + export filename=$(basename ${{ inputs.buildfilename }}) + export nameonly="${filename%.*}" + if [ ${nameonly} == ${filename} ]; then echo "SUFFIX=" >> $GITHUB_ENV ; else echo "SUFFIX=-${nameonly}" >> $GITHUB_ENV; fi + + - name: "📥 Download digests" + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-${{ steps.prepare.outputs.slug }}-* + merge-multiple: true + + - name: "👷 Set up Docker Buildx" + uses: docker/setup-buildx-action@v3 + + - name: "🏷 Prepare docker tags" + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository }}${{ env.SUFFIX }} + tags: | + type=pep440,pattern={{version}},value=${{ inputs.version }} + type=ref,event=tag + type=ref,event=pr + + - name: "🔏 Log in to registry" + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: "🔗 Create manifest list and push" + working-directory: /tmp/digests + run: | + docker buildx imagetools create \ + $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY }}/${{ github.repository }}${{ env.SUFFIX }}@sha256:%s ' *) diff --git a/container/opencv4.containerfile b/container/opencv4.containerfile index 4895a7d..717efe1 100644 --- a/container/opencv4.containerfile +++ b/container/opencv4.containerfile @@ -28,8 +28,7 @@ RUN cmake \ -D BUILD_PERF_TESTS=OFF \ -D BUILD_TESTS=OFF \ -D CMAKE_INSTALL_PREFIX=/usr/local \ - -D OPENCV_EXTRA_MODULES_PATH=${OPENCV_EXTRA_MODULES_PATH} \ - -D BUILD_opencv_python3=ON \ + -D OPENCV_EXTRA_MODULES_PATH=${OPENCV_EXTRA_PATH}/modules \ -D BUILD_opencv_python3=OFF \ -D PYTHON3_EXECUTABLE=$(which python3) \ -D PYTHON_DEFAULT_EXECUTABLE=$(which python3) \ From f5960dcd9d6f68729b2a3c82df0e64d0d4516762 Mon Sep 17 00:00:00 2001 From: Keigh Rim Date: Fri, 20 Feb 2026 18:24:29 -0500 Subject: [PATCH 2/2] drop tf2-hf images and update transformers to v5 --- .github/workflows/containers.yml | 27 -------------------------- container/ffmpeg-hf.containerfile | 2 +- container/ffmpeg-tf2-hf.containerfile | 7 ------- container/hf.containerfile | 2 +- container/opencv4-hf.containerfile | 2 +- container/opencv4-tf2-hf.containerfile | 7 ------- container/tf2-hf.containerfile | 7 ------- 7 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 container/ffmpeg-tf2-hf.containerfile delete mode 100644 container/opencv4-tf2-hf.containerfile delete mode 100644 container/tf2-hf.containerfile diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml index bc45b7a..2c9160c 100644 --- a/.github/workflows/containers.yml +++ b/.github/workflows/containers.yml @@ -134,15 +134,6 @@ jobs: buildfilename: './container/opencv4-torch2.containerfile' version: ${{ needs.set-version.outputs.version }} - call-build-tf2-hf: - name: "🤙 Call container workflow with `tf2-hf`" - needs: ['set-version', 'call-build-tf2'] - uses: ./.github/workflows/container.yml - secrets: inherit - with: - buildfilename: './container/tf2-hf.containerfile' - version: ${{ needs.set-version.outputs.version }} - call-build-hf: name: "🤙 Call container workflow with `hf`" needs: ['set-version', 'call-build-torch2'] @@ -152,15 +143,6 @@ jobs: buildfilename: './container/hf.containerfile' version: ${{ needs.set-version.outputs.version }} - call-build-ffmpeg-tf2-hf: - name: "🤙 Call container workflow with `ffmpeg-tf2-hf`" - needs: ['set-version', 'call-build-ffmpeg-tf2'] - uses: ./.github/workflows/container.yml - secrets: inherit - with: - buildfilename: './container/ffmpeg-tf2-hf.containerfile' - version: ${{ needs.set-version.outputs.version }} - call-build-ffmpeg-hf: name: "🤙 Call container workflow with `ffmpeg-hf`" needs: ['set-version', 'call-build-ffmpeg-torch2'] @@ -170,15 +152,6 @@ jobs: buildfilename: './container/ffmpeg-hf.containerfile' version: ${{ needs.set-version.outputs.version }} - call-build-opencv4-tf2-hf: - name: "🤙 Call container workflow with `opencv4-tf2-hf`" - needs: ['set-version', 'call-build-opencv4-tf2'] - uses: ./.github/workflows/container.yml - secrets: inherit - with: - buildfilename: './container/opencv4-tf2-hf.containerfile' - version: ${{ needs.set-version.outputs.version }} - call-build-opencv4-hf: name: "🤙 Call container workflow with `opencv4-hf`" needs: ['set-version', 'call-build-opencv4-torch2'] diff --git a/container/ffmpeg-hf.containerfile b/container/ffmpeg-hf.containerfile index 51a2ab3..0a0dc6b 100644 --- a/container/ffmpeg-hf.containerfile +++ b/container/ffmpeg-hf.containerfile @@ -2,6 +2,6 @@ ARG clams_version FROM ghcr.io/clamsproject/clams-python-ffmpeg-torch2:$clams_version LABEL org.opencontainers.image.description="clams-python-ffmpeg-hf image is shipped with clams-python, ffmpeg, and vairous huggingface libraries (PyTorch backend)" -RUN pip install --no-cache-dir transformers[torch,tokenizers]==4.* +RUN pip install --no-cache-dir transformers[torch,tokenizers]==5.* RUN pip install --no-cache-dir datasets diff --git a/container/ffmpeg-tf2-hf.containerfile b/container/ffmpeg-tf2-hf.containerfile deleted file mode 100644 index 7d7a9dd..0000000 --- a/container/ffmpeg-tf2-hf.containerfile +++ /dev/null @@ -1,7 +0,0 @@ -ARG clams_version -FROM ghcr.io/clamsproject/clams-python-ffmpeg-tf2:$clams_version -LABEL org.opencontainers.image.description="clams-python-ffmpeg-tf2-hf image is shipped with clams-python, ffmpeg, tensorflow2, and vairous huggingface libraries" - -RUN pip install --no-cache-dir transformers[tf,tokenizers]==4.* -RUN pip install --no-cache-dir datasets - diff --git a/container/hf.containerfile b/container/hf.containerfile index 4de3e48..77c9d8e 100644 --- a/container/hf.containerfile +++ b/container/hf.containerfile @@ -2,6 +2,6 @@ ARG clams_version FROM ghcr.io/clamsproject/clams-python-torch2:$clams_version LABEL org.opencontainers.image.description="clams-python-hf image is shipped with clams-python and vairous huggingface libraries (PyTorch backend)" -RUN pip install --no-cache-dir transformers[torch,tokenizers]==4.* +RUN pip install --no-cache-dir transformers[torch,tokenizers]==5.* RUN pip install --no-cache-dir datasets diff --git a/container/opencv4-hf.containerfile b/container/opencv4-hf.containerfile index b28670f..a1b4841 100644 --- a/container/opencv4-hf.containerfile +++ b/container/opencv4-hf.containerfile @@ -2,6 +2,6 @@ ARG clams_version FROM ghcr.io/clamsproject/clams-python-opencv4-torch2:$clams_version LABEL org.opencontainers.image.description="clams-python-opencv4-hf image is shipped with clams-python, opencv4 (ffmpeg backend), and vairous huggingface libraries (PyTorch backend)" -RUN pip install --no-cache-dir transformers[torch,tokenizers]==4.* +RUN pip install --no-cache-dir transformers[torch,tokenizers]==5.* RUN pip install --no-cache-dir datasets diff --git a/container/opencv4-tf2-hf.containerfile b/container/opencv4-tf2-hf.containerfile deleted file mode 100644 index ea0a3dd..0000000 --- a/container/opencv4-tf2-hf.containerfile +++ /dev/null @@ -1,7 +0,0 @@ -ARG clams_version -FROM ghcr.io/clamsproject/clams-python-opencv4-tf2:$clams_version -LABEL org.opencontainers.image.description="clams-python-opencv4-tf2-hf image is shipped with clams-python, opencv4 (ffmpeg backend), tensorflow2, and vairous huggingface libraries" - -RUN pip install --no-cache-dir transformers[tf,tokenizers]==4.* -RUN pip install --no-cache-dir datasets - diff --git a/container/tf2-hf.containerfile b/container/tf2-hf.containerfile deleted file mode 100644 index 6b0fe7d..0000000 --- a/container/tf2-hf.containerfile +++ /dev/null @@ -1,7 +0,0 @@ -ARG clams_version -FROM ghcr.io/clamsproject/clams-python-tf2:$clams_version -LABEL org.opencontainers.image.description="clams-python-tf2-hf image is shipped with clams-python, tensorflow2, and vairous huggingface libraries" - -RUN pip install --no-cache-dir transformers[tf,tokenizers]==4.* -RUN pip install --no-cache-dir datasets -