diff --git a/.common-ci.yml b/.common-ci.yml index d859d63..7cd5a20 100644 --- a/.common-ci.yml +++ b/.common-ci.yml @@ -13,9 +13,9 @@ # limitations under the License. default: - image: docker:stable + image: docker services: - - name: docker:stable-dind + - name: docker:dind command: ["--experimental"] variables: @@ -23,192 +23,35 @@ variables: BUILD_MULTI_ARCH_IMAGES: "true" stages: - - image - - lint - - go-checks - - go-build - - unit-tests - - package-build - - image-build - - test + - pull - scan - - aws_kube_setup - - integration_tests - - e2e_tests - - aws_kube_clean - release + - sign -# Define the distribution targets -.dist-ubuntu22.04: - variables: - DIST: ubuntu22.04 - -.dist-ubi9: - variables: - DIST: ubi9 - -# Define the platform targets -.platform-amd64: - variables: - PLATFORM: linux/amd64 - -.platform-arm64: - variables: - PLATFORM: linux/arm64 - -# Define the sample targets -.sample-vectoradd: - variables: - SAMPLE: vectorAdd - LOWER_CASE_SAMPLE: vectoradd - PUSH_SAMPLE_ONLY_TAG: "false" - -.sample-nbody: - variables: - SAMPLE: nbody - LOWER_CASE_SAMPLE: nbody - PUSH_SAMPLE_ONLY_TAG: "true" - -.sample-device-query: - variables: - SAMPLE: deviceQuery - LOWER_CASE_SAMPLE: devicequery - PUSH_SAMPLE_ONLY_TAG: "true" - -.sample-simple-multi-gpu: - variables: - SAMPLE: simpleMultiGPU - LOWER_CASE_SAMPLE: simplemultigpu - PUSH_SAMPLE_ONLY_TAG: "true" - -# Define the sample targets -.sample-vulkan: - variables: - SAMPLE: vulkan - LOWER_CASE_SAMPLE: vulkan - PUSH_SAMPLE_ONLY_TAG: "true" - -.sample-nvbandwidth: - variables: - SAMPLE: nvbandwidth - LOWER_CASE_SAMPLE: nvbandwidth - PUSH_SAMPLE_ONLY_TAG: "true" - -# Make buildx available as a docker CLI plugin -.buildx-setup: - before_script: - - export BUILDX_VERSION=v0.6.3 - - apk add --no-cache curl - - mkdir -p ~/.docker/cli-plugins - - curl -sSLo ~/.docker/cli-plugins/docker-buildx "https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-amd64" - - chmod a+x ~/.docker/cli-plugins/docker-buildx - - - docker buildx create --use --platform=linux/amd64,linux/arm64 - - - '[[ -n "${SKIP_QEMU_SETUP}" ]] || docker run --rm --privileged multiarch/qemu-user-static --reset -p yes' +.pipeline-trigger-rules: + rules: + # We trigger the pipeline if started manually + - if: $CI_PIPELINE_SOURCE == "web" + # We trigger the pipeline on the main branch + - if: $CI_COMMIT_BRANCH == "main" + # We trigger the pipeline on the release- branches + - if: $CI_COMMIT_BRANCH =~ /^release-.*$/ + # We trigger the pipeline on tags + - if: $CI_COMMIT_TAG && $CI_COMMIT_TAG != "" + +workflow: + rules: + # We trigger the pipeline on a merge request + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + # We then add all the regular triggers + - !reference [.pipeline-trigger-rules, rules] # Download the regctl binary for use in the release steps .regctl-setup: before_script: - - export REGCTL_VERSION=v0.3.10 + - export REGCTL_VERSION=v0.4.5 - apk add --no-cache curl - mkdir -p bin - curl -sSLo bin/regctl https://github.com/regclient/regclient/releases/download/${REGCTL_VERSION}/regctl-linux-amd64 - chmod a+x bin/regctl - export PATH=$(pwd)/bin:${PATH} - -# .release forms the base of the deployment jobs which push images to the CI registry. -# This is extended with the version to be deployed (e.g. the SHA or TAG) and the -# target os. -.release: - stage: - release - variables: - # Define the source image for the release - IMAGE_NAME: "${CI_REGISTRY_IMAGE}/cuda-samples" - VERSION: "${CI_COMMIT_SHORT_SHA}" - # OUT_IMAGE_VERSION is overridden for external releases - OUT_IMAGE_VERSION: "${CI_COMMIT_SHORT_SHA}" - before_script: - - !reference [.regctl-setup, before_script] - - # We ensure that the OUT_IMAGE_VERSION is set - - 'echo Version: ${OUT_IMAGE_VERSION} ; [[ -n "${OUT_IMAGE_VERSION}" ]] || exit 1' - - - apk add --no-cache make bash - script: - # Log in to the "output" registry, tag the image and push the image - - 'echo "Logging in to CI registry ${CI_REGISTRY}"' - - regctl registry login "${CI_REGISTRY}" -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" - - '[ ${CI_REGISTRY} = ${OUT_REGISTRY} ] || echo "Logging in to output registry ${OUT_REGISTRY}"' - - '[ ${CI_REGISTRY} = ${OUT_REGISTRY} ] || regctl registry login "${OUT_REGISTRY}" -u "${OUT_REGISTRY_USER}" -p "${OUT_REGISTRY_TOKEN}"' - - # Since OUT_IMAGE_NAME and OUT_IMAGE_VERSION are set, this will push the CI image to the - # Target - - make -f deployments/container/Makefile push-${DIST} - -# Define a staging release step that pushes an image to an internal "staging" repository -# This is triggered for all pipelines (i.e. not only tags) to test the pipeline steps -# outside of the release process. -.release:staging: - extends: - - .release - variables: - OUT_REGISTRY_USER: "${CI_REGISTRY_USER}" - OUT_REGISTRY_TOKEN: "${CI_REGISTRY_PASSWORD}" - OUT_REGISTRY: "${CI_REGISTRY}" - OUT_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/staging/cuda-samples" - -# Define an external release step that pushes an image to an external repository. -# This includes a devlopment image off main. -.release:external: - extends: - - .release - rules: - - if: $CI_COMMIT_TAG - variables: - OUT_IMAGE_VERSION: "${CI_COMMIT_TAG}" - - if: $CI_COMMIT_BRANCH == $RELEASE_DEVEL_BRANCH - variables: - OUT_IMAGE_VERSION: "${DEVEL_RELEASE_IMAGE_VERSION}" - -# Define the release jobs -release:staging-vectoradd-ubi9: - extends: - - .release:staging - - .dist-ubi9 - - .sample-vectoradd - needs: - - image-vectoradd-ubi9 - -release:staging-vectoradd-ubuntu22.04: - extends: - - .release:staging - - .dist-ubuntu22.04 - - .sample-vectoradd - needs: - - image-vectoradd-ubuntu22.04 - -release:staging-device-query-ubuntu22.04: - extends: - - .release:staging - - .dist-ubuntu22.04 - - .sample-device-query - needs: - - image-device-query-ubuntu22.04 - -release:staging-vulkan: - extends: - - .release:staging - - .dist-ubuntu22.04 - - .sample-vulkan - needs: - - image-vulkan-ubuntu22.04 - -release:staging-nvbandwidth: - extends: - - .release:staging - - .dist-ubuntu22.04 - - .sample-nvbandwidth - needs: - - image-nvbandwidth-ubuntu22.04 diff --git a/.github/workflows/image.yaml b/.github/workflows/image.yaml index 751214d..3fdba2e 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/image.yaml @@ -32,27 +32,13 @@ jobs: strategy: fail-fast: false matrix: - dist: - - ubuntu22.04 - - ubi9 sample: - - vectorAdd + - devicequery - nbody - - deviceQuery - nvbandwidth - - simpleMultiGPU + - simplemultigpu + - vectoradd - vulkan - exclude: - - dist: ubi9 - sample: deviceQuery - - dist: ubi9 - sample: nbody - - dist: ubi9 - sample: nvbandwidth - - dist: ubi9 - sample: simpleMultiGPU - - dist: ubi9 - sample: vulkan steps: - uses: actions/checkout@v4 @@ -61,7 +47,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: - image: tonistiigi/binfmt:qemu-v7.0.0 + image: tonistiigi/binfmt:qemu-v9.2.2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -78,7 +64,6 @@ jobs: IMAGE_NAME: ghcr.io/nvidia/k8s-samples VERSION: ${{ inputs.version }} PUSH_ON_BUILD: true - BUILD_MULTI_ARCH_IMAGES: ${{ inputs.build_multi_arch_images }} run: | - echo "Building ${{ matrix.sample }} on ${{ matrix.dist }}" - SAMPLE=${{ matrix.sample }} make -f deployments/container/Makefile build-${{ matrix.dist }} + echo "Building ${{ matrix.sample }}" + make -f deployments/container/Makefile build-${{ matrix.sample }} diff --git a/.nvidia-ci.yml b/.nvidia-ci.yml index de7038e..0380dd1 100644 --- a/.nvidia-ci.yml +++ b/.nvidia-ci.yml @@ -13,7 +13,7 @@ # limitations under the License. include: - - local: '.common-ci.yml' + - local: ".common-ci.yml" default: tags: @@ -36,99 +36,116 @@ variables: STAGING_REGISTRY: ghcr.io/nvidia STAGING_VERSION: ${CI_COMMIT_SHORT_SHA} -.image-pull: - stage: image-build +# .copy-images copies the required application and packaging images from the +# IN_IMAGE="${IN_IMAGE_NAME}:${SAMPLE}-${IN_IMAGE_TAG}" +# to +# OUT_IMAGE="${OUT_IMAGE_NAME}:${SAMPLE}-${OUT_IMAGE_TAG}" +# The script also logs into IN_REGISTRY and OUT_REGISTRY using the supplied +# username and tokens. +.copy-images: + parallel: + matrix: + - SAMPLE: + - devicequery + - nbody + - nvbandwidth + - simplemultigpu + - vectoradd + - vulkan + before_script: + - !reference [.regctl-setup, before_script] + - apk add --no-cache make bash + variables: + REGCTL: regctl + script: + - | + if [ -n ${IN_REGISTRY} ] && [ -n ${IN_REGISTRY_USER} ]; then + echo "Logging in to ${IN_REGISTRY}" + ${REGCTL} registry login "${IN_REGISTRY}" -u "${IN_REGISTRY_USER}" -p "${IN_REGISTRY_TOKEN}" || exit 1 + fi + + if [ -n ${OUT_REGISTRY} ] && [ -n ${OUT_REGISTRY_USER} ] && [ "${IN_REGISTRY}" != "${OUT_REGISTRY}" ]; then + echo "Logging in to ${OUT_REGISTRY}" + ${REGCTL} registry login "${OUT_REGISTRY}" -u "${OUT_REGISTRY_USER}" -p "${OUT_REGISTRY_TOKEN}" || exit 1 + fi + + export IN_IMAGE="${IN_IMAGE_NAME}:${SAMPLE}-${IN_IMAGE_TAG}" + export OUT_IMAGE="${OUT_IMAGE_NAME}:{SAMPLE}-${OUT_IMAGE_TAG}" + + echo "Copying ${IN_IMAGE} to ${OUT_IMAGE}" + ${REGCTL} image copy ${IN_IMAGE} ${OUT_IMAGE} + +# pull-images pulls images from the public CI registry to the internal CI registry. +pull-images: + extends: + - .copy-images + stage: pull variables: IN_REGISTRY: "${STAGING_REGISTRY}" - IN_IMAGE_NAME: k8s-samples - IN_VERSION: "${LOWER_CASE_SAMPLE}-${STAGING_VERSION}" + IN_IMAGE_NAME: ${STAGING_REGISTRY}/k8s-samples + IN_IMAGE_TAG: "${STAGING_VERSION}" + + OUT_REGISTRY: "${CI_REGISTRY}" OUT_REGISTRY_USER: "${CI_REGISTRY_USER}" OUT_REGISTRY_TOKEN: "${CI_REGISTRY_PASSWORD}" - OUT_REGISTRY: "${CI_REGISTRY}" - OUT_IMAGE_NAME: ${CI_REGISTRY_IMAGE}/cuda-samples - OUT_VERSION: ${LOWER_CASE_SAMPLE}-${CI_COMMIT_SHORT_SHA} - PUSH_MULTIPLE_TAGS: "false" + OUT_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/cuda-samples" + OUT_IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}" # We delay the job start to allow the public pipeline to generate the required images. - when: delayed - start_in: 30 minutes + rules: + # If the pipeline is triggered from a tag or the WEB UI we don't delay the + # start of the pipeline. + - if: $CI_COMMIT_TAG || $CI_PIPELINE_SOURCE == "web" + # If the pipeline is triggered through other means (i.e. a branch or MR) + # we add a 30 minute delay to ensure that the images are available in the + # public CI registry. + - when: delayed + start_in: 30 minutes timeout: 30 minutes retry: max: 2 when: - job_execution_timeout - stuck_or_timeout_failure - before_script: - - !reference [.regctl-setup, before_script] - - apk add --no-cache make bash - - > - regctl manifest get ${IN_REGISTRY}/${IN_IMAGE_NAME}:${IN_VERSION}-${DIST} --list > /dev/null && echo "${IN_REGISTRY}/${IN_IMAGE_NAME}:${IN_VERSION}-${DIST}" || ( echo "${IN_REGISTRY}/${IN_IMAGE_NAME}:${IN_VERSION}-${DIST} does not exist" && sleep infinity ) - script: - - regctl registry login "${OUT_REGISTRY}" -u "${OUT_REGISTRY_USER}" -p "${OUT_REGISTRY_TOKEN}" - - make -f deployments/container/Makefile IMAGE=${IN_REGISTRY}/${IN_IMAGE_NAME}:${IN_VERSION}-${DIST} OUT_IMAGE=${OUT_IMAGE_NAME}:${OUT_VERSION}-${DIST} push-${DIST} - -image-vectoradd-ubuntu22.04: - extends: - - .image-pull - - .dist-ubuntu22.04 - - .sample-vectoradd - -image-vectoradd-ubi9: - extends: - - .image-pull - - .dist-ubi9 - - .sample-vectoradd - -image-device-query-ubuntu22.04: - extends: - - .image-pull - - .dist-ubuntu22.04 - - .sample-device-query - -image-nbody-ubuntu22.04: - extends: - - .image-pull - - .dist-ubuntu22.04 - - .sample-nbody - -image-simple-multi-gpu-ubuntu22.04: - extends: - - .image-pull - - .dist-ubuntu22.04 - - .sample-simple-multi-gpu - -image-vulkan-ubuntu22.04: - extends: - - .image-pull - - .dist-ubuntu22.04 - - .sample-vulkan - -image-nvbandwidth-ubuntu22.04: - extends: - - .image-pull - - .dist-ubuntu22.04 - - .sample-nvbandwidth # The .scan step forms the base of the image scan operation performed before releasing # images. -.scan: +scan-images: stage: scan + needs: + - pull-images image: "${PULSE_IMAGE}" + parallel: + matrix: + - SAMPLE: + - devicequery + - nvbandwidth + - simplemultigpu + - vectoradd + PLATFORM: ["linux/amd64", "linux/arm64"] + - SAMPLE: + - nbody + - vulkan + PLATFORM: "linux/amd64" variables: - IMAGE: "${CI_REGISTRY_IMAGE}/cuda-samples:${LOWER_CASE_SAMPLE}-${CI_COMMIT_SHORT_SHA}-${DIST}" - IMAGE_ARCHIVE: "cuda-samples.tar" - except: - variables: - - $SKIP_SCANS && $SKIP_SCANS == "yes" - before_script: - - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" - - docker pull --platform="${PLATFORM}" "${IMAGE}" - - docker save "${IMAGE}" -o "${IMAGE_ARCHIVE}" - - AuthHeader=$(echo -n $SSA_CLIENT_ID:$SSA_CLIENT_SECRET | base64 -w0) - - > - export SSA_TOKEN=$(curl --request POST --header "Authorization: Basic $AuthHeader" --header "Content-Type: application/x-www-form-urlencoded" ${SSA_ISSUER_URL} | jq ".access_token" | tr -d '"') - - if [ -z "$SSA_TOKEN" ]; then exit 1; else echo "SSA_TOKEN set!"; fi + IMAGE: "${CI_REGISTRY_IMAGE}/cuda-samples" + IMAGE_ARCHIVE: "cuda-samples-${CI_JOB_ID}.tar" + rules: + - if: $IGNORE_SCANS == "yes" + allow_failure: true + - when: on_success script: - - pulse-cli -n $NSPECT_ID --ssa $SSA_TOKEN scan -i $IMAGE_ARCHIVE -p $CONTAINER_POLICY -o + - | + docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" + export SCAN_IMAGE=${IMAGE}:${SAMPLE}-:${CI_COMMIT_SHORT_SHA} + echo "Scanning image ${SCAN_IMAGE} for ${PLATFORM}" + docker pull --platform="${PLATFORM}" "${SCAN_IMAGE}" + docker save "${SCAN_IMAGE}" -o "${IMAGE_ARCHIVE}" + AuthHeader=$(echo -n $SSA_CLIENT_ID:$SSA_CLIENT_SECRET | base64 -w0) + export SSA_TOKEN=$(curl --request POST --header "Authorization: Basic $AuthHeader" --header "Content-Type: application/x-www-form-urlencoded" ${SSA_ISSUER_URL} | jq ".access_token" | tr -d '"') + if [ -z "$SSA_TOKEN" ]; then exit 1; else echo "SSA_TOKEN set!"; fi + + pulse-cli -n $NSPECT_ID --ssa $SSA_TOKEN scan -i $IMAGE_ARCHIVE -p $CONTAINER_POLICY -o + rm -f "${IMAGE_ARCHIVE}" artifacts: when: always expire_in: 1 week @@ -139,190 +156,123 @@ image-nvbandwidth-ubuntu22.04: - vulns.json - policy_evaluation.json -# Define the scan targets -scan-vectoradd-ubuntu22.04-amd64: - extends: - - .scan - - .sample-vectoradd - - .dist-ubuntu22.04 - - .platform-amd64 - needs: - - image-vectoradd-ubuntu22.04 - -scan-vectoradd-ubuntu22.04-arm64: - extends: - - .scan - - .sample-vectoradd - - .dist-ubuntu22.04 - - .platform-arm64 - needs: - - image-vectoradd-ubuntu22.04 - - scan-vectoradd-ubuntu22.04-amd64 - -scan-device-query-ubuntu22.04-amd64: - extends: - - .scan - - .sample-device-query - - .dist-ubuntu22.04 - - .platform-amd64 - needs: - - image-device-query-ubuntu22.04 - -scan-device-query-ubuntu22.04-arm64: - extends: - - .scan - - .sample-device-query - - .dist-ubuntu22.04 - - .platform-arm64 - needs: - - image-device-query-ubuntu22.04 - - scan-device-query-ubuntu22.04-amd64 - -scan-vectoradd-ubi9-amd64: - extends: - - .scan - - .sample-vectoradd - - .dist-ubi9 - - .platform-amd64 - needs: - - image-vectoradd-ubi9 - -scan-vectoradd-ubi9-arm64: +push-images-to-staging: extends: - - .scan - - .sample-vectoradd - - .dist-ubi9 - - .platform-arm64 + - .copy-images + stage: release needs: - - image-vectoradd-ubi9 - - scan-vectoradd-ubi9-amd64 - -scan-nbody-ubuntu22.04-amd64: - extends: - - .scan - - .sample-nbody - - .dist-ubuntu22.04 - - .platform-amd64 - needs: - - image-nbody-ubuntu22.04 - -scan-nbody-ubuntu22.04-arm64: - extends: - - .scan - - .sample-nbody - - .dist-ubuntu22.04 - - .platform-arm64 - needs: - - image-nbody-ubuntu22.04 - - scan-nbody-ubuntu22.04-amd64 - -scan-simple-multi-gpu-ubuntu22.04-amd64: - extends: - - .scan - - .sample-simple-multi-gpu - - .dist-ubuntu22.04 - - .platform-amd64 - needs: - - image-simple-multi-gpu-ubuntu22.04 - -scan-simple-multi-gpu-ubuntu22.04-arm64: - extends: - - .scan - - .sample-simple-multi-gpu - - .dist-ubuntu22.04 - - .platform-arm64 - needs: - - image-simple-multi-gpu-ubuntu22.04 - - scan-simple-multi-gpu-ubuntu22.04-amd64 - -scan-vulkan-ubuntu22.04-amd64: - extends: - - .scan - - .sample-vulkan - - .dist-ubuntu22.04 - - .platform-amd64 - needs: - - image-vulkan-ubuntu22.04 - -scan-vulkan-ubuntu22.04-arm64: - extends: - - .scan - - .sample-vulkan - - .dist-ubuntu22.04 - - .platform-arm64 - needs: - - image-vulkan-ubuntu22.04 - - scan-vulkan-ubuntu22.04-amd64 + - scan-images + variables: + IN_REGISTRY: "${CI_REGISTRY}" + IN_REGISTRY_USER: "${CI_REGISTRY_USER}" + IN_REGISTRY_TOKEN: "${CI_REGISTRY_PASSWORD}" + IN_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/cuda-amples" + IN_IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}" -scan-nvbandwidth-ubuntu22.04-amd64: - extends: - - .scan - - .sample-nvbandwidth - - .dist-ubuntu22.04 - - .platform-amd64 - needs: - - image-nvbandwidth-ubuntu22.04 + OUT_REGISTRY: "${NGC_REGISTRY}" + OUT_REGISTRY_USER: "${NGC_REGISTRY_USER}" + OUT_REGISTRY_TOKEN: "${NGC_REGISTRY_TOKEN}" + OUT_IMAGE_NAME: "${NGC_STAGING_REGISTRY}/cuda-amples" + OUT_IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}" -scan-nvbandwidth-ubuntu22.04-arm64: +.release-images: extends: - - .scan - - .sample-nvbandwidth - - .dist-ubuntu22.04 - - .platform-arm64 + - .copy-images + stage: release needs: - - image-nvbandwidth-ubuntu22.04 - - scan-nvbandwidth-ubuntu22.04-amd64 - -# Define external release helpers -.release:ngc: - extends: - - .release:external + - scan-images + - push-images-to-staging variables: + IN_REGISTRY: "${CI_REGISTRY}" + IN_REGISTRY_USER: "${CI_REGISTRY_USER}" + IN_REGISTRY_TOKEN: "${CI_REGISTRY_PASSWORD}" + IN_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/cuda-amples" + IN_IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}" + + OUT_REGISTRY: "${NGC_REGISTRY}" OUT_REGISTRY_USER: "${NGC_REGISTRY_USER}" OUT_REGISTRY_TOKEN: "${NGC_REGISTRY_TOKEN}" - OUT_REGISTRY: "${NGC_REGISTRY}" OUT_IMAGE_NAME: "${NGC_REGISTRY_IMAGE}" + OUT_IMAGE_TAG: "${CI_COMMIT_TAG}" -# Define the external release targets -# Release to NGC -release:ngc-vectoradd-ubuntu22.04: - extends: - - .release:ngc - - .dist-ubuntu22.04 - - .sample-vectoradd - -release:ngc-device-query-ubuntu22.04: - extends: - - .release:ngc - - .dist-ubuntu22.04 - - .sample-device-query - -release:ngc-vectoradd-ubi9: - extends: - - .release:ngc - - .dist-ubi9 - - .sample-vectoradd - -release:ngc-nbody-ubuntu22.04: +release-images-to-ngc: extends: - - .release:ngc - - .dist-ubuntu22.04 - - .sample-nbody + - .release-images + rules: + - if: $CI_COMMIT_TAG -release:ngc-simple-multi-gpu-ubuntu22.04: +release-images-dummy: extends: - - .release:ngc - - .dist-ubuntu22.04 - - .sample-simple-multi-gpu - -release:ngc-vulkan-ubuntu22.04: + - .release-images + variables: + REGCTL: "echo [DUMMY] regctl" + rules: + - if: $CI_COMMIT_TAG == null || $CI_COMMIT_TAG == "" + +# .sign-images forms the base of the jobs which sign images in the NGC registry. +.sign-images: + stage: sign + image: ubuntu:latest + parallel: + matrix: + - SAMPLE: + - devicequery + - nbody + - nvbandwidth + - simplemultigpu + - vectoradd + - vulkan + variables: + IMAGE_NAME: "${NGC_REGISTRY_IMAGE}" + IMAGE_TAG: "${CI_COMMIT_TAG}" + NGC_CLI: "ngc-cli/ngc" + before_script: + - !reference [.ngccli-setup, before_script] + script: + - | + # We ensure that the IMAGE_NAME and IMAGE_TAG is set + echo Image Name: ${IMAGE_NAME} && [[ -n "${IMAGE_NAME}" ]] || exit 1 + echo Image Tag: ${IMAGE_TAG} && [[ -n "${IMAGE_TAG}" ]] || exit 1 + + export IMAGE=${IMAGE_NAME}:${SAMPLE}-${IMAGE_TAG} + echo "Signing the image ${IMAGE}" + ${NGC_CLI} registry image publish --source ${IMAGE} ${IMAGE} --public --discoverable --allow-guest --sign --org nvidia + +# Define the external image signing steps for NGC +# Download the ngc cli binary for use in the sign steps +.ngccli-setup: + before_script: + - apt-get update && apt-get install -y curl unzip jq + - | + if [ -z "${NGCCLI_VERSION}" ]; then + NGC_VERSION_URL="https://api.ngc.nvidia.com/v2/resources/nvidia/ngc-apps/ngc_cli/versions" + # Extract the latest version from the JSON data using jq + export NGCCLI_VERSION=$(curl -s $NGC_VERSION_URL | jq -r '.recipe.latestVersionIdStr') + fi + echo "NGCCLI_VERSION ${NGCCLI_VERSION}" + - curl -sSLo ngccli_linux.zip https://api.ngc.nvidia.com/v2/resources/nvidia/ngc-apps/ngc_cli/versions/${NGCCLI_VERSION}/files/ngccli_linux.zip + - unzip ngccli_linux.zip + - chmod u+x ngc-cli/ngc + +sign-ngc-images: extends: - - .release:ngc - - .dist-ubuntu22.04 - - .sample-vulkan + - .sign-images + needs: + - release-images-to-ngc + rules: + - if: $CI_COMMIT_TAG + variables: + NGC_CLI_API_KEY: "${NGC_REGISTRY_TOKEN}" + retry: + max: 2 -release:ngc-nvbandwidth-ubuntu22.04: +sign-images-dummy: extends: - - .release:ngc - - .dist-ubuntu22.04 - - .sample-nvbandwidth + - .sign-images + needs: + - release-images-dummy + variables: + NGC_CLI: "echo [DUMMY] ngc-cli/ngc" + IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}" + rules: + - if: $CI_COMMIT_TAG == null || $CI_COMMIT_TAG == "" diff --git a/deployments/container/Dockerfile.ubi9 b/deployments/container/Dockerfile similarity index 97% rename from deployments/container/Dockerfile.ubi9 rename to deployments/container/Dockerfile index d0ad12d..e48a3d0 100644 --- a/deployments/container/Dockerfile.ubi9 +++ b/deployments/container/Dockerfile @@ -14,8 +14,7 @@ FROM nvcr.io/nvidia/cuda:12.9.1-base-ubi9 AS builder -ARG CUDA_VERSION -RUN dnf install -y --allowerasing \ +RUN dnf install -y --allowerasing \ cmake \ cuda-cudart-devel-12-9 \ cuda-nvcc-12-9 \ @@ -37,6 +36,7 @@ RUN curl -L https://codeload.github.com/NVIDIA/cuda-samples/tar.gz/refs/tags/${C cp ${SAMPLE_NAME} /build/${SAMPLE_NAME} FROM nvcr.io/nvidia/cuda:12.9.1-base-ubi9 + ARG SAMPLE_NAME LABEL io.k8s.display-name="NVIDIA CUDA ${SAMPLE_NAME} sample" LABEL name="NVIDIA CUDA ${SAMPLE_NAME} sample" diff --git a/deployments/container/Dockerfile.ubuntu b/deployments/container/Dockerfile.ubuntu deleted file mode 100644 index 33afdf3..0000000 --- a/deployments/container/Dockerfile.ubuntu +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM nvcr.io/nvidia/cuda:12.9.1-base-ubuntu22.04 AS builder - -ARG SAMPLE_NAME -ENV SAMPLE_NAME=${SAMPLE_NAME} - -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - cmake \ - cuda-nvcc-12-9 \ - g++ \ - curl \ - && \ - rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -ARG TARGETARCH - -ARG CUDA_SAMPLES_VERSION=v12.9 -RUN curl -L https://codeload.github.com/NVIDIA/cuda-samples/tar.gz/refs/tags/${CUDA_SAMPLES_VERSION} | \ - tar -xzvf - --strip-components=1 --wildcards */${SAMPLE_NAME}/* --wildcards */Common/* && \ - cd $(find /build/Samples -iname "${SAMPLE_NAME}") && \ - cmake . && \ - make && \ - cp ${SAMPLE_NAME} /build/${SAMPLE_NAME} - -FROM nvcr.io/nvidia/cuda:12.9.1-base-ubuntu22.04 -ARG SAMPLE_NAME -LABEL io.k8s.display-name="NVIDIA CUDA ${SAMPLE_NAME} sample" -LABEL name="NVIDIA CUDA ${SAMPLE_NAME} sample" -LABEL vendor="NVIDIA" -LABEL version="1.0.0" -LABEL release="N/A" -LABEL summary="NVIDIA container to validate GPU support" -LABEL description="See summary" - -COPY ./LICENSE ./licenses/LICENSE - -RUN mkdir -p /cuda-samples -COPY --from=builder /build/${SAMPLE_NAME} /cuda-samples/${SAMPLE_NAME} - -RUN ln -s /cuda-samples/${SAMPLE_NAME} /cuda-samples/sample -ENTRYPOINT ["/cuda-samples/sample"] diff --git a/deployments/container/Makefile b/deployments/container/Makefile index b7a8d78..90ccb78 100644 --- a/deployments/container/Makefile +++ b/deployments/container/Makefile @@ -12,100 +12,45 @@ # See the License for the specific language governing permissions and # limitations under the License. -BUILD_MULTI_ARCH_IMAGES ?= false +BUILD_MULTI_ARCH_IMAGES ?= true DOCKER ?= docker -BUILDX = +BUILDX ?= buildx MKDIR ?= mkdir include $(CURDIR)/versions.mk -# The Makefile describes the build process for a single CUDA sample: e.g. `vectorAdd` -ifeq ($(SAMPLE),) -# Use vectorAdd as the default sample - SAMPLE := vectorAdd -endif -LOWER_CASE_SAMPLE := $(shell echo $(SAMPLE) | tr '[:upper:]' '[:lower:]') +IMAGE_VERSION := $(VERSION) -IMAGE_VERSION := $(LOWER_CASE_SAMPLE)-$(VERSION) - -IMAGE_TAG ?= $(IMAGE_VERSION)-$(DIST) +IMAGE_TAG ?= $(SAMPLE)-$(VERSION) IMAGE = $(IMAGE_NAME):$(IMAGE_TAG) -OUT_IMAGE_NAME ?= $(IMAGE_NAME) -OUT_IMAGE_VERSION ?= $(VERSION) -OUT_IMAGE_TAG ?= $(LOWER_CASE_SAMPLE)-$(OUT_IMAGE_VERSION)-$(DIST) -OUT_IMAGE = $(OUT_IMAGE_NAME):$(OUT_IMAGE_TAG) - -DEFAULT_PUSH_TARGET := ubuntu22.04 -DISTRIBUTIONS := ubuntu22.04 ubi9 +SAMPLES := vectoradd nbody devicequery simplemultigpu vulkan nvbandwidth -IMAGE_TARGETS := $(patsubst %,image-%,$(DISTRIBUTIONS)) -BUILD_TARGETS := $(patsubst %,build-%,$(DISTRIBUTIONS)) -PUSH_TARGETS := $(patsubst %,push-%,$(DISTRIBUTIONS)) -TEST_TARGETS := $(patsubst %,test-%,$(DISTRIBUTIONS)) +IMAGE_TARGETS := $(patsubst %,image-%,$(SAMPLES)) +BUILD_TARGETS := $(patsubst %,build-%,$(SAMPLES)) -.PHONY: $(DISTRIBUTIONS) $(PUSH_TARGETS) $(BUILD_TARGETS) $(TEST_TARGETS) +.PHONY: $(SAMPLES) $(BUILD_TARGETS) $(IMAGE_TARGETS) # Certain samples do not allow multi-arch images. We disable them here. # TODO: Does it make more sense to set this at a CI-level? -AMD64_SAMPLES = vulkan -ARM64_SAMPLES = -SINGLE_ARCH_SAMPLES = nbody $(AMD64_SAMPLES) $(ARM64_SAMPLES) -ifeq ($(SAMPLE),$(filter $(SAMPLE),$(SINGLE_ARCH_SAMPLES))) -$(info Using single-architecture for $(SAMPLE)) -BUILD_MULTI_ARCH_IMAGES = false -# Certain samples are only supported on AMD64. -ifeq ($(SAMPLE),$(filter $(SAMPLE),$(AMD64_SAMPLES))) -ARCH = amd64 -endif -# Certain samples are only supported on AMD64. -ifeq ($(SAMPLE),$(filter $(SAMPLE),$(ARM64_SAMPLES))) -ARCH = arm64 -endif -endif - -# If BUILD_MULTI_ARCH_IMAGES is still true for a given set of samples, we enable buildx. -ifeq ($(BUILD_MULTI_ARCH_IMAGES),true) -BUILDX = buildx -endif - -ifneq ($(BUILD_MULTI_ARCH_IMAGES),true) -include $(CURDIR)/deployments/container/native-only.mk -else -include $(CURDIR)/deployments/container/multi-arch.mk -endif +image-nbody: DOCKER_BUILD_PLATFORM_OPTIONS = --platform=linux/$(ARCH) +image-vulkan: DOCKER_BUILD_PLATFORM_OPTIONS = --platform=linux/$(ARCH) -push-%: DIST = $(*) -push-short: DIST = $(DEFAULT_PUSH_TARGET) -push-sample: DIST = $(DEFAULT_PUSH_TARGET) +image-%: SAMPLE = $(*) +image-%: SAMPLE_NAME = $(*) +image-%: DOCKERFILE = $(CURDIR)/deployments/container/$(*)/Dockerfile +image-%: ARCH ?= $(shell uname -m) +image-%: DOCKER_BUILD_OPTIONS = --output=type=image,push=$(PUSH_ON_BUILD) +image-%: DOCKER_BUILD_PLATFORM_OPTIONS = --platform=linux/amd64,linux/arm64 -# For the default push target we also push a short tag equal to the version. -# We skip this for the development release -DEVEL_RELEASE_IMAGE_VERSION ?= devel -PUSH_MULTIPLE_TAGS ?= true -PUSH_SAMPLE_ONLY_TAG ?= false -ifeq ($(strip $(OUT_IMAGE_VERSION)),$(DEVEL_RELEASE_IMAGE_VERSION)) -PUSH_MULTIPLE_TAGS = false -endif -ifeq ($(PUSH_MULTIPLE_TAGS),true) -push-$(DEFAULT_PUSH_TARGET): push-short -# If required we retag and push the image tagged only with the sample name -ifeq ($(PUSH_SAMPLE_ONLY_TAG),true) -push-$(DEFAULT_PUSH_TARGET): push-sample -endif -endif +# TODO: We should switch to single ubi9 images where possible +image-devicequery: DOCKERFILE = $(CURDIR)/deployments/container/Dockerfile +image-devicequery: SAMPLE_NAME = deviceQuery +image-simplemultigpu: DOCKERFILE = $(CURDIR)/deployments/container/Dockerfile +image-simplemultigpu: SAMPLE_NAME = simpleMultiGPU +image-vectoradd: DOCKERFILE = $(CURDIR)/deployments/container/Dockerfile +image-vectoradd: SAMPLE_NAME = vectorAdd -build-%: DIST = $(*) -# For the following samples, we use specific Dockerfiles: -ifeq ($(SAMPLE),$(filter $(SAMPLE),nbody nvbandwidth vulkan)) -build-%: DOCKERFILE = $(CURDIR)/deployments/container/$(SAMPLE)/Dockerfile -else -build-%: DOCKERFILE = $(CURDIR)/deployments/container/Dockerfile.$(DOCKERFILE_SUFFIX) -endif - -build-ubuntu%: DOCKERFILE_SUFFIX = ubuntu - -build-ubi9: DOCKERFILE_SUFFIX = ubi9 # Use a generic build target to build the relevant images $(IMAGE_TARGETS): image-%: @@ -116,23 +61,8 @@ $(IMAGE_TARGETS): image-%: $(DOCKER_BUILD_PLATFORM_OPTIONS) \ --tag $(IMAGE) \ --build-arg CUDA_SAMPLES_VERSION="$(CUDA_SAMPLES_VERSION)" \ - --build-arg SAMPLE_NAME=$(SAMPLE) \ + --build-arg SAMPLE_NAME=$(SAMPLE_NAME) \ -f $(DOCKERFILE) \ $(CURDIR) -# Handle the default build target. -.PHONY: build -build: $(DEFAULT_PUSH_TARGET) -$(DEFAULT_PUSH_TARGET): build-$(DEFAULT_PUSH_TARGET) -$(DEFAULT_PUSH_TARGET): DIST = $(DEFAULT_PUSH_TARGET) - -REGCTL ?= regctl -$(PUSH_TARGETS): push-%: - $(REGCTL) \ - image copy \ - $(IMAGE) $(OUT_IMAGE) - -push-short: - $(REGCTL) \ - image copy \ - $(IMAGE) $(OUT_IMAGE_NAME):$(OUT_IMAGE_VERSION) +$(BUILD_TARGETS): build-%: image-% diff --git a/deployments/container/multi-arch.mk b/deployments/container/multi-arch.mk deleted file mode 100644 index 33cedca..0000000 --- a/deployments/container/multi-arch.mk +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -PUSH_ON_BUILD ?= false -DOCKER_BUILD_OPTIONS = --output=type=image,push=$(PUSH_ON_BUILD) -DOCKER_BUILD_PLATFORM_OPTIONS = --platform=linux/amd64,linux/arm64 - -$(BUILD_TARGETS): build-%: image-% \ No newline at end of file diff --git a/deployments/container/native-only.mk b/deployments/container/native-only.mk deleted file mode 100644 index c5e9ba4..0000000 --- a/deployments/container/native-only.mk +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -PUSH_ON_BUILD ?= false -ARCH ?= $(shell uname -m) -DOCKER_BUILD_PLATFORM_OPTIONS = --platform=linux/$(ARCH) - -ifeq ($(PUSH_ON_BUILD),true) -$(BUILD_TARGETS): build-%: image-% - $(DOCKER) push "$(IMAGE)" -else -$(BUILD_TARGETS): build-%: image-% -endif - -# For the default distribution we also retag the image. -# Note: This needs to be updated for multi-arch images. -ifeq ($(IMAGE_TAG),$(VERSION)-$(DIST)) -$(DEFAULT_PUSH_TARGET): - $(DOCKER) image inspect $(IMAGE) > /dev/null || $(DOCKER) pull $(IMAGE) - $(DOCKER) tag $(IMAGE) $(subst :$(IMAGE_TAG),:$(VERSION),$(IMAGE)) -endif diff --git a/hack/publish-images.sh b/hack/publish-images.sh new file mode 100755 index 0000000..9b255c9 --- /dev/null +++ b/hack/publish-images.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is used to publish images to a registry. It checks whether the image +# already exists in the registry and skips publishing if it does. This can be overridden +# using the FORCE_PUBLISH_IMAGES environment variable. + +set -ex + +: ${DOCKER=docker} +: ${REGCTL=regctl} + +# publish_docker uses docker to publish an image. +# In this case, the image is first retagged (if required) and then pushed. +function publish_docker() { + if [[ "${1}" != "${2}" ]]; then + ${DOCKER} tag ${1} ${2} + fi + ${DOCKER} push ${2} +} + +# publish_regctl uses regctl to copy an image from one registry to another. +# If the two images are the same, this is a no-op. +function publish_regctl() { + if [[ "${1}" != "${2}" ]]; then + ${REGCTL} image copy ${1} ${2} + fi +} + +function publish() { + if [[ $(command -v ${REGCTL}) || x"${BUILD_MULTI_ARCH_IMAGES}" == x"true" ]]; then + publish_regctl $@ + else + publish_docker $@ + fi +} + +INPUT_IMAGE=$1 +shift +if [[ x"${SKIP_FIRST_IMAGE_ON_PUBLISH}" == x"true" ]]; then + shift +fi + +for OUTPUT_IMAGE in "${@}"; do + echo "Publishing ${INPUT_IMAGE} as ${OUTPUT_IMAGE}" + publish ${INPUT_IMAGE} ${OUTPUT_IMAGE} +done diff --git a/versions.mk b/versions.mk index 06e68b7..13932a8 100644 --- a/versions.mk +++ b/versions.mk @@ -13,7 +13,7 @@ # limitations under the License. # Specify the CUDA base image version -VERSION ?= cuda$(shell grep -Eo "FROM.*cuda:[0-9\.]+" deployments/container/Dockerfile.ubuntu | sort -u | sed 's/.*://g') +VERSION ?= cuda$(shell grep -Eo "FROM.*cuda:[0-9\.]+" deployments/container/Dockerfile | sort -u | sed 's/.*://g') # Specify the tag for the https://github.com/NVIDIA/cuda-samples repository. # This need not match the CUDA_VERSION above.