From 37423aa5763835c6b1bc3d17ba0585fbdc9e2963 Mon Sep 17 00:00:00 2001 From: Rajat Chopra Date: Wed, 3 Dec 2025 13:33:53 -0800 Subject: [PATCH 1/2] ci workflow with amd support only Signed-off-by: Rajat Chopra --- .common-ci.yml | 145 +++++++++++++ .github/copy-pr-bot.yaml | 3 + .github/dependabot.yml | 9 +- .github/workflows/ci.yaml | 48 +++++ .github/workflows/code_scanning.yaml | 53 +++++ .github/workflows/golang.yaml | 80 +++++++ .github/workflows/images.yaml | 105 ++++++++++ .gitlab-ci.yml | 36 ++++ .nvidia-ci.yml | 219 ++++++++++++++++++++ Dockerfile | 13 +- Makefile | 2 +- deployments/container/Dockerfile.distroless | 73 +++++++ deployments/container/Makefile | 87 ++++++++ deployments/container/multi-arch.mk | 24 +++ deployments/container/native-only.mk | 22 ++ deployments/devel/Dockerfile | 26 +++ deployments/devel/Makefile | 43 ++++ deployments/devel/tools.go | 26 +++ scripts/golang-version.sh | 22 ++ versions.mk | 25 +++ 20 files changed, 1057 insertions(+), 4 deletions(-) create mode 100644 .common-ci.yml create mode 100644 .github/copy-pr-bot.yaml create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/code_scanning.yaml create mode 100644 .github/workflows/golang.yaml create mode 100644 .github/workflows/images.yaml create mode 100644 .gitlab-ci.yml create mode 100644 .nvidia-ci.yml create mode 100644 deployments/container/Dockerfile.distroless create mode 100644 deployments/container/Makefile create mode 100644 deployments/container/multi-arch.mk create mode 100644 deployments/container/native-only.mk create mode 100644 deployments/devel/Dockerfile create mode 100644 deployments/devel/Makefile create mode 100644 deployments/devel/tools.go create mode 100755 scripts/golang-version.sh create mode 100644 versions.mk diff --git a/.common-ci.yml b/.common-ci.yml new file mode 100644 index 00000000..1e59eeb2 --- /dev/null +++ b/.common-ci.yml @@ -0,0 +1,145 @@ +# Copyright (c) 2021-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. + +default: + image: docker:dind + services: + - name: docker:dind + command: ["--experimental"] + +variables: + BUILD_MULTI_ARCH_IMAGES: "true" + +stages: + - image-build + - test + - scan + - release + - ngc-publish + +# Define the distribution targets +.dist-distroless: + variables: + DIST: distroless + +# Define the platform targets +.platform-amd64: + variables: + PLATFORM: linux/amd64 + +.platform-arm64: + variables: + PLATFORM: linux/arm64 + +# Make buildx available as a docker CLI plugin +.buildx-setup: + before_script: + - export BUILDX_VERSION=v0.16.0 + - 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' + +# Define test helpers +.integration: + stage: test + variables: + VERSION: "${CI_COMMIT_SHORT_SHA}" + IMAGE_NAME: "${CI_REGISTRY_IMAGE}" + except: + variables: + - $CI_COMMIT_MESSAGE =~ /\[skip[ _-]tests?\]/i + - $SKIP_TESTS + before_script: + - apk add --no-cache make bash jq + - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" + - docker pull "${IMAGE_NAME}:${VERSION}" + script: + - make -f deployments/container/Makefile test-${DIST} + +# Download the regctl binary for use in the release steps +.regctl-setup: + before_script: + - export REGCTL_VERSION=v0.7.0 + - 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}" + 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' + # In the case where we are deploying a different version to the CI_COMMIT_SHA, we + # need to tag the image. + # Note: a leading 'v' is stripped from the version if present + - apk add --no-cache make bash + script: + - '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: "${NGC_REGISTRY_USER}" + OUT_REGISTRY_TOKEN: "${NGC_REGISTRY_TOKEN}" + OUT_REGISTRY: "${NGC_REGISTRY}" + OUT_IMAGE_NAME: "${NGC_STAGING_REGISTRY}/nvidia-sandbox-device-plugin" + +# Define an external release step that pushes an image to an external repository. +# This includes a devlopment image off master. +.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-distroless: + extends: + - .release:staging + - .dist-distroless + needs: + - image-distroless diff --git a/.github/copy-pr-bot.yaml b/.github/copy-pr-bot.yaml new file mode 100644 index 00000000..f4b26b73 --- /dev/null +++ b/.github/copy-pr-bot.yaml @@ -0,0 +1,3 @@ +# https://docs.gha-runners.nvidia.com/platform/apps/copy-pr-bot/#configuration + +enabled: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ba66a149..1934b2ac 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,8 +8,15 @@ updates: directory: "/" schedule: interval: "daily" + open-pull-requests-limit: 10 labels: - - dependencies + - dependencies + groups: + k8sio: + patterns: + - k8s.io/* + exclude-patterns: + - k8s.io/klog/* - package-ecosystem: "docker" directory: "/" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..d5d7a031 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,48 @@ +# Copyright 2025 NVIDIA CORPORATION +# +# 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. + +name: CI Pipeline + +on: + push: + branches: + - "pull-request/[0-9]+" + - main + - ci + - release-* + +jobs: + code-scanning: + uses: ./.github/workflows/code_scanning.yaml + + variables: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Generate Commit Short SHA + id: version + run: echo "version=$(echo $GITHUB_SHA | cut -c1-8)" >> "$GITHUB_OUTPUT" + + golang: + needs: [variables] + secrets: inherit + uses: ./.github/workflows/golang.yaml + + image: + uses: ./.github/workflows/images.yaml + needs: [variables, golang, code-scanning] + secrets: inherit + with: + version: ${{ needs.variables.outputs.version }} diff --git a/.github/workflows/code_scanning.yaml b/.github/workflows/code_scanning.yaml new file mode 100644 index 00000000..cec5c040 --- /dev/null +++ b/.github/workflows/code_scanning.yaml @@ -0,0 +1,53 @@ +# Copyright 2025 NVIDIA CORPORATION +# +# 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. + +name: "CodeQL" + +on: + workflow_call: {} + pull_request: + types: + - opened + - synchronize + branches: + - main + - ci + - release-* + +jobs: + analyze: + name: Analyze Go code with CodeQL + runs-on: ubuntu-latest + timeout-minutes: 360 + permissions: + security-events: write + packages: read + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: go + build-mode: manual + + - shell: bash + run: | + make build + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:go" diff --git a/.github/workflows/golang.yaml b/.github/workflows/golang.yaml new file mode 100644 index 00000000..47ec8422 --- /dev/null +++ b/.github/workflows/golang.yaml @@ -0,0 +1,80 @@ +# Copyright 2025 NVIDIA CORPORATION +# +# 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. + +name: Golang + +on: + workflow_call: {} + +jobs: + test: + name: Unit test + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Get Golang version + id: vars + run: | + GOLANG_VERSION=$(./scripts/golang-version.sh) + echo "GOLANG_VERSION=${GOLANG_VERSION##GOLANG_VERSION := }" >> $GITHUB_ENV + + - name: Install Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GOLANG_VERSION }} + + - name: Run unit tests + run: make test + + - name: Generate coverage report + run: make coverage + + - name: Upload to Coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + file: coverage.out + + build: + name: Build + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Get Golang version + id: vars + run: | + GOLANG_VERSION=$(./scripts/golang-version.sh) + echo "GOLANG_VERSION=${GOLANG_VERSION##GOLANG_VERSION ?= }" >> $GITHUB_ENV + + - name: Install Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GOLANG_VERSION }} + +# - name: Setup Go Proxy +# id: setup-go-proxy +# uses: nv-gha-runners/setup-artifactory-go-proxy@main +# - env: +# GOPROXY: ${{ steps.setup-go-proxy.outputs.goproxy-url }} + + - name: Build + run: | + make build diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml new file mode 100644 index 00000000..895f3402 --- /dev/null +++ b/.github/workflows/images.yaml @@ -0,0 +1,105 @@ +# Copyright 2024 NVIDIA CORPORATION +# +# 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. + +# Run this workflow on pull requests or merge to main/release branches +name: Image + +on: + workflow_call: + inputs: + version: + required: true + type: string + +jobs: + build: + strategy: + matrix: + arch: + - amd64 +# - arm64 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + name: Check out code + - name: Calculate build vars + id: vars + run: | + echo "COMMIT_SHORT_SHA=${GITHUB_SHA:0:8}" >> $GITHUB_ENV + echo "LOWERCASE_REPO_OWNER=$(echo "${GITHUB_REPOSITORY_OWNER}" | awk '{print tolower($0)}')" >> $GITHUB_ENV + REPO_FULL_NAME="${{ github.event.pull_request.head.repo.full_name }}" + echo "${REPO_FULL_NAME}" + echo "LABEL_IMAGE_SOURCE=https://github.com/${REPO_FULL_NAME}" >> $GITHUB_ENV + + GENERATE_ARTIFACTS="false" + if [[ "${{ github.actor }}" == "dependabot[bot]" ]]; then + GENERATE_ARTIFACTS="false" + elif [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]]; then + GENERATE_ARTIFACTS="true" + elif [[ "${{ github.event_name }}" == "push" ]]; then + GENERATE_ARTIFACTS="true" + fi + echo "PUSH_ON_BUILD=${GENERATE_ARTIFACTS}" >> $GITHUB_ENV + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build image + env: + IMAGE_NAME: ghcr.io/${LOWERCASE_REPO_OWNER}/nvidia-sandbox-device-plugin + VERSION: ${COMMIT_SHORT_SHA}-${{ matrix.arch }} + DOCKER_BUILD_PLATFORM_OPTIONS: "--platform=linux/${{ matrix.arch }}" + run: | + echo "${VERSION}" + make -f deployments/container/Makefile build + + create-manifest: + needs: [ build ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + name: Check out code + - name: Calculate build vars + id: vars + run: | + echo "COMMIT_SHORT_SHA=${GITHUB_SHA:0:8}" >> $GITHUB_ENV + echo "LOWERCASE_REPO_OWNER=$(echo "${GITHUB_REPOSITORY_OWNER}" | awk '{print tolower($0)}')" >> $GITHUB_ENV + + GENERATE_ARTIFACTS="false" + if [[ "${{ github.actor }}" == "dependabot[bot]" ]]; then + GENERATE_ARTIFACTS="false" + elif [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]]; then + GENERATE_ARTIFACTS="true" + elif [[ "${{ github.event_name }}" == "push" ]]; then + GENERATE_ARTIFACTS="true" + fi + + echo "GENERATE_ARTIFACTS=${GENERATE_ARTIFACTS}" >> $GITHUB_ENV + - name: Login to GitHub Container Registry + if: ${{ env.GENERATE_ARTIFACTS == 'true' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build Manifest + if: ${{ env.GENERATE_ARTIFACTS == 'true' }} + env: + MULTIARCH_IMAGE: ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/nvidia-sandbox-device-plugin:${{ env.COMMIT_SHORT_SHA }} + run: | + docker buildx imagetools create \ + --tag ${MULTIARCH_IMAGE} \ + ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/nvidia-sandbox-device-plugin:${{ env.COMMIT_SHORT_SHA }}-amd64 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..2ee8d5b2 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,36 @@ +# Copyright (c) 2021-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. + +include: + - local: '.common-ci.yml' + +# Define the image build targets +.image-build: + stage: image-build + variables: + IMAGE_NAME: "${CI_REGISTRY_IMAGE}" + VERSION: "${CI_COMMIT_SHORT_SHA}" + PUSH_ON_BUILD: "true" + before_script: + - !reference [.buildx-setup, before_script] + - apk add --no-cache bash make + - 'echo "Logging in to CI registry ${CI_REGISTRY}"' + - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" + script: + - make -f deployments/container/Makefile build-${DIST} + +image-ubi9: + extends: + - .image-build + - .dist-distroless diff --git a/.nvidia-ci.yml b/.nvidia-ci.yml new file mode 100644 index 00000000..fc54e822 --- /dev/null +++ b/.nvidia-ci.yml @@ -0,0 +1,219 @@ +# Copyright (c) 2021-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. + +include: + - local: '.common-ci.yml' + +default: + tags: + - cnt + - container-dev + - docker/multi-arch + - docker/privileged + - os/linux + - type/docker + +variables: + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "/certs" + # Release "devel"-tagged images off the master branch + RELEASE_DEVEL_BRANCH: "main" + DEVEL_RELEASE_IMAGE_VERSION: "devel" + # On the multi-arch builder we don't need the qemu setup. + SKIP_QEMU_SETUP: "1" + # Define the public staging registry + STAGING_REGISTRY: ghcr.io/nvidia + STAGING_VERSION: ${CI_COMMIT_SHORT_SHA} + +.image-pull: + stage: image-build + variables: + IN_REGISTRY: "${STAGING_REGISTRY}" + IN_IMAGE_NAME: nvidia-sandbox-device-plugin + IN_VERSION: "${STAGING_VERSION}" + OUT_REGISTRY_USER: "${CI_REGISTRY_USER}" + OUT_REGISTRY_TOKEN: "${CI_REGISTRY_PASSWORD}" + OUT_REGISTRY: "${CI_REGISTRY}" + OUT_IMAGE_NAME: "${CI_REGISTRY_IMAGE}" + PUSH_MULTIPLE_TAGS: "false" + # We delay the job start to allow the public pipeline to generate the required images. + 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} --list > /dev/null && echo "${IN_REGISTRY}/${IN_IMAGE_NAME}:${IN_VERSION}" || ( echo "${IN_REGISTRY}/${IN_IMAGE_NAME}:${IN_VERSION} 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} OUT_IMAGE=${OUT_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA} push-${DIST} + +image-distroless: + extends: + - .image-pull + - .dist-distroless + +# We skip the integration tests for the internal CI: +.integration: + stage: test + before_script: + - echo "Skipped in internal CI" + script: + - echo "Skipped in internal CI" + +# The .scan step forms the base of the image scan operation performed before releasing +# images. +.scan: + stage: scan + image: "${PULSE_IMAGE}" + variables: + IMAGE: "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}" + IMAGE_ARCHIVE: "nvidia-sandbox-device-plugin.tar" + except: + variables: + - $CI_COMMIT_MESSAGE =~ /\[skip[ _-]scans?\]/i + - $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 + script: + - pulse-cli -n $NSPECT_ID --ssa $SSA_TOKEN scan -i $IMAGE_ARCHIVE -p $CONTAINER_POLICY -o + artifacts: + when: always + expire_in: 1 week + paths: + - pulse-cli.log + - licenses.json + - sbom.json + - vulns.json + - policy_evaluation.json + +# The .scan-distroless steps forms the base for all distroless image scans across supported architectures +.scan-distroless: + extends: + - .scan + - .dist-distroless + needs: + - image-distroless + +# Define the scan targets +scan-distroless-amd64: + extends: + - .scan-distroless + - .platform-amd64 + +scan-distroless-arm64: + extends: + - .scan-distroless + - .platform-arm64 + # For now, run the scans sequentially to avoid any issues + # when pulling the same tag, but different arch, on the gitlab runner + needs: + - scan-distroless-amd64 + +.ngc-publish-variables: + before_script: + - | + if [ -n "${CI_COMMIT_TAG}" ]; then + echo "${CI_COMMIT_SHORT_SHA} ${CI_COMMIT_TAG}" > build-info-${CI_PIPELINE_ID}.txt + else + echo "${CI_COMMIT_SHORT_SHA} ${CI_COMMIT_SHORT_SHA}" > build-info-${CI_PIPELINE_ID}.txt + fi + +.update-nspect: + stage: ngc-publish + needs: + - job: release:staging-distroless + extends: + - .ngc-publish-variables + image: + name: "${CNT_NGC_PUBLISH_IMAGE}" + pull_policy: always + variables: + PROJECT_NAME: "nvidia-sandbox-device-plugin" + REPO_URL: "https://github.com/NVIDIA/sandbox-device-plugin.git" + script: + - | + cnt-ngc-publish nspect --versions-file "build-info-${CI_PIPELINE_ID}.txt" + +# Update the nspect staging environment to test the nspect publishing logic +update-nspect-staging: + extends: + - .update-nspect + except: + - tags + variables: + ENV: "stage" + RELEASE_VERSION: "test" + NSPECT_CLIENT_ID: "${NSPECT_STAGING_CLIENT_ID}" + NSPECT_CLIENT_SECRET: "${NSPECT_STAGING_CLIENT_SECRET}" + +# Update the nspect production environment with the new release +update-nspect: + extends: + - .update-nspect + rules: + - if: $CI_COMMIT_TAG + variables: + OSRB_BUG_ID: "${OSRB_BUG_ID}" + ENV: "prod" + RELEASE_VERSION: "${CI_COMMIT_TAG}" + NSPECT_CLIENT_ID: "${NSPECT_PROD_CLIENT_ID}" + NSPECT_CLIENT_SECRET: "${NSPECT_PROD_CLIENT_SECRET}" + +.publish-images: + stage: ngc-publish + extends: + - .ngc-publish-variables + image: + name: "${CNT_NGC_PUBLISH_IMAGE}" + pull_policy: always + variables: + GITLAB_ACCESS_TOKEN: "${CNT_GITLAB_TOKEN}" + script: + - cnt-ngc-publish render --project-name "nvidia-sandbox-device-plugin" --versions-file "build-info-${CI_PIPELINE_ID}.txt" --output nvidia-sandbox-device-plugin.yaml + - cnt-ngc-publish merge-request --files "nvidia-sandbox-device-plugin.yaml" + +# Raise an MR to publish the image to NGC +ngc-image-publish: + extends: + - .publish-images + rules: + - if: $CI_COMMIT_TAG + needs: + - job: update-nspect + variables: + NGC_PUBLISHING_PROJECT_PATH: "${NGC_PUBLISHING_PROD_PROJECT_PATH}" + +# Create a dummy MR that exercises the publishing logic +mock-image-publish: + extends: + - .publish-images + except: + - tags + needs: + - job: update-nspect-staging + variables: + NGC_PUBLISHING_PROJECT_PATH: "${NGC_PUBLISHING_TEST_PROJECT_PATH}" diff --git a/Dockerfile b/Dockerfile index f215ea66..5843ad2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,8 +28,17 @@ FROM nvcr.io/nvidia/cuda:12.9.1-base-ubi9 as builder RUN yum install -y wget make gcc -ARG GOLANG_VERSION=1.24.7 -RUN wget -nv -O - https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz \ +ARG GOLANG_VERSION=1.25.3 +RUN set -eux; \ + \ + arch="$(uname -m)"; \ + case "${arch##*-}" in \ + x86_64 | amd64) ARCH='amd64' ;; \ + ppc64el | ppc64le) ARCH='ppc64le' ;; \ + aarch64 | arm64) ARCH='arm64' ;; \ + *) echo "unsupported architecture" ; exit 1 ;; \ + esac; \ + wget -nv -O - https://go.dev/dl/go${GOLANG_VERSION}.linux-${ARCH}.tar.gz \ | tar -C /usr/local -xz ENV GOPATH /go diff --git a/Makefile b/Makefile index 80e96c05..06d06932 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ build: go build -o nvidia-sandbox-device-plugin ./cmd test: go test ./... -coverprofile=coverage.out -v -test-coverage: +coverage: go tool cover -html=coverage.out clean: rm -f nvidia-sandbox-device-plugin && rm -rf coverage.out diff --git a/deployments/container/Dockerfile.distroless b/deployments/container/Dockerfile.distroless new file mode 100644 index 00000000..f7b820d5 --- /dev/null +++ b/deployments/container/Dockerfile.distroless @@ -0,0 +1,73 @@ +# Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM nvcr.io/nvidia/cuda:12.9.1-base-ubi9 as builder + +RUN yum install -y wget make gcc + +ARG GOLANG_VERSION=1.25.3 +RUN set -eux; \ + \ + arch="$(uname -m)"; \ + case "${arch##*-}" in \ + x86_64 | amd64) ARCH='amd64' ;; \ + ppc64el | ppc64le) ARCH='ppc64le' ;; \ + aarch64 | arm64) ARCH='arm64' ;; \ + *) echo "unsupported architecture" ; exit 1 ;; \ + esac; \ + wget -nv -O - https://go.dev/dl/go${GOLANG_VERSION}.linux-${ARCH}.tar.gz \ + | tar -C /usr/local -xz + +ENV GOPATH /go +ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH + +ENV GOOS=linux\ + GOARCH=amd64 + +WORKDIR /go/src/sandbox-device-plugin + +COPY . . + +RUN make build + +FROM nvcr.io/nvidia/distroless/go:v3.1.11 + +ARG VERSION + +LABEL io.k8s.display-name="NVIDIA Sandbox Device Plugin" +LABEL name="NVIDIA Sandbox Device Plugin" +LABEL vendor="NVIDIA" +LABEL version="${VERSION}" +LABEL release="N/A" +LABEL summary="NVIDIA Sandbox Device Plugin" +LABEL description="See summary" + +COPY --from=builder /go/src/sandbox-device-plugin/nvidia-sandbox-device-plugin /usr/bin/ +COPY --from=builder /go/src/sandbox-device-plugin/utils/pci.ids /usr/pci.ids + +USER 0:0 + +CMD ["nvidia-sandbox-device-plugin"] diff --git a/deployments/container/Makefile b/deployments/container/Makefile new file mode 100644 index 00000000..f37e25de --- /dev/null +++ b/deployments/container/Makefile @@ -0,0 +1,87 @@ +# Copyright (c) 2021-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. + +BUILD_MULTI_ARCH_IMAGES ?= no +DOCKER ?= docker + +##### Global variables ##### +include $(CURDIR)/versions.mk + +ifeq ($(IMAGE_NAME),) +REGISTRY ?= nvidia +IMAGE_NAME := $(REGISTRY)/nvidia-sandbox-device-plugin +endif + +GOPROXY ?= https://proxy.golang.org,direct + +IMAGE_VERSION := $(VERSION) + +IMAGE = $(IMAGE_NAME):$(IMAGE_VERSION) + +OUT_IMAGE_NAME ?= $(IMAGE_NAME) +OUT_IMAGE_VERSION ?= $(IMAGE_VERSION) +OUT_IMAGE = $(OUT_IMAGE_NAME):$(OUT_IMAGE_VERSION) + +##### Public rules ##### +DISTRIBUTIONS := distroless +DEFAULT_PUSH_TARGET := distroless + +PUSH_TARGETS := $(patsubst %, push-%, $(DISTRIBUTIONS)) +BUILD_TARGETS := $(patsubst %, build-%, $(DISTRIBUTIONS)) +TEST_TARGETS := $(patsubst %, build-%, $(DISTRIBUTIONS)) + +.PHONY: $(DISTRIBUTIONS) $(PUSH_TARGETS) $(BUILD_TARGETS) $(TEST_TARGETS) + +ifneq ($(BUILD_MULTI_ARCH_IMAGES),true) +include $(CURDIR)/deployments/container/native-only.mk +else +include $(CURDIR)/deployments/container/multi-arch.mk +endif + +# Both distroless and build-distroless trigger a build of the relevant image +$(DISTRIBUTIONS): %: build-% + +build-%: DOCKERFILE_SUFFIX = $(*) +build-%: DOCKERFILE = $(CURDIR)/deployments/container/Dockerfile.$(DOCKERFILE_SUFFIX) +$(BUILD_TARGETS): build-%: + $(DOCKER) build --pull \ + $(DOCKER_BUILD_OPTIONS) \ + $(DOCKER_BUILD_PLATFORM_OPTIONS) \ + --tag $(IMAGE) \ + --build-arg GOLANG_VERSION="$(GOLANG_VERSION)" \ + --build-arg VERSION="$(VERSION)" \ + --build-arg GIT_COMMIT="$(GIT_COMMIT)" \ + --build-arg CVE_UPDATES="$(CVE_UPDATES)" \ + --build-arg GOPROXY="$(GOPROXY)" \ + --file $(DOCKERFILE) \ + $(CURDIR) +ifeq ($(PUSH_ON_BUILD),true) + $(DOCKER) push "$(IMAGE)" +endif + +# Handle the default build target. +.PHONY: build +build: $(DEFAULT_PUSH_TARGET) + +.PHONY: bump-commit +BUMP_COMMIT := Bump to version $(VERSION) +bump-commit: + @git log | if [ ! -z "$$(grep -o '$(BUMP_COMMIT)' | sort -u)" ]; then \ + echo "\nERROR: '$(BUMP_COMMIT)' already committed\n"; \ + exit 1; \ + fi + @git add versions.mk + @git commit -m "$(BUMP_COMMIT)" + @echo "Applied the diff:" + @git --no-pager diff HEAD~1 diff --git a/deployments/container/multi-arch.mk b/deployments/container/multi-arch.mk new file mode 100644 index 00000000..55afe73d --- /dev/null +++ b/deployments/container/multi-arch.mk @@ -0,0 +1,24 @@ +# 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 +ATTACH_ATTESTATIONS ?= false +DOCKER_BUILD_OPTIONS = --output=type=image,push=$(PUSH_ON_BUILD) --provenance=$(ATTACH_ATTESTATIONS) --sbom=$(ATTACH_ATTESTATIONS) +DOCKER_BUILD_PLATFORM_OPTIONS ?= --platform=linux/amd64,linux/arm64 + +REGCTL ?= regctl +$(PUSH_TARGETS): push-%: + $(REGCTL) \ + image copy \ + $(IMAGE) $(OUT_IMAGE) diff --git a/deployments/container/native-only.mk b/deployments/container/native-only.mk new file mode 100644 index 00000000..399bfe57 --- /dev/null +++ b/deployments/container/native-only.mk @@ -0,0 +1,22 @@ +# 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 +ATTACH_ATTESTATIONS ?= false +DOCKER_BUILD_PLATFORM_OPTIONS ?= --platform=linux/amd64 +DOCKER_BUILD_OPTIONS = --output=type=image,push=$(PUSH_ON_BUILD) --provenance=$(ATTACH_ATTESTATIONS) --sbom=$(ATTACH_ATTESTATIONS) + +$(PUSH_TARGETS): push-%: + $(DOCKER) tag "$(IMAGE)" "$(OUT_IMAGE)" + $(DOCKER) push "$(OUT_IMAGE)" diff --git a/deployments/devel/Dockerfile b/deployments/devel/Dockerfile new file mode 100644 index 00000000..5b63901f --- /dev/null +++ b/deployments/devel/Dockerfile @@ -0,0 +1,26 @@ +# Copyright (c) 2025, 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. + +# This Dockerfile is also used to define the golang version used in this project +# This allows dependabot to manage this version in addition to other images. +FROM golang:1.25.3 + +WORKDIR /work +COPY * . + +RUN make install-tools + +# We need to set the /work directory as a safe directory. +# This allows git commands to run in the container. +RUN git config --file=/.gitconfig --add safe.directory /work diff --git a/deployments/devel/Makefile b/deployments/devel/Makefile new file mode 100644 index 00000000..ace377dd --- /dev/null +++ b/deployments/devel/Makefile @@ -0,0 +1,43 @@ +# Copyright 2024 NVIDIA CORPORATION +# +# 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. + +download: + @echo Download go.mod dependencies + @go mod download + +install-tools: download + @echo Installing tools from tools.go + @cat tools.go | grep _ | awk -F'"' '{print $$2}' | xargs -tI % go install % + + +DOCKER ?= docker +-include $(CURDIR)/versions.mk + +DOCKERFILE_DEVEL = deployments/devel/Dockerfile +DOCKERFILE_CONTEXT = deployments/devel + +.PHONY: .build-image +.build-image: + $(DOCKER) build \ + --progress=plain \ + --tag $(BUILDIMAGE) \ + -f $(DOCKERFILE_DEVEL) \ + $(DOCKERFILE_CONTEXT) + +modules: + go mod tidy + go mod verify + +check-modules: modules + git diff --quiet HEAD -- go.mod go.sum diff --git a/deployments/devel/tools.go b/deployments/devel/tools.go new file mode 100644 index 00000000..13c34608 --- /dev/null +++ b/deployments/devel/tools.go @@ -0,0 +1,26 @@ +//go:build tools +// +build tools + +/** +# Copyright 2024 NVIDIA CORPORATION +# +# 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. +**/ + +package main + +// Define the tooling required to build the device plugin. +import ( + _ "github.com/golangci/golangci-lint/cmd/golangci-lint" + _ "github.com/matryer/moq" +) diff --git a/scripts/golang-version.sh b/scripts/golang-version.sh new file mode 100755 index 00000000..304b79ae --- /dev/null +++ b/scripts/golang-version.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright 2025 NVIDIA CORPORATION +# +# 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. + +SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../scripts && pwd )" + +DOCKERFILE_ROOT=${SCRIPTS_DIR}/../deployments/devel + +GOLANG_VERSION=$(grep -E "^FROM golang:.*$" ${DOCKERFILE_ROOT}/Dockerfile | grep -oE "[0-9\.]+") + +echo $GOLANG_VERSION diff --git a/versions.mk b/versions.mk new file mode 100644 index 00000000..38fe493e --- /dev/null +++ b/versions.mk @@ -0,0 +1,25 @@ +# Copyright (c) 2021-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. + +VERSION ?= v0.9.0 +MODULE := github.com/NVIDIA/sandbox-device-plugin + +vVERSION := v$(VERSION:v%=%) + +GOLANG_VERSION := $(shell ./scripts/golang-version.sh) + +BUILDIMAGE_TAG ?= devel-go$(GOLANG_VERSION) +BUILDIMAGE ?= $(LIB_NAME):$(BUILDIMAGE_TAG) + +GIT_COMMIT ?= $(shell git describe --match="" --dirty --long --always --abbrev=40 2> /dev/null || echo "") From bf2126ece92179314d58cf62f8c046a7ef47cdf3 Mon Sep 17 00:00:00 2001 From: Rajat Chopra Date: Fri, 5 Dec 2025 12:52:42 -0800 Subject: [PATCH 2/2] Keep pointer to kubevirt device plugin exec name for backward compatibility wrt invocation --- deployments/container/Dockerfile.distroless | 1 + 1 file changed, 1 insertion(+) diff --git a/deployments/container/Dockerfile.distroless b/deployments/container/Dockerfile.distroless index f7b820d5..5843ad2e 100644 --- a/deployments/container/Dockerfile.distroless +++ b/deployments/container/Dockerfile.distroless @@ -66,6 +66,7 @@ LABEL summary="NVIDIA Sandbox Device Plugin" LABEL description="See summary" COPY --from=builder /go/src/sandbox-device-plugin/nvidia-sandbox-device-plugin /usr/bin/ +COPY --link --from=builder /go/src/sandbox-device-plugin/nvidia-sandbox-device-plugin /usr/bin/nvidia-kubevirt-gpu-device-plugin COPY --from=builder /go/src/sandbox-device-plugin/utils/pci.ids /usr/pci.ids USER 0:0