chore: remove unused pytest.ini (#3083) #8221
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # SPDX-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: NICo Core CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - "pull-request/[0-9]+" | |
| tags: | |
| - "v[0-9]*.[0-9]*.[0-9]*" | |
| - "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: | |
| changes: | |
| name: Detect Core CI Gate | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run_core_ci: ${{ steps.gate.outputs.run_core_ci }} | |
| non_rest_changed: ${{ steps.non-rest-changes.outputs.non_rest }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect non-rest changes | |
| id: non-rest-changes | |
| if: startsWith(github.ref, 'refs/heads/pull-request/') | |
| uses: dorny/paths-filter@v3 | |
| with: | |
| base: main | |
| predicate-quantifier: every | |
| filters: | | |
| non_rest: | |
| - '**' | |
| - '!rest-api/**' | |
| - '!.github/workflows/rest-*.yml' | |
| - '!helm/rest/**' | |
| - '!docs/**' | |
| - '!fern/**' | |
| - name: Decide whether Core CI should run | |
| id: gate | |
| env: | |
| REF: ${{ github.ref }} | |
| COMMIT_MESSAGE: ${{ github.event.head_commit.message || '' }} | |
| NON_REST_CHANGED: ${{ steps.non-rest-changes.outputs.non_rest }} | |
| run: | | |
| run_core_ci=true | |
| if [[ "${REF}" =~ ^refs/heads/pull-request/[0-9]+$ ]]; then | |
| run_core_ci="${NON_REST_CHANGED}" | |
| fi | |
| if [[ "${COMMIT_MESSAGE}" =~ ci-run-complete-pipeline ]]; then | |
| run_core_ci=true | |
| fi | |
| echo "run_core_ci=${run_core_ci}" >> "$GITHUB_OUTPUT" | |
| echo "Core CI gate: ${run_core_ci}" | |
| # ============================================================================ | |
| # PREPARE STAGE | |
| # ============================================================================ | |
| prepare: | |
| needs: | |
| - changes | |
| if: ${{ needs.changes.outputs.run_core_ci == 'true' }} | |
| 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 }} | |
| proto_files_changed: ${{ steps.base-container-gate.outputs.proto_files_changed }} | |
| core_rpc_proto_files_changed: ${{ steps.base-container-gate.outputs.core_rpc_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 }} | |
| 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' | |
| proto_files: | |
| - '**/*.proto' | |
| core_rpc_proto_files: | |
| - 'crates/rpc/proto/**' | |
| source_files: | |
| - 'crates/**' | |
| - 'Cargo.toml' | |
| - 'Cargo.lock' | |
| - 'Makefile.toml' | |
| - 'rust-toolchain.toml' | |
| - name: Calculate version | |
| id: version | |
| run: | | |
| set -euo pipefail | |
| # Fetch tags for accurate git describe | |
| git fetch --tags --force | |
| 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 }} | |
| PROTO_FILES_CHANGED: ${{ steps.build-container-changes.outputs.proto_files }} | |
| CORE_RPC_PROTO_FILES_CHANGED: ${{ steps.build-container-changes.outputs.core_rpc_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 | |
| proto_files_changed=false | |
| core_rpc_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 [[ "${PROTO_FILES_CHANGED}" == "true" ]]; then | |
| proto_files_changed=true | |
| fi | |
| if [[ "${CORE_RPC_PROTO_FILES_CHANGED}" == "true" ]]; then | |
| core_rpc_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 | |
| 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 "proto_files_changed=${proto_files_changed}" >> "$GITHUB_OUTPUT" | |
| echo "core_rpc_proto_files_changed=${core_rpc_proto_files_changed}" >> "$GITHUB_OUTPUT" | |
| echo "source_files_changed=${source_files_changed}" >> "$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.result == 'success' | |
| && contains('success,skipped', needs.build-container-x86_64.result) | |
| && contains('success,skipped', needs.build-runtime-container-x86_64.result) | |
| && contains('success,skipped', needs.check-rest-core-proto-sync.result) | |
| && contains('success,skipped', needs.lint-police.result) | |
| }} | |
| needs: | |
| - prepare | |
| - build-container-x86_64 | |
| - build-runtime-container-x86_64 | |
| - check-rest-core-proto-sync | |
| - lint-police | |
| 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 | |
| scan: true | |
| tag_latest: false | |
| timeout_minutes: 120 | |
| secrets: inherit | |
| build-release-container-aarch64: | |
| if: >- | |
| ${{ | |
| always() | |
| && github.event_name != 'schedule' | |
| && needs.prepare.result == 'success' | |
| && contains('success,skipped', needs.build-container-aarch64.result) | |
| && contains('success,skipped', needs.build-runtime-container-aarch64.result) | |
| && contains('success,skipped', needs.check-rest-core-proto-sync.result) | |
| }} | |
| needs: | |
| - prepare | |
| - build-container-aarch64 | |
| - build-runtime-container-aarch64 | |
| - check-rest-core-proto-sync | |
| 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 | |
| # Combine the per-arch nvmetal-carbide images into a single multi-arch manifest | |
| # at the bare tag, so the carbide control plane can be scheduled on both amd64 | |
| # and arm64 nodes. The per-arch images are still pushed individually | |
| # (nvmetal-carbide = amd64, nvmetal-carbide-aarch64 = arm64). Sources are | |
| # referenced by digest so re-runs are idempotent. Push refs only. | |
| merge-manifests-nvmetal-carbide: | |
| needs: | |
| - prepare | |
| - build-release-container-x86_64 | |
| - build-release-container-aarch64 | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && !contains(github.ref, 'pull-request/') && needs.build-release-container-x86_64.result == 'success' && needs.build-release-container-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/nvmetal-carbide:${{ needs.prepare.outputs.version }} \ | |
| nvcr.io/0837451325059433/carbide-dev/nvmetal-carbide@${{ needs.build-release-container-x86_64.outputs.image_digest }} \ | |
| nvcr.io/0837451325059433/carbide-dev/nvmetal-carbide-aarch64@${{ needs.build-release-container-aarch64.outputs.image_digest }} | |
| test-release-container-services: | |
| if: >- | |
| ${{ | |
| always() | |
| && github.event_name != 'schedule' | |
| && needs.prepare.result == 'success' | |
| && contains('success,skipped', needs.build-container-x86_64.result) | |
| && contains('success,skipped', needs.build-runtime-container-x86_64.result) | |
| && contains('success,skipped', needs.check-rest-core-proto-sync.result) | |
| }} | |
| needs: | |
| - prepare | |
| - build-container-x86_64 | |
| - build-runtime-container-x86_64 | |
| - check-rest-core-proto-sync | |
| runs-on: linux-amd64-cpu16 | |
| 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: Run release-container service tests | |
| env: | |
| BUILD_CONTAINER: nvcr.io/0837451325059433/carbide-dev/build-container-x86_64:${{ needs.prepare.outputs.build_container_x86_64_version }} | |
| CI_COMMIT_SHORT_SHA: ${{ needs.prepare.outputs.short_sha }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${{ github.workspace }}/.sccache" | |
| docker pull "${BUILD_CONTAINER}" | |
| docker run --rm \ | |
| -v "${{ github.workspace }}:/carbide" \ | |
| -v "${{ github.workspace }}/.sccache:/sccache" \ | |
| -w /carbide \ | |
| -e CARGO_HOME=/carbide/cargo \ | |
| -e CARGO_INCREMENTAL=0 \ | |
| -e CARGO_MAKE_SKIP_CODECOV=true \ | |
| -e DATABASE_URL='postgresql://root@%2Fvar%2Frun%2Fpostgresql/root' \ | |
| -e SCCACHE_DIR=/sccache \ | |
| -e RUSTC_WRAPPER=sccache \ | |
| -e CARGO_PROFILE_RELEASE_DEBUG=true \ | |
| -e CI_COMMIT_SHORT_SHA="${CI_COMMIT_SHORT_SHA}" \ | |
| -e VERSION="${VERSION}" \ | |
| -e CONTAINER_REPO_ROOT=/carbide \ | |
| "${BUILD_CONTAINER}" \ | |
| bash -c ' | |
| set -euo pipefail | |
| git config --global --add safe.directory /carbide | |
| /etc/init.d/postgresql start | |
| sudo -u postgres psql -c "ALTER USER root WITH SUPERUSER;" | |
| createdb root | |
| cargo make test-release-container-services | |
| ' | |
| - name: Final repository clean check | |
| run: bash scripts/check-repo-clean.sh "release-container service tests" | |
| # ============================================================================ | |
| # BUILD STAGE - Forge CLI (Multi-arch) | |
| # ============================================================================ | |
| build-forge-cli-x86_64: | |
| needs: | |
| - prepare | |
| - build-artifacts-container-x86_64 | |
| if: ${{ always() && github.event_name != 'schedule' && needs.prepare.result == 'success' }} | |
| 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 | |
| scan: true | |
| secrets: inherit | |
| build-forge-cli-aarch64: | |
| needs: | |
| - prepare | |
| - build-artifacts-container-aarch64 | |
| if: ${{ always() && github.event_name != 'schedule' && needs.prepare.result == 'success' }} | |
| 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-cpu16 | |
| 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-cpu16 | |
| 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 }} | |
| # Multi-arch on push so this x86_64 boot-artifacts carrier can run as an | |
| # init container on both amd64 and arm64 control-plane nodes; the payload | |
| # it ships is unchanged (x86_64 boot blobs). The Dockerfile has no RUN | |
| # steps (FROM alpine + COPY only), so no QEMU is needed. Single-arch on PR | |
| # so the image loads to the daemon for the Grype scan. | |
| platforms: ${{ !contains(github.ref, 'pull-request/') && 'linux/amd64,linux/arm64' || 'linux/amd64' }} | |
| runner: linux-amd64-cpu4 | |
| push: ${{ !contains(github.ref, 'pull-request/') }} | |
| load: true | |
| scan: 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 }} | |
| # Container arch is independent of the payload: this carrier always ships | |
| # the aarch64 boot blobs as files. Build it multi-arch on push so it can | |
| # run as an init container on both amd64 and arm64 control-plane nodes. The | |
| # Dockerfile has no RUN steps (FROM alpine + COPY only), so no QEMU is | |
| # needed. Single-arch on PR so the image loads to the daemon for Grype. | |
| platforms: ${{ !contains(github.ref, 'pull-request/') && 'linux/amd64,linux/arm64' || 'linux/amd64' }} | |
| runner: linux-amd64-cpu4 | |
| push: ${{ !contains(github.ref, 'pull-request/') }} | |
| load: true | |
| scan: 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 | |
| # ============================================================================ | |
| # 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: 'false' | |
| 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: true # load to daemon so the Grype scan can read it on PR builds | |
| scan: true | |
| 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: true # load to daemon so the Grype scan can read it on PR builds | |
| scan: true | |
| secrets: inherit | |
| # arm64 container build of the machine-validation config carrier, so it can run | |
| # as an init container on arm64 control-plane nodes. FROM the aarch64 runtime | |
| # base; pushed as machine_validation-aarch64 and merged into the bare | |
| # machine_validation tag below. (The bundled validation runner payload staying | |
| # arm64-capable is tracked separately — this only makes the carrier runnable on | |
| # arm64 nodes.) | |
| build-release-machine-validation-artifacts-arm-host: | |
| needs: | |
| - prepare | |
| - build-runtime-container-aarch64 | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && contains('success,skipped', needs.build-runtime-container-aarch64.result) }} | |
| uses: ./.github/workflows/docker-build.yml | |
| with: | |
| dockerfile_path: dev/docker/Dockerfile.machine-validation-config-aarch64 | |
| image_name: nvcr.io/0837451325059433/carbide-dev/machine_validation-aarch64 | |
| image_tag: ${{ needs.prepare.outputs.version }} | |
| build_args: '{"CI_COMMIT_SHORT_SHA":"${{ needs.prepare.outputs.short_sha }}","CONTAINER_RUNTIME_AARCH64":"nvcr.io/0837451325059433/carbide-dev/runtime-container-aarch64:${{ needs.prepare.outputs.runtime_container_aarch64_version }}"}' | |
| platforms: linux/arm64 | |
| runner: linux-arm64-cpu4 | |
| push: ${{ !contains(github.ref, 'pull-request/') }} | |
| load: true # load to daemon so the Grype scan can read it on PR builds | |
| scan: true | |
| secrets: inherit | |
| # Combine machine_validation (amd64) and machine_validation-aarch64 into a | |
| # single multi-arch manifest at the bare machine_validation tag. Sources are | |
| # referenced by digest so re-runs are idempotent. Push refs only. | |
| merge-manifests-machine-validation: | |
| needs: | |
| - prepare | |
| - build-release-machine-validation-artifacts-x86-host | |
| - build-release-machine-validation-artifacts-arm-host | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && !contains(github.ref, 'pull-request/') && needs.build-release-machine-validation-artifacts-x86-host.result == 'success' && needs.build-release-machine-validation-artifacts-arm-host.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/machine_validation:${{ needs.prepare.outputs.version }} \ | |
| nvcr.io/0837451325059433/carbide-dev/machine_validation@${{ needs.build-release-machine-validation-artifacts-x86-host.outputs.image_digest }} \ | |
| nvcr.io/0837451325059433/carbide-dev/machine_validation-aarch64@${{ needs.build-release-machine-validation-artifacts-arm-host.outputs.image_digest }} | |
| 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/ | |
| proto-breaking-changes: | |
| name: Proto Breaking Changes Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Required to compute the merge-base against main | |
| - name: Install Buf CLI | |
| run: | | |
| sudo curl -sSL https://github.com/bufbuild/buf/releases/download/v1.70.0/buf-Linux-x86_64 -o /usr/local/bin/buf | |
| sudo chmod +x /usr/local/bin/buf | |
| buf --version | |
| - name: Check for Breaking Changes | |
| run: | | |
| set -euo pipefail | |
| git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main | |
| MERGE_BASE="$(git merge-base HEAD origin/main)" | |
| BASE_PROTO_DIR="$(mktemp -d)" | |
| trap 'rm -rf "${BASE_PROTO_DIR}"' EXIT | |
| echo "Comparing protobuf changes against merge-base ${MERGE_BASE}" | |
| git archive "${MERGE_BASE}" crates/rpc/proto | tar -x -C "${BASE_PROTO_DIR}" | |
| buf breaking crates/rpc/proto \ | |
| --against "${BASE_PROTO_DIR}/crates/rpc/proto" \ | |
| --error-format=github-actions | |
| check-rest-core-proto-sync: | |
| name: Check REST Core Proto Sync | |
| permissions: | |
| contents: read | |
| needs: | |
| - prepare | |
| if: ${{ needs.prepare.outputs.core_rpc_proto_files_changed == 'true' }} | |
| runs-on: linux-amd64-cpu4 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.26.4" | |
| cache: true | |
| cache-dependency-path: rest-api/go.sum | |
| - name: Install buf and protoc plugins | |
| run: | | |
| go install github.com/bufbuild/buf/cmd/buf@v1.70.0 | |
| go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11 | |
| go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.1 | |
| - name: Regenerate REST protos from Core protos | |
| run: | | |
| make -C rest-api core-proto | |
| make -C rest-api/flow gen-nicoapi-pb | |
| - name: Check repository is clean | |
| run: bash scripts/check-repo-clean.sh "REST Core protobuf sync" | |
| 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. | |
| # Durability settings are disabled for speed in CI/DC. | |
| - name: Start PostgreSQL | |
| run: | | |
| printf 'fsync = off\nsynchronous_commit = off\nfull_page_writes = off\n' | tee -a /etc/postgresql/*/main/postgresql.conf | |
| /etc/init.d/postgresql start | |
| sudo -u postgres psql -c "ALTER USER root WITH SUPERUSER;" | |
| createdb root | |
| - name: Run clippy | |
| 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 | |
| - name: Check repository is clean | |
| run: bash scripts/check-repo-clean.sh "Core pre-build checks" | |
| # ============================================================================ | |
| # 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@7de619729962a6bd5e8355b6fb3582a22517d7e5 | |
| 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-validate-helm-prereqs-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 prereqs chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 | |
| with: | |
| chart-path: helm-prereqs | |
| lint: 'true' | |
| template: 'true' | |
| build-push-helm-prereqs-chart: | |
| needs: | |
| - prepare | |
| - build-validate-helm-prereqs-chart | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-validate-helm-prereqs-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 prereqs chart to NGC | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@7de619729962a6bd5e8355b6fb3582a22517d7e5 | |
| with: | |
| chart-path: helm-prereqs | |
| 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-transceiver-exporter: | |
| needs: | |
| - prepare | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' }} | |
| uses: ./.github/workflows/docker-build.yml | |
| with: | |
| dockerfile_path: bluefield/containers/transceiver-exporter/Dockerfile | |
| context_path: . | |
| image_name: nvcr.io/0837451325059433/carbide-dev/transceiver-exporter | |
| image_tag: ${{ needs.prepare.outputs.version }} | |
| platforms: linux/arm64 | |
| runner: linux-arm64-cpu4 | |
| push: ${{ !contains(github.ref, 'pull-request/') }} | |
| load: false | |
| secrets: inherit | |
| download-mft-aarch64: | |
| needs: | |
| - prepare | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' }} | |
| runs-on: linux-arm64-cpu4 | |
| steps: | |
| - name: Download and extract MFT package | |
| run: | | |
| wget https://www.mellanox.com/downloads/MFT/mft-4.35.0-159-aarch64-deb.tgz | |
| tar -zxvf mft-4.35.0-159-aarch64-deb.tgz | |
| rm mft-4.35.0-159-aarch64-deb.tgz | |
| - name: Upload MFT as artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: mft-aarch64-deb-${{ github.run_id }} | |
| path: . | |
| build-bluefield-forge-dpu-agent: | |
| needs: | |
| - prepare | |
| - build-bluefield-binaries | |
| - download-mft-aarch64 | |
| if: ${{ !cancelled() && github.event_name != 'schedule' && needs.prepare.result == 'success' && needs.build-bluefield-binaries.result == 'success' && needs.download-mft-aarch64.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-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 nico-otelcol chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 | |
| with: | |
| chart-path: bluefield/charts/nico-otelcol | |
| lint: 'true' | |
| template: 'true' | |
| - name: Validate nico-dpu-agent chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 | |
| with: | |
| chart-path: bluefield/charts/nico-dpu-agent | |
| lint: 'true' | |
| template: 'true' | |
| - name: Validate nico-dhcp-server chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 | |
| with: | |
| chart-path: bluefield/charts/nico-dhcp-server | |
| lint: 'true' | |
| template: 'true' | |
| - name: Validate nico-fmds chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 | |
| with: | |
| chart-path: bluefield/charts/nico-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 nico-otelcol chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@7de619729962a6bd5e8355b6fb3582a22517d7e5 | |
| with: | |
| chart-path: bluefield/charts/nico-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 | |
| - name: Package and push nico-dpu-agent chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@7de619729962a6bd5e8355b6fb3582a22517d7e5 | |
| with: | |
| chart-path: bluefield/charts/nico-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 | |
| - name: Package and push nico-dhcp-server chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@7de619729962a6bd5e8355b6fb3582a22517d7e5 | |
| with: | |
| chart-path: bluefield/charts/nico-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 | |
| - name: Package and push nico-fmds chart | |
| uses: NVIDIA/dsx-github-actions/.github/actions/helm-package-push@7de619729962a6bd5e8355b6fb3582a22517d7e5 | |
| with: | |
| chart-path: bluefield/charts/nico-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-summary: | |
| runs-on: linux-amd64-cpu4 | |
| if: ${{ always() && github.event_name != 'schedule' && needs.prepare.result == 'success' }} | |
| 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 | |
| - test-release-container-services | |
| - 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-validate-helm-chart | |
| - build-push-helm-chart | |
| - build-validate-helm-prereqs-chart | |
| - build-push-helm-prereqs-chart | |
| - build-release-artifacts-x86-host | |
| - build-release-artifacts-arm-host | |
| - build-bluefield-binaries | |
| - build-bluefield-otelcol-contrib | |
| - build-bluefield-transceiver-exporter | |
| - build-bluefield-forge-dpu-agent | |
| - build-bluefield-forge-dhcp-server | |
| - 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-")) or (.key | startswith("test-"))) | |
| | "| \(.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-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 }} | |
| # ============================================================================ | |
| # CONTAINER SCAN SUMMARY | |
| # ============================================================================ | |
| # Aggregates the per-image `grype-*` artifacts produced by the `scan: true` | |
| # docker-build jobs into a single sticky comment on copy-pr-bot | |
| # `pull-request/N` PRs. Inline Grype only runs on PRs (images are loaded, not | |
| # pushed), so this job is PR-only. Advisory only — intentionally NOT wired | |
| # into `core-ci-pass` so a scan/aggregation hiccup never blocks a merge. | |
| security-container-scan-summary: | |
| name: Container Scan Summary | |
| runs-on: linux-amd64-cpu4 | |
| needs: | |
| - build-release-container-x86_64 | |
| - build-forge-cli-x86_64 | |
| - build-release-artifacts-x86-host | |
| - build-release-artifacts-arm-host | |
| - build-release-machine-validation-runner | |
| - build-release-machine-validation-artifacts-x86-host | |
| if: ${{ always() && contains(github.ref, 'pull-request/') }} | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - uses: NVIDIA/dsx-github-actions/.github/actions/security-container-scan-aggregate@739847ddf00fda38916504ef84e1f504eac3158f | |
| with: | |
| post-pr-comment: 'true' | |
| # ============================================================================ | |
| # NOTIFICATION STAGE | |
| # ============================================================================ | |
| notify-build-status: | |
| if: ${{ always() && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/tags/')) && 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 | |
| - test-release-container-services | |
| - 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-validate-helm-chart | |
| - build-push-helm-chart | |
| - build-validate-helm-prereqs-chart | |
| - build-push-helm-prereqs-chart | |
| - build-release-artifacts-x86-host | |
| - build-release-artifacts-arm-host | |
| - build-bluefield-binaries | |
| - build-bluefield-otelcol-contrib | |
| - build-bluefield-transceiver-exporter | |
| - build-bluefield-forge-dpu-agent | |
| - build-bluefield-forge-dhcp-server | |
| - build-bluefield-carbide-fmds | |
| - build-validate-bluefield-helm-charts | |
| - build-push-bluefield-helm-charts | |
| - 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: "NICo 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 }} | |
| # ============================================================================ | |
| # AGGREGATOR — single required check for branch protection | |
| # ============================================================================ | |
| # Fails iff any required job listed in `needs` is `failure` or `cancelled`. | |
| # `skipped` counts as pass — that's how rest-only PRs unblock when the | |
| # `changes` gate intentionally skips the core pipeline. | |
| # Every stage of each gated release chain is listed so an upstream failure | |
| # cannot be hidden when its downstream jobs become SKIPPED. | |
| # `changes` + `prepare` are also included so a gate or prepare failure doesn't | |
| # silently pass. | |
| # Branch protection ruleset should require ONLY this aggregator + rest-ci-pass. | |
| core-ci-pass: | |
| name: core-ci-pass | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: | |
| - changes | |
| - prepare | |
| # x86_64 release-container chain | |
| - build-container-x86_64 | |
| - build-runtime-container-x86_64 | |
| - build-release-container-x86_64 | |
| # aarch64 release-container chain | |
| - build-container-aarch64 | |
| - build-runtime-container-aarch64 | |
| - build-release-container-aarch64 | |
| - test-release-container-services | |
| # x86_64 release-artifact chain | |
| - build-artifacts-container-x86_64 | |
| - build-boot-artifacts-x86 | |
| - build-boot-artifacts-ephemeral-image-x86-host | |
| - build-release-artifacts-x86-host | |
| # aarch64 release-artifact chain | |
| - build-artifacts-container-aarch64 | |
| - build-boot-artifacts-bfb | |
| - build-boot-artifacts-ephemeral-image-arm-host | |
| - build-release-artifacts-arm-host | |
| - security-secret-scan | |
| - lint-police | |
| - check-rest-core-proto-sync | |
| steps: | |
| - name: Decide pass/fail | |
| env: | |
| NEEDS_JSON: ${{ toJson(needs) }} | |
| run: | | |
| set -euo pipefail | |
| echo "$NEEDS_JSON" | jq -r 'to_entries[] | "\(.key): \(.value.result)"' | |
| if echo "$NEEDS_JSON" | jq -e ' | |
| to_entries | |
| | map(select(.value.result == "failure" or .value.result == "cancelled")) | |
| | length > 0 | |
| ' >/dev/null; then | |
| echo "::error::One or more required jobs failed or were cancelled" | |
| exit 1 | |
| fi | |
| echo "All required jobs OK (success or skipped)" |