Skip to content

feat: derive bluefield service versions from build-time git describe #2787

feat: derive bluefield service versions from build-time git describe

feat: derive bluefield service versions from build-time git describe #2787

Workflow file for this run

#
# SPDX-FileCopyrightText: Copyright (c) 2026 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.
#
name: Carbide CI
on:
push:
branches:
- main
- release/*
- "pull-request/[0-9]+"
tags:
- "v[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9]*"
- "v[0-9].[0-9].[0-9]-rc[0-9]*"
env:
# Build configuration
CARGO_INCREMENTAL: 0
CARGO_HOME: ${{ github.workspace }}/cargo
FF_USE_FASTZIP: "true"
GIT_SUBMODULE_STRATEGY: recursive
jobs:
# ============================================================================
# PREPARE STAGE
# ============================================================================
prepare:
runs-on: linux-amd64-cpu4
outputs:
version: ${{ steps.version.outputs.version }}
helm_version: ${{ steps.version.outputs.helm_version }}
short_sha: ${{ steps.version.outputs.short_sha }}
extras_container_ref: ${{ steps.resolve-extras.outputs.extras_container_ref }}
build_container_x86_64_run: ${{ steps.base-container-gate.outputs.build_container_x86_64_run }}
build_container_x86_64_version: ${{ steps.base-container-gate.outputs.build_container_x86_64_version }}
runtime_container_x86_64_run: ${{ steps.base-container-gate.outputs.runtime_container_x86_64_run }}
runtime_container_x86_64_version: ${{ steps.base-container-gate.outputs.runtime_container_x86_64_version }}
build_container_aarch64_run: ${{ steps.base-container-gate.outputs.build_container_aarch64_run }}
build_container_aarch64_version: ${{ steps.base-container-gate.outputs.build_container_aarch64_version }}
build_artifacts_container_x86_64_run: ${{ steps.base-container-gate.outputs.build_artifacts_container_x86_64_run }}
build_artifacts_container_x86_64_version: ${{ steps.base-container-gate.outputs.build_artifacts_container_x86_64_version }}
build_artifacts_container_aarch64_run: ${{ steps.base-container-gate.outputs.build_artifacts_container_aarch64_run }}
build_artifacts_container_aarch64_version: ${{ steps.base-container-gate.outputs.build_artifacts_container_aarch64_version }}
runtime_container_aarch64_run: ${{ steps.base-container-gate.outputs.runtime_container_aarch64_run }}
runtime_container_aarch64_version: ${{ steps.base-container-gate.outputs.runtime_container_aarch64_version }}
powerdns_container_run: ${{ steps.base-container-gate.outputs.powerdns_container_run }}
proto_files_changed: ${{ steps.base-container-gate.outputs.proto_files_changed }}
source_files_changed: ${{ steps.base-container-gate.outputs.source_files_changed }}
release_build_args: ${{ steps.release-metadata.outputs.build_args }}
release_build_args_aarch64: ${{ steps.release-metadata.outputs.build_args_aarch64 }}
sbom_container_run: ${{ steps.base-container-gate.outputs.sbom_container_run }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Detect build-container-x86_64 changes
id: build-container-changes
uses: dorny/paths-filter@v3
with:
filters: |
build_container:
- 'dev/docker/Dockerfile.build-container-x86_64'
runtime_container:
- 'dev/docker/Dockerfile.runtime-container-x86_64'
runtime_container_aarch64:
- 'dev/docker/Dockerfile.runtime-container-aarch64'
build_container_aarch64:
- 'dev/docker/Dockerfile.build-container-aarch64'
build_artifacts_x86_64:
- 'dev/docker/Dockerfile.build-artifacts-container-x86_64'
build_artifacts_aarch64:
- 'dev/docker/Dockerfile.build-artifacts-container-aarch64'
powerdns_container:
- 'dev/docker/Dockerfile-powerdns'
proto_files:
- '**/*.proto'
source_files:
- 'crates/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'Makefile.toml'
- 'rust-toolchain.toml'
sbom_container:
- 'dev/docker/sbom-tools/Dockerfile'
- name: Calculate version
id: version
run: |
set -euo pipefail
# Fetch tags for accurate git describe
git fetch --tags --force
# Get short SHA
SHORT_SHA=$(git rev-parse --short=7 HEAD)
echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "Using Git describe to extract version as VERSION and HELM_VERSION"
VERSION=$(git describe --tags --first-parent --always --long)
# HELM_VERSION strips leading 'v' for strict SemVer and replaces the last '-' with '.'
HELM_VERSION_BASE="${VERSION#v}"
HELM_VERSION=$(echo "$HELM_VERSION_BASE" | sed 's/\(.*\)-/\1./')
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "helm_version=${HELM_VERSION}" >> $GITHUB_OUTPUT
echo "Calculated VERSION: ${VERSION}"
echo "Calculated HELM_VERSION: ${HELM_VERSION}"
# Output to GitHub Summary
echo "## 📦 Build Version" >> $GITHUB_STEP_SUMMARY
echo "| Variable | Value |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| VERSION | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| HELM_VERSION | \`${HELM_VERSION}\` |" >> $GITHUB_STEP_SUMMARY
- name: Login to NVCR
uses: ./.github/actions/docker-auth
with:
username: ${{ secrets.NVCR_USERNAME }}
token: ${{ secrets.NVCR_TOKEN }}
- name: Resolve pinned carbide-extras image digest
id: resolve-extras
env:
EXTRAS_IMAGE: nvcr.io/0837451325059433/carbide-dev/nvmetal-carbide-extras:latest
run: |
set -euo pipefail
docker pull "${EXTRAS_IMAGE}"
EXTRAS_REF="$(docker inspect --format='{{index .RepoDigests 0}}' "${EXTRAS_IMAGE}")"
if [ -z "${EXTRAS_REF}" ]; then
echo "::error::Failed to resolve digest for ${EXTRAS_IMAGE}"
exit 1
fi
echo "extras_container_ref=${EXTRAS_REF}" >> "$GITHUB_OUTPUT"
echo "Resolved extras image to pinned digest: ${EXTRAS_REF}"
echo "## 📌 Carbide Extras Image" >> "$GITHUB_STEP_SUMMARY"
echo "| Requested | Pinned |" >> "$GITHUB_STEP_SUMMARY"
echo "|-----------|--------|" >> "$GITHUB_STEP_SUMMARY"
echo "| \`${EXTRAS_IMAGE}\` | \`${EXTRAS_REF}\` |" >> "$GITHUB_STEP_SUMMARY"
- name: Decide if build-container-x86_64 must run
id: base-container-gate
env:
EVENT_NAME: ${{ github.event_name }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message || '' }}
VERSION: ${{ steps.version.outputs.version }}
BUILD_CONTAINER_X86_64_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.build_container }}
RUNTIME_CONTAINER_X86_64_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.runtime_container }}
RUNTIME_CONTAINER_AARCH64_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.runtime_container_aarch64 }}
BUILD_CONTAINER_AARCH64_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.build_container_aarch64 }}
BUILD_ARTIFACTS_X86_64_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.build_artifacts_x86_64 }}
BUILD_ARTIFACTS_AARCH64_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.build_artifacts_aarch64 }}
POWERDNS_DOCKERFILE_CHANGED: ${{ steps.build-container-changes.outputs.powerdns_container }}
PROTO_FILES_CHANGED: ${{ steps.build-container-changes.outputs.proto_files }}
SOURCE_FILES_CHANGED: ${{ steps.build-container-changes.outputs.source_files }}
run: |
build_container_x86_64_run=false
runtime_container_x86_64_run=false
build_container_aarch64_run=false
runtime_container_aarch64_run=false
build_artifacts_container_x86_64_run=false
build_artifacts_container_aarch64_run=false
powerdns_container_run=false
proto_files_changed=false
source_files_changed=false
if [[ "${COMMIT_MESSAGE}" =~ ci-rebuild-base-containers ]]; then
build_container_x86_64_run=true
runtime_container_x86_64_run=true
build_container_aarch64_run=true
runtime_container_aarch64_run=true
build_artifacts_container_x86_64_run=true
build_artifacts_container_aarch64_run=true
elif [[ "${BUILD_CONTAINER_X86_64_DOCKERFILE_CHANGED}" == "true" ]]; then
build_container_x86_64_run=true
fi
if [[ "${COMMIT_MESSAGE}" =~ ci-rebuild-sbom-tools ]]; then
sbom_container_run=true
fi
if [[ "${COMMIT_MESSAGE}" =~ ci-rebuild-powerdns ]] || [[ "${POWERDNS_DOCKERFILE_CHANGED}" == "true" ]]; then
powerdns_container_run=true
fi
if [[ "${PROTO_FILES_CHANGED}" == "true" ]]; then
proto_files_changed=true
fi
if [[ "${SOURCE_FILES_CHANGED}" == "true" ]]; then
source_files_changed=true
fi
if [[ "${RUNTIME_CONTAINER_X86_64_DOCKERFILE_CHANGED}" == "true" ]]; then
runtime_container_x86_64_run=true
fi
if [[ "${RUNTIME_CONTAINER_AARCH64_DOCKERFILE_CHANGED}" == "true" ]]; then
runtime_container_aarch64_run=true
fi
if [[ "${BUILD_CONTAINER_AARCH64_DOCKERFILE_CHANGED}" == "true" ]]; then
build_container_aarch64_run=true
fi
if [[ "${BUILD_ARTIFACTS_X86_64_DOCKERFILE_CHANGED}" == "true" ]]; then
build_artifacts_container_x86_64_run=true
fi
if [[ "${BUILD_ARTIFACTS_AARCH64_DOCKERFILE_CHANGED}" == "true" ]]; then
build_artifacts_container_aarch64_run=true
fi
if [[ "${SBOM_CONTAINER_DOCKERFILE_CHANGED}" == "true" ]]; then
sbom_container_run=true
fi
echo "build_container_x86_64_run=${build_container_x86_64_run}" >> "$GITHUB_OUTPUT"
echo "runtime_container_x86_64_run=${runtime_container_x86_64_run}" >> "$GITHUB_OUTPUT"
echo "build_container_aarch64_run=${build_container_aarch64_run}" >> "$GITHUB_OUTPUT"
echo "runtime_container_aarch64_run=${runtime_container_aarch64_run}" >> "$GITHUB_OUTPUT"
echo "build_artifacts_container_x86_64_run=${build_artifacts_container_x86_64_run}" >> "$GITHUB_OUTPUT"
echo "build_artifacts_container_aarch64_run=${build_artifacts_container_aarch64_run}" >> "$GITHUB_OUTPUT"
echo "powerdns_container_run=${powerdns_container_run}" >> "$GITHUB_OUTPUT"
echo "proto_files_changed=${proto_files_changed}" >> "$GITHUB_OUTPUT"
echo "source_files_changed=${source_files_changed}" >> "$GITHUB_OUTPUT"
echo "sbom_container_run=${sbom_container_run}" >> "$GITHUB_OUTPUT"
if [[ "$build_container_x86_64_run" == "true" ]]; then
echo "build_container_x86_64_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "build_container_x86_64_version=latest" >> "$GITHUB_OUTPUT"
fi
if [[ "$runtime_container_x86_64_run" == "true" ]]; then
echo "runtime_container_x86_64_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "runtime_container_x86_64_version=latest" >> "$GITHUB_OUTPUT"
fi
if [[ "$build_container_aarch64_run" == "true" ]]; then
echo "build_container_aarch64_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "build_container_aarch64_version=latest" >> "$GITHUB_OUTPUT"
fi
if [[ "$runtime_container_aarch64_run" == "true" ]]; then
echo "runtime_container_aarch64_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "runtime_container_aarch64_version=latest" >> "$GITHUB_OUTPUT"
fi
if [[ "$build_artifacts_container_x86_64_run" == "true" ]]; then
echo "build_artifacts_container_x86_64_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "build_artifacts_container_x86_64_version=latest" >> "$GITHUB_OUTPUT"
fi
if [[ "$build_artifacts_container_aarch64_run" == "true" ]]; then
echo "build_artifacts_container_aarch64_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "build_artifacts_container_aarch64_version=latest" >> "$GITHUB_OUTPUT"
fi
- name: Decide release container publish strategy
id: release-gate
env:
EVENT_NAME: ${{ github.event_name }}
REF: ${{ github.ref }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message || '' }}
run: |
PUBLISH=false
if [[ "${EVENT_NAME}" == "pull_request" ]] || [[ "${REF}" =~ pull-request/[0-9]+ ]] ; then
PUBLISH=false
elif [[ "${REF}" == "refs/heads/main" ]] || [[ "${REF}" =~ ^refs/heads/release/ ]] || [[ "${REF}" =~ ^refs/tags/ ]] || [[ "${COMMIT_MESSAGE}" =~ ci-run-complete-pipeline ]]; then
PUBLISH=true
fi
echo "publish_built_container=${PUBLISH}" >> "$GITHUB_OUTPUT"
- name: Prepare release container build args
id: release-metadata
env:
VERSION: ${{ steps.version.outputs.version }}
SHORT_SHA: ${{ steps.version.outputs.short_sha }}
BUILD_VERSION: ${{ steps.base-container-gate.outputs.build_container_x86_64_version }}
RUNTIME_VERSION: ${{ steps.base-container-gate.outputs.runtime_container_x86_64_version }}
BUILD_VERSION_AARCH64: ${{ steps.base-container-gate.outputs.build_container_aarch64_version }}
RUNTIME_VERSION_AARCH64: ${{ steps.base-container-gate.outputs.runtime_container_aarch64_version }}
run: |
set -euo pipefail
# x86_64 build args
BUILD_REF="nvcr.io/0837451325059433/carbide-dev/build-container-x86_64:${BUILD_VERSION}"
RUNTIME_REF="nvcr.io/0837451325059433/carbide-dev/runtime-container-x86_64:${RUNTIME_VERSION}"
BUILD_ARGS=$(jq -n -c \
--arg VERSION "$VERSION" \
--arg SHORT_SHA "$SHORT_SHA" \
--arg BUILD "$BUILD_REF" \
--arg RUNTIME "$RUNTIME_REF" \
'{VERSION: $VERSION, CI_COMMIT_SHORT_SHA: $SHORT_SHA, CONTAINER_BUILD_X86_64: $BUILD, CONTAINER_RUNTIME_X86_64: $RUNTIME}')
echo "build_args=${BUILD_ARGS}" >> "$GITHUB_OUTPUT"
# aarch64 build args
BUILD_REF_AARCH64="nvcr.io/0837451325059433/carbide-dev/build-container-aarch64:${BUILD_VERSION_AARCH64}"
RUNTIME_REF_AARCH64="nvcr.io/0837451325059433/carbide-dev/runtime-container-aarch64:${RUNTIME_VERSION_AARCH64}"
BUILD_ARGS_AARCH64=$(jq -n -c \
--arg VERSION "$VERSION" \
--arg SHORT_SHA "$SHORT_SHA" \
--arg BUILD "$BUILD_REF_AARCH64" \
--arg RUNTIME "$RUNTIME_REF_AARCH64" \
'{VERSION: $VERSION, CI_COMMIT_SHORT_SHA: $SHORT_SHA, CONTAINER_BUILD_AARCH64: $BUILD, CONTAINER_RUNTIME_AARCH64: $RUNTIME}')
echo "build_args_aarch64=${BUILD_ARGS_AARCH64}" >> "$GITHUB_OUTPUT"
# ============================================================================
# BUILD STAGE - Base Containers
# ============================================================================
build-container-x86_64:
if: needs.prepare.outputs.build_container_x86_64_run == 'true'
needs:
- prepare
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.build-container-x86_64
image_name: nvcr.io/0837451325059433/carbide-dev/build-container-x86_64
image_tag: ${{ needs.prepare.outputs.build_container_x86_64_version }}
platforms: linux/amd64
runner: linux-amd64-cpu4
push: true
load: true
tag_latest: ${{ github.ref == 'refs/heads/main' }}
secrets: inherit
build-container-aarch64:
if: needs.prepare.outputs.build_container_aarch64_run == 'true'
needs:
- prepare
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.build-container-aarch64
image_name: nvcr.io/0837451325059433/carbide-dev/build-container-aarch64
image_tag: ${{ needs.prepare.outputs.build_container_aarch64_version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: true
load: false
tag_latest: ${{ github.ref == 'refs/heads/main' }}
secrets: inherit
build-runtime-container-x86_64:
if: needs.prepare.outputs.runtime_container_x86_64_run == 'true'
needs:
- prepare
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.runtime-container-x86_64
image_name: nvcr.io/0837451325059433/carbide-dev/runtime-container-x86_64
image_tag: ${{ needs.prepare.outputs.runtime_container_x86_64_version }}
platforms: linux/amd64
runner: linux-amd64-cpu4
push: true
load: true
tag_latest: ${{ github.ref == 'refs/heads/main' }}
secrets: inherit
build-runtime-container-aarch64:
if: needs.prepare.outputs.runtime_container_aarch64_run == 'true'
needs:
- prepare
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.runtime-container-aarch64
image_name: nvcr.io/0837451325059433/carbide-dev/runtime-container-aarch64
image_tag: ${{ needs.prepare.outputs.runtime_container_aarch64_version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: true
load: false
tag_latest: ${{ github.ref == 'refs/heads/main' }}
secrets: inherit
build-artifacts-container-x86_64:
if: needs.prepare.outputs.build_artifacts_container_x86_64_run == 'true'
needs:
- prepare
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.build-artifacts-container-x86_64
image_name: nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-x86_64
image_tag: ${{ needs.prepare.outputs.build_artifacts_container_x86_64_version }}
platforms: linux/amd64
runner: linux-amd64-cpu4
push: true
load: true
tag_latest: ${{ github.ref == 'refs/heads/main' }}
secrets: inherit
build-artifacts-container-aarch64:
if: needs.prepare.outputs.build_artifacts_container_aarch64_run == 'true'
needs:
- prepare
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.build-artifacts-container-aarch64
image_name: nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-aarch64
image_tag: ${{ needs.prepare.outputs.build_artifacts_container_aarch64_version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: true
load: false
tag_latest: ${{ github.ref == 'refs/heads/main' }}
secrets: inherit
# ============================================================================
# BUILD STAGE - Release Container
# ============================================================================
build-release-container-x86_64:
if: ${{ always() && github.event_name != 'schedule' }}
needs:
- prepare
- build-container-x86_64
- build-runtime-container-x86_64
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.release-container-x86_64
context_path: .
build_args: ${{ needs.prepare.outputs.release_build_args }}
image_name: nvcr.io/0837451325059433/carbide-dev/nvmetal-carbide
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/amd64
runner: linux-amd64-cpu16
push: ${{ !contains(github.ref, 'pull-request/') }}
load: true
tag_latest: false
timeout_minutes: 120
secrets: inherit
build-release-container-aarch64:
if: ${{ always() && github.event_name != 'schedule' }}
needs:
- prepare
- build-container-aarch64
- build-runtime-container-aarch64
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.release-container-aarch64
context_path: .
build_args: ${{ needs.prepare.outputs.release_build_args_aarch64 }}
image_name: nvcr.io/0837451325059433/carbide-dev/nvmetal-carbide-aarch64
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/arm64
runner: linux-arm64-cpu16
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
tag_latest: false
secrets: inherit
# ============================================================================
# BUILD STAGE - Forge CLI (Multi-arch)
# ============================================================================
build-forge-cli-x86_64:
needs:
- prepare
- build-artifacts-container-x86_64
if: ${{ always() && github.event_name != 'schedule' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.release-forge-cli
image_name: nvcr.io/0837451325059433/carbide-dev/forge-admin-cli-x86_64
image_tag: ${{ needs.prepare.outputs.version }}
build_args: '{"CI_COMMIT_SHORT_SHA":"${{ needs.prepare.outputs.short_sha }}","CONTAINER_BUILD":"nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-x86_64:${{ needs.prepare.outputs.build_artifacts_container_x86_64_version }}"}'
platforms: linux/amd64
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: true
secrets: inherit
build-forge-cli-aarch64:
needs:
- prepare
- build-artifacts-container-aarch64
if: ${{ always() && github.event_name != 'schedule' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.release-forge-cli
image_name: nvcr.io/0837451325059433/carbide-dev/forge-admin-cli-aarch64
image_tag: ${{ needs.prepare.outputs.version }}
build_args: '{"CI_COMMIT_SHORT_SHA":"${{ needs.prepare.outputs.short_sha }}","CONTAINER_BUILD":"nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-aarch64:${{ needs.prepare.outputs.build_artifacts_container_aarch64_version }}"}'
platforms: linux/arm64
runner: linux-arm64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: true
secrets: inherit
merge-manifests-forge-cli:
needs:
- prepare
- build-forge-cli-x86_64
- build-forge-cli-aarch64
if: ${{ !cancelled() && github.event_name != 'schedule' && !contains(github.ref, 'pull-request/') && needs.build-forge-cli-x86_64.result == 'success' && needs.build-forge-cli-aarch64.result == 'success' }}
runs-on: linux-amd64-cpu4
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to NVCR
uses: ./.github/actions/docker-auth
with:
username: ${{ secrets.NVCR_USERNAME }}
token: ${{ secrets.NVCR_TOKEN }}
- name: Create and push multi-arch manifest
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08
with:
max_attempts: 3
timeout_minutes: 10
retry_wait_seconds: 20
command: |
docker buildx imagetools create -t \
nvcr.io/0837451325059433/carbide-dev/forge-admin-cli:${{ needs.prepare.outputs.version }} \
nvcr.io/0837451325059433/carbide-dev/forge-admin-cli-x86_64:${{ needs.prepare.outputs.version }} \
nvcr.io/0837451325059433/carbide-dev/forge-admin-cli-aarch64:${{ needs.prepare.outputs.version }}
docker buildx imagetools create -t \
nvcr.io/0837451325059433/carbide-dev/forge-admin-cli:latest \
nvcr.io/0837451325059433/carbide-dev/forge-admin-cli-x86_64:${{ needs.prepare.outputs.version }} \
nvcr.io/0837451325059433/carbide-dev/forge-admin-cli-aarch64:${{ needs.prepare.outputs.version }}
# ============================================================================
# BUILD STAGE - Boot Artifacts
# ============================================================================
build-boot-artifacts-x86:
needs:
- prepare
- build-artifacts-container-x86_64
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && contains('success,skipped', needs.build-artifacts-container-x86_64.result) }}
uses: ./.github/workflows/build-boot-artifacts.yml
with:
arch: x86_64
build_type: boot
cargo_make_task: build-boot-artifacts-x86-host-ci
build_container: nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-x86_64:${{ needs.prepare.outputs.build_artifacts_container_x86_64_version }}
runner: linux-amd64-cpu4
version: ${{ needs.prepare.outputs.version }}
use_container: true
inject_extras: true
extras_container: ${{ needs.prepare.outputs.extras_container_ref }}
secrets: inherit
build-boot-artifacts-bfb:
needs:
- prepare
- build-artifacts-container-aarch64
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && contains('success,skipped', needs.build-artifacts-container-aarch64.result) }}
uses: ./.github/workflows/build-boot-artifacts.yml
with:
arch: aarch64
build_type: boot
cargo_make_task: build-boot-artifacts-bfb-ci
build_container: nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-aarch64:${{ needs.prepare.outputs.build_artifacts_container_aarch64_version }}
runner: linux-arm64-cpu8
version: ${{ needs.prepare.outputs.version }}
use_container: true
inject_extras: true
extras_container: ${{ needs.prepare.outputs.extras_container_ref }}
secrets: inherit
# ============================================================================
# BUILD STAGE - Ephemeral Images
# ============================================================================
# These builds create bootable ephemeral images (scout.efi, qcow-imager.efi)
# using mkosi. They run on standard Ubuntu runners with mkosi installed.
build-boot-artifacts-ephemeral-image-x86-host:
needs:
- prepare
- build-boot-artifacts-x86
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-boot-artifacts-x86.result == 'success' }}
uses: ./.github/workflows/build-boot-artifacts.yml
with:
arch: x86_64
build_type: ephemeral
cargo_make_task: create-ephemeral-image-x86-host-ci
version: ${{ needs.prepare.outputs.version }}
runner: linux-amd64-cpu8
use_container: false
sa_enablement: true
inject_extras: true
extras_container: ${{ needs.prepare.outputs.extras_container_ref }}
secrets: inherit
build-boot-artifacts-ephemeral-image-arm-host:
needs:
- prepare
- build-boot-artifacts-bfb
# Run only if boot artifacts succeeded (we need those artifacts); skip if cancelled
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-boot-artifacts-bfb.result == 'success' }}
uses: ./.github/workflows/build-boot-artifacts.yml
with:
arch: aarch64
build_type: ephemeral
cargo_make_task: create-ephemeral-image-arm-host-ci
version: ${{ needs.prepare.outputs.version }}
runner: linux-arm64-cpu8
use_container: false
sa_enablement: true
inject_extras: true
extras_container: ${{ needs.prepare.outputs.extras_container_ref }}
secrets: inherit
# ============================================================================
# BUILD STAGE - Release Artifacts
# ============================================================================
build-release-artifacts-x86-host:
needs:
- prepare
- build-boot-artifacts-x86
- build-boot-artifacts-ephemeral-image-x86-host
# Run only if both boot and ephemeral jobs succeeded (we need those artifacts); skip if failed/cancelled
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-boot-artifacts-x86.result == 'success' && needs.build-boot-artifacts-ephemeral-image-x86-host.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.release-artifacts-x86_64
image_name: nvcr.io/0837451325059433/carbide-dev/boot-artifacts-x86_64
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/amd64
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: true
download_artifacts: true # Download boot and ephemeral artifacts for packaging
build_args: |
{
"VERSION": "${{ needs.prepare.outputs.version }}",
"CI_COMMIT_SHORT_SHA": "${{ needs.prepare.outputs.short_sha }}",
"CONTAINER_RUNTIME_X86_64": "alpine:latest"
}
secrets: inherit
build-release-artifacts-arm-host:
needs:
- prepare
- build-boot-artifacts-bfb
- build-boot-artifacts-ephemeral-image-arm-host
# Run only if both boot and ephemeral jobs succeeded (we need those artifacts); skip if failed/cancelled
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-boot-artifacts-bfb.result == 'success' && needs.build-boot-artifacts-ephemeral-image-arm-host.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.release-artifacts-aarch64
image_name: nvcr.io/0837451325059433/carbide-dev/boot-artifacts-aarch64
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/amd64 # Note: aarch64 artifacts packaged in x86_64 image
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: true
download_artifacts: true # Download boot and ephemeral artifacts for packaging
build_args: |
{
"VERSION": "${{ needs.prepare.outputs.version }}",
"CI_COMMIT_SHORT_SHA": "${{ needs.prepare.outputs.short_sha }}",
"CONTAINER_RUNTIME_AARCH64": "alpine:latest"
}
secrets: inherit
# ============================================================================
# BUILD STAGE - Publish Documentation
# ============================================================================
build-publish-documentation:
if: false
needs:
- prepare
- build-container-x86_64
uses: ./.github/workflows/docs.yml
with:
build_container: ${{ format('nvcr.io/0837451325059433/carbide-dev/build-container-x86_64:{0}', (needs['build-container-x86_64'].result == 'success' && needs.prepare.outputs.version) || 'latest') }}
runner: linux-amd64-cpu4
secrets: inherit
# ============================================================================
# SECURITY STAGE
# ============================================================================
security-secret-scan:
name: Secret Scan with TruffleHog
needs: prepare
runs-on: linux-amd64-cpu4
timeout-minutes: 30
permissions:
actions: read
contents: read
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for secret scanning
- name: Run TruffleHog Scan
uses: NVIDIA/dsx-github-actions/.github/actions/trufflehog-scan@9a9ce3a7770a8b53d2726afa920be3276bc3ddd7
with:
extra-args: '--results=verified,unknown --only-verified'
post-pr-comment: 'true'
fail-on-findings: 'true'
security-codeql-scan:
name: CodeQL Security Analysis
needs: prepare
runs-on: linux-amd64-cpu4
timeout-minutes: 360
permissions:
actions: read
contents: read
security-events: write
packages: read
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run CodeQL Scan
uses: NVIDIA/dsx-github-actions/.github/actions/codeql-scan@20dc10dda4fa9f8f0380a47cd9a7800d3da3dcf3
with:
languages: 'rust'
build-mode: 'none'
category: '/language:rust'
upload-sarif: 'false' # Disable upload until GHAS is enabled, such as the repo be public
post-pr-comment: 'false'
fail-on-findings: 'true' # Enforce quality gate
fail-on-severity: 'error' # Only fail on critical/high severity issues
# ============================================================================
# BUILD STAGE - Machine Validation
# ============================================================================
build-release-machine-validation-runner:
needs:
- prepare
- build-runtime-container-x86_64
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && contains('success,skipped', needs.build-runtime-container-x86_64.result) }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.machine-validation-runner
image_name: nvcr.io/0837451325059433/carbide-dev/machine-validation-runner
image_tag: ${{ needs.prepare.outputs.version }}
build_args: '{"CI_COMMIT_SHORT_SHA":"${{ needs.prepare.outputs.short_sha }}","CONTAINER_RUNTIME_X86_64":"nvcr.io/0837451325059433/carbide-dev/runtime-container-x86_64:${{ needs.prepare.outputs.runtime_container_x86_64_version }}"}'
platforms: linux/amd64
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
secrets: inherit
build-release-machine-validation-artifacts-x86-host:
needs:
- prepare
- build-release-machine-validation-runner
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-release-machine-validation-runner.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile.machine-validation-config
image_name: nvcr.io/0837451325059433/carbide-dev/machine_validation
image_tag: ${{ needs.prepare.outputs.version }}
build_args: '{"CI_COMMIT_SHORT_SHA":"${{ needs.prepare.outputs.short_sha }}","CONTAINER_RUNTIME_X86_64":"nvcr.io/0837451325059433/carbide-dev/runtime-container-x86_64:${{ needs.prepare.outputs.runtime_container_x86_64_version }}"}'
platforms: linux/amd64
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
secrets: inherit
# ============================================================================
# BUILD STAGE - PowerDNS
# ============================================================================
build-powerdns-container:
needs:
- prepare
if: needs.prepare.outputs.powerdns_container_run == 'true'
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/Dockerfile-powerdns
image_name: nvcr.io/0837451325059433/carbide-dev/powerdns
image_tag: "4.9.3"
build_args: '{"CI_COMMIT_SHORT_SHA":"${{ needs.prepare.outputs.short_sha }}"}'
platforms: linux/amd64
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
secrets: inherit
proto-police:
needs:
- prepare
if: ${{ needs.prepare.outputs.proto_files_changed == 'true' && contains(github.ref, 'pull-request/') }}
runs-on: linux-amd64-cpu4
container:
image: yoheimuta/protolint
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Protolint
run: protolint lint -config_path=.protolint.yaml crates/rpc/proto/
lint-police:
needs:
- prepare
- build-container-x86_64
if: ${{ !failure() && !cancelled() && needs.prepare.outputs.source_files_changed == 'true' && contains(github.ref, 'pull-request/') }}
runs-on: linux-amd64-cpu16
container:
image: nvcr.io/0837451325059433/carbide-dev/build-container-x86_64:${{ needs.prepare.outputs.build_container_x86_64_version }}
credentials:
username: ${{ secrets.NVCR_USERNAME }}
password: ${{ secrets.NVCR_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4
# PostgreSQL is required because sqlx proc macros (sqlx::query!) connect to
# a local database at compile time to validate SQL queries and return types.
- name: Start PostgreSQL
run: |
/etc/init.d/postgresql start
sudo -u postgres psql -c "ALTER USER root WITH SUPERUSER;"
createdb root
- name: Run clippy
env:
DATABASE_URL: "postgresql://%2Fvar%2Frun%2Fpostgresql"
run: cargo make --no-workspace clippy-flow
- name: Run carbide lints
run: cargo make carbide-lints
- name: Check TOML formatting
run: taplo fmt --check || echo "Please format toml files"
- name: Check Rust formatting
run: cargo make --no-workspace check-format-nightly
- name: Check workspace deps
run: cargo xtask check-workspace-deps
- name: Check licenses
run: cargo make --no-workspace check-licenses
- name: Check bans
run: cargo make --no-workspace check-bans
# ============================================================================
# BUILD STAGE - Helm Chart
# ============================================================================
build-validate-helm-chart:
needs:
- prepare
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' }}
runs-on: linux-amd64-cpu4
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate Helm chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: helm
lint: 'true'
template: 'true'
build-push-helm-chart:
needs:
- prepare
- build-validate-helm-chart
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-validate-helm-chart.result == 'success' && !contains(github.ref, 'pull-request/') }}
runs-on: linux-amd64-cpu4
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Package and push Helm chart to NGC
uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: helm
chart-version: ${{ needs.prepare.outputs.helm_version }}
app-version: ${{ needs.prepare.outputs.version }}
lint: 'false'
ngc-key: ${{ secrets.NVCR_TOKEN }}
ngc-path: 0837451325059433/carbide-dev
ngc-duplicate: fail
# ============================================================================
# BUILD STAGE - Bluefield Images
# ============================================================================
build-bluefield-binaries:
needs:
- prepare
- build-artifacts-container-aarch64
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && contains('success,skipped', needs.build-artifacts-container-aarch64.result) }}
runs-on: linux-arm64-cpu8
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Login to NVCR
uses: ./.github/actions/docker-auth
with:
username: ${{ secrets.NVCR_USERNAME }}
token: ${{ secrets.NVCR_TOKEN }}
- name: Pull build container
run: docker pull nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-aarch64:${{ needs.prepare.outputs.build_artifacts_container_aarch64_version }}
- name: Compile bluefield Rust binaries
run: |
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
-e CARGO_HOME=/workspace/cargo \
-e CARGO_INCREMENTAL=0 \
-e CARGO_BUILD_TARGET=aarch64-unknown-linux-gnu \
nvcr.io/0837451325059433/carbide-dev/build-artifacts-container-aarch64:${{ needs.prepare.outputs.build_artifacts_container_aarch64_version }} \
bash -c "git config --global --add safe.directory /workspace && \
cargo make --cwd bluefield build-dpu-agent-and-dhcp-server-ci && \
cargo make --cwd bluefield build-fmds-ci && \
cargo make --cwd bluefield build-dpu-otel-agent-ci"
- name: Stage bluefield binaries for upload
run: |
mkdir -p bluefield-binaries-dir/target/aarch64-unknown-linux-gnu/release
cp target/aarch64-unknown-linux-gnu/release/{forge-dpu-agent,forge-dhcp-server,forge-dpu-otel-agent,carbide-fmds} \
bluefield-binaries-dir/target/aarch64-unknown-linux-gnu/release/
- name: Upload bluefield binaries
uses: actions/upload-artifact@v4
with:
name: bluefield-binaries-${{ github.run_id }}
path: bluefield-binaries-dir/
build-bluefield-otelcol-contrib:
needs:
- prepare
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: bluefield/containers/otelcol-contrib/Dockerfile
context_path: .
image_name: nvcr.io/0837451325059433/carbide-dev/otelcol-contrib
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
secrets: inherit
build-bluefield-forge-dpu-agent:
needs:
- prepare
- build-bluefield-binaries
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-bluefield-binaries.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: bluefield/containers/forge-dpu-agent/Dockerfile
image_name: nvcr.io/0837451325059433/carbide-dev/forge-dpu-agent
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
download_artifacts: true
secrets: inherit
build-bluefield-forge-dhcp-server:
needs:
- prepare
- build-bluefield-binaries
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-bluefield-binaries.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: bluefield/containers/forge-dhcp-server/Dockerfile
image_name: nvcr.io/0837451325059433/carbide-dev/forge-dhcp-server
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
download_artifacts: true
secrets: inherit
build-bluefield-forge-dpu-otel-agent:
needs:
- prepare
- build-bluefield-binaries
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-bluefield-binaries.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: bluefield/containers/forge-dpu-otel-agent/Dockerfile
image_name: nvcr.io/0837451325059433/carbide-dev/forge-dpu-otel-agent
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
download_artifacts: true
secrets: inherit
build-bluefield-carbide-fmds:
needs:
- prepare
- build-bluefield-binaries
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-bluefield-binaries.result == 'success' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: bluefield/containers/carbide-fmds/Dockerfile
image_name: nvcr.io/0837451325059433/carbide-dev/carbide-fmds
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/arm64
runner: linux-arm64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
download_artifacts: true
secrets: inherit
# ============================================================================
# BUILD STAGE - Bluefield Helm Charts
# ============================================================================
build-validate-bluefield-helm-charts:
needs:
- prepare
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' }}
runs-on: linux-amd64-cpu4
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate carbide-otelcol chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-otelcol
lint: 'true'
template: 'true'
- name: Validate carbide-dpu-agent chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-dpu-agent
lint: 'true'
template: 'true'
- name: Validate carbide-dhcp-server chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-dhcp-server
lint: 'true'
template: 'true'
- name: Validate carbide-dpu-otel-agent chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-dpu-otel-agent
lint: 'true'
template: 'true'
- name: Validate carbide-fmds chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-fmds
lint: 'true'
template: 'true'
build-push-bluefield-helm-charts:
needs:
- prepare
- build-validate-bluefield-helm-charts
if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-validate-bluefield-helm-charts.result == 'success' && !contains(github.ref, 'pull-request/') }}
runs-on: linux-amd64-cpu4
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Package and push carbide-otelcol chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-otelcol
chart-version: ${{ needs.prepare.outputs.helm_version }}
app-version: ${{ needs.prepare.outputs.version }}
lint: 'false'
ngc-key: ${{ secrets.NVCR_TOKEN }}
ngc-path: 0837451325059433/carbide-dev
ngc-duplicate: fail
# helm-package-push expects exactly one .tgz in package/, so we have to clean the previously built chart
- name: Clean helm package directory
run: rm -rf package/
- name: Package and push carbide-dpu-agent chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-dpu-agent
chart-version: ${{ needs.prepare.outputs.helm_version }}
app-version: ${{ needs.prepare.outputs.version }}
lint: 'false'
ngc-key: ${{ secrets.NVCR_TOKEN }}
ngc-path: 0837451325059433/carbide-dev
ngc-duplicate: fail
# helm-package-push expects exactly one .tgz in package/, so we have to clean the previously built chart
- name: Clean helm package directory
run: rm -rf package/
- name: Package and push carbide-dhcp-server chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-dhcp-server
chart-version: ${{ needs.prepare.outputs.helm_version }}
app-version: ${{ needs.prepare.outputs.version }}
lint: 'false'
ngc-key: ${{ secrets.NVCR_TOKEN }}
ngc-path: 0837451325059433/carbide-dev
ngc-duplicate: fail
# helm-package-push expects exactly one .tgz in package/, so we have to clean the previously built chart
- name: Clean helm package directory
run: rm -rf package/
- name: Package and push carbide-dpu-otel-agent chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-dpu-otel-agent
chart-version: ${{ needs.prepare.outputs.helm_version }}
app-version: ${{ needs.prepare.outputs.version }}
lint: 'false'
ngc-key: ${{ secrets.NVCR_TOKEN }}
ngc-path: 0837451325059433/carbide-dev
ngc-duplicate: fail
# helm-package-push expects exactly one .tgz in package/, so we have to clean the previously built chart
- name: Clean helm package directory
run: rm -rf package/
- name: Package and push carbide-fmds chart
uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@94bde998f5d7965576b0c663db7d5d709c918167
with:
chart-path: bluefield/charts/carbide-fmds
chart-version: ${{ needs.prepare.outputs.helm_version }}
app-version: ${{ needs.prepare.outputs.version }}
lint: 'false'
ngc-key: ${{ secrets.NVCR_TOKEN }}
ngc-path: 0837451325059433/carbide-dev
ngc-duplicate: fail
# ============================================================================
# BUILD SBOM
# ============================================================================
build-sbom-container:
needs:
- prepare
if: ${{ needs.prepare.outputs.sbom_container_run == 'true' }}
uses: ./.github/workflows/docker-build.yml
with:
dockerfile_path: dev/docker/sbom-tools/Dockerfile
image_name: nvcr.io/0837451325059433/carbide-dev/sbom-tools
image_tag: ${{ needs.prepare.outputs.version }}
platforms: linux/amd64
runner: linux-amd64-cpu4
push: ${{ !contains(github.ref, 'pull-request/') }}
load: false
secrets: inherit
build-summary:
runs-on: linux-amd64-cpu4
if: ${{ always() && github.event_name != 'schedule' }}
needs:
- build-container-x86_64
- build-container-aarch64
- build-runtime-container-x86_64
- build-runtime-container-aarch64
- build-artifacts-container-x86_64
- build-artifacts-container-aarch64
- build-release-container-x86_64
- build-release-container-aarch64
- build-boot-artifacts-x86
- build-boot-artifacts-bfb
- build-boot-artifacts-ephemeral-image-x86-host
- build-boot-artifacts-ephemeral-image-arm-host
- build-forge-cli-x86_64
- build-forge-cli-aarch64
- merge-manifests-forge-cli
- build-release-machine-validation-runner
- build-release-machine-validation-artifacts-x86-host
- build-powerdns-container
- build-validate-helm-chart
- build-push-helm-chart
- build-release-artifacts-x86-host
- build-release-artifacts-arm-host
- build-bluefield-binaries
- build-bluefield-otelcol-contrib
- build-bluefield-forge-dpu-agent
- build-bluefield-forge-dhcp-server
- build-bluefield-forge-dpu-otel-agent
- build-bluefield-carbide-fmds
- build-validate-bluefield-helm-charts
- build-push-bluefield-helm-charts
- lint-police
steps:
- name: Generate summary
run: |
NEEDS='${{ toJson(needs) }}'
echo "## Build Jobs Summary" >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
echo "| Job | Status |" >> "$GITHUB_STEP_SUMMARY"
echo "|-----|--------|" >> "$GITHUB_STEP_SUMMARY"
echo "$NEEDS" | jq -r '
to_entries[]
| select(.key | startswith("build-"))
| "| \(.key) | \(if .value.result == "failure" then "**\(.value.result)**" else .value.result end) |"
' >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
echo "## Docker Images Built" >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
echo "| Job | Image |" >> "$GITHUB_STEP_SUMMARY"
echo "|-----|-------|" >> "$GITHUB_STEP_SUMMARY"
# Collect image_ref from docker-build jobs
declare -A IMAGES
IMAGES["build-container-x86_64"]="${{ needs.build-container-x86_64.outputs.image_ref }}"
IMAGES["build-container-aarch64"]="${{ needs.build-container-aarch64.outputs.image_ref }}"
IMAGES["build-runtime-container-x86_64"]="${{ needs.build-runtime-container-x86_64.outputs.image_ref }}"
IMAGES["build-runtime-container-aarch64"]="${{ needs.build-runtime-container-aarch64.outputs.image_ref }}"
IMAGES["build-artifacts-container-x86_64"]="${{ needs.build-artifacts-container-x86_64.outputs.image_ref }}"
IMAGES["build-artifacts-container-aarch64"]="${{ needs.build-artifacts-container-aarch64.outputs.image_ref }}"
IMAGES["build-release-container-x86_64"]="${{ needs.build-release-container-x86_64.outputs.image_ref }}"
IMAGES["build-release-container-aarch64"]="${{ needs.build-release-container-aarch64.outputs.image_ref }}"
IMAGES["build-forge-cli-x86_64"]="${{ needs.build-forge-cli-x86_64.outputs.image_ref }}"
IMAGES["build-forge-cli-aarch64"]="${{ needs.build-forge-cli-aarch64.outputs.image_ref }}"
IMAGES["build-release-machine-validation-runner"]="${{ needs.build-release-machine-validation-runner.outputs.image_ref }}"
IMAGES["build-release-machine-validation-artifacts-x86-host"]="${{ needs.build-release-machine-validation-artifacts-x86-host.outputs.image_ref }}"
IMAGES["build-powerdns-container"]="${{ needs.build-powerdns-container.outputs.image_ref }}"
IMAGES["build-release-artifacts-x86-host"]="${{ needs.build-release-artifacts-x86-host.outputs.image_ref }}"
IMAGES["build-release-artifacts-arm-host"]="${{ needs.build-release-artifacts-arm-host.outputs.image_ref }}"
for job in "${!IMAGES[@]}"; do
image="${IMAGES[$job]}"
if [[ -n "$image" ]]; then
echo "| $job | \`$image\` |" >> "$GITHUB_STEP_SUMMARY"
fi
done
promote-to-be-scanned-image:
# Skip for pull-request/* branches (main, release/*, and tags are allowed by workflow trigger)
if: ${{ !cancelled() && needs.build-release-container-x86_64.result == 'success' && github.event_name != 'schedule' && !contains(github.ref, 'pull-request/') }}
needs:
- prepare
- build-release-container-x86_64
uses: NVIDIA/dsx-github-actions/.github/workflows/promote-image.yml@760d2d7964b479fde431cd3e0b980bc6b6a26ccd
with:
source: nvcr.io/0837451325059433/carbide-dev/nvmetal-carbide
source_tag: ${{ needs.prepare.outputs.version }}
destination: nvcr.io/0837451325059433/carbide/nvmetal-carbide
destination_tag: "to-be-scanned"
secrets:
SOURCE_USERNAME: ${{ secrets.NVCR_USERNAME }}
SOURCE_PASSWORD: ${{ secrets.NVCR_TOKEN }}
DEST_USERNAME: ${{ secrets.NVCR_PROD_USERNAME }}
DEST_PASSWORD: ${{ secrets.NVCR_PROD_TOKEN }}
# ============================================================================
# NOTIFICATION STAGE
# ============================================================================
notify-build-status:
if: ${{ always() && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && github.event_name != 'schedule' }}
needs:
- prepare
- build-container-x86_64
- build-container-aarch64
- build-runtime-container-x86_64
- build-runtime-container-aarch64
- build-artifacts-container-x86_64
- build-artifacts-container-aarch64
- build-release-container-x86_64
- build-release-container-aarch64
- build-boot-artifacts-x86
- build-boot-artifacts-bfb
- build-boot-artifacts-ephemeral-image-x86-host
- build-boot-artifacts-ephemeral-image-arm-host
- build-forge-cli-x86_64
- build-forge-cli-aarch64
- merge-manifests-forge-cli
- build-release-machine-validation-runner
- build-release-machine-validation-artifacts-x86-host
- build-powerdns-container
- build-validate-helm-chart
- build-push-helm-chart
- build-release-artifacts-x86-host
- build-release-artifacts-arm-host
- build-bluefield-binaries
- build-bluefield-otelcol-contrib
- build-bluefield-forge-dpu-agent
- build-bluefield-forge-dhcp-server
- build-bluefield-forge-dpu-otel-agent
- build-bluefield-carbide-fmds
- build-validate-bluefield-helm-charts
- build-push-bluefield-helm-charts
- build-sbom-container
- security-secret-scan
- security-codeql-scan
- promote-to-be-scanned-image
uses: ./.github/workflows/notify-build-status.yml
with:
version: ${{ needs.prepare.outputs.version }}
workflow-name: "Carbide Core CI"
channel-id: C0A0TSKJKSB # #dsx-carbide-feed
needs-context: ${{ toJson(needs) }}
notify-on-success: true
notify-on-partial: true
notify-on-failure: true
secrets:
slack-bot-token: ${{ secrets.CDS_SLACK_BOT_OAUTH_TOKEN }}