From 69492bf5bf1273348439680bf6133fde7fbad7f1 Mon Sep 17 00:00:00 2001 From: nv-dmendoza <117955115+nv-dmendoza@users.noreply.github.com> Date: Mon, 29 Jun 2026 23:03:24 +0000 Subject: [PATCH 1/3] feat(ci): add feature branch creation and building containers on feat/* --- .github/workflows/ci.yaml | 91 ++++++++++++++++------------ .github/workflows/feature-branch.yml | 69 +++++++++++++++++++++ 2 files changed, 122 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/feature-branch.yml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 93cd9ca215..ce053ee85f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,6 +21,7 @@ on: branches: - main - "pull-request/[0-9]+" + - "feat/*" 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]*" @@ -33,7 +34,6 @@ env: FF_USE_FASTZIP: "true" GIT_SUBMODULE_STRATEGY: recursive - jobs: changes: name: Detect Core CI Gate @@ -164,6 +164,23 @@ jobs: HELM_VERSION_BASE="${VERSION#v}" HELM_VERSION=$(echo "$HELM_VERSION_BASE" | sed 's/\(.*\)-/\1./') + # Feature branch support + IS_FEATURE_BRANCH=false + if [[ "${GITHUB_REF}" =~ ^refs/heads/feat/ ]]; then + IS_FEATURE_BRANCH=true + FIRST_PARENT_TAG=$(git describe --tags --first-parent --abbrev=0 HEAD 2>/dev/null || echo "") + + # error if feature branch made not using /feature-branch command + if [[ "${FIRST_PARENT_TAG}" != *"feat-"* ]]; then + FEAT_BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr '/' '-') + echo "## ❌ Feature Branch Tag Generation Failed" >> $GITHUB_STEP_SUMMARY + echo "First parent tag does not contain \`feat-\`, tag found: \`${FIRST_PARENT_TAG}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**To fix:** ask a maintainer to delete this branch, then use \`/feature-branch ${FEAT_BRANCH#feat-}\` in a GitHub issue to recreate it correctly." >> $GITHUB_STEP_SUMMARY + exit 1 + fi + fi + echo "version=${VERSION}" >> $GITHUB_OUTPUT echo "helm_version=${HELM_VERSION}" >> $GITHUB_OUTPUT echo "Calculated VERSION: ${VERSION}" @@ -822,7 +839,7 @@ jobs: push: ${{ !contains(github.ref, 'pull-request/') }} load: true scan: true - download_artifacts: true # Download boot and ephemeral artifacts for packaging + download_artifacts: true # Download boot and ephemeral artifacts for packaging build_args: | { "VERSION": "${{ needs.prepare.outputs.version }}", @@ -853,7 +870,7 @@ jobs: push: ${{ !contains(github.ref, 'pull-request/') }} load: true scan: true - download_artifacts: true # Download boot and ephemeral artifacts for packaging + download_artifacts: true # Download boot and ephemeral artifacts for packaging build_args: | { "VERSION": "${{ needs.prepare.outputs.version }}", @@ -879,14 +896,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 with: - fetch-depth: 0 # Full history for secret scanning + 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' + extra-args: "--results=verified,unknown --only-verified" + post-pr-comment: "false" + fail-on-findings: "true" security-codeql-scan: name: CodeQL Security Analysis @@ -906,20 +923,18 @@ jobs: - 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 - + 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 @@ -934,7 +949,7 @@ jobs: 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 + load: true # load to daemon so the Grype scan can read it on PR builds scan: true secrets: inherit @@ -952,7 +967,7 @@ jobs: 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 + load: true # load to daemon so the Grype scan can read it on PR builds scan: true secrets: inherit @@ -976,7 +991,7 @@ jobs: 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 + load: true # load to daemon so the Grype scan can read it on PR builds scan: true secrets: inherit @@ -1161,8 +1176,8 @@ jobs: uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 with: chart-path: helm - lint: 'true' - template: 'true' + lint: "true" + template: "true" build-push-helm-chart: needs: @@ -1180,7 +1195,7 @@ jobs: chart-path: helm chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: 'false' + lint: "false" ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1198,8 +1213,8 @@ jobs: uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 with: chart-path: helm-prereqs - lint: 'true' - template: 'true' + lint: "true" + template: "true" build-push-helm-prereqs-chart: needs: @@ -1217,7 +1232,7 @@ jobs: chart-path: helm-prereqs chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: 'false' + lint: "false" ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1389,29 +1404,29 @@ jobs: uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 with: chart-path: bluefield/charts/nico-otelcol - lint: 'true' - template: 'true' + 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' + 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' + 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' + lint: "true" + template: "true" build-push-bluefield-helm-charts: needs: @@ -1429,7 +1444,7 @@ jobs: chart-path: bluefield/charts/nico-otelcol chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: 'false' + lint: "false" ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1440,7 +1455,7 @@ jobs: chart-path: bluefield/charts/nico-dpu-agent chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: 'false' + lint: "false" ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1451,7 +1466,7 @@ jobs: chart-path: bluefield/charts/nico-dhcp-server chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: 'false' + lint: "false" ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1462,7 +1477,7 @@ jobs: chart-path: bluefield/charts/nico-fmds chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: 'false' + lint: "false" ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1592,7 +1607,7 @@ jobs: steps: - uses: NVIDIA/dsx-github-actions/.github/actions/security-container-scan-aggregate@739847ddf00fda38916504ef84e1f504eac3158f with: - post-pr-comment: 'true' + post-pr-comment: "true" # ============================================================================ # NOTIFICATION STAGE diff --git a/.github/workflows/feature-branch.yml b/.github/workflows/feature-branch.yml new file mode 100644 index 0000000000..f236d898b6 --- /dev/null +++ b/.github/workflows/feature-branch.yml @@ -0,0 +1,69 @@ +name: Create Feature Branch + +on: + issue_comment: + types: + - created + +jobs: + create-feat-branch: + if: startsWith(github.event.comment.body, '/feature-branch ') + runs-on: ubuntu-latest + permissions: + contents: write + issues: write + steps: + - name: Checkout main + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create feature branch with empty commit + env: + COMMENT_BODY: ${{ github.event.comment.body }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_URL: ${{ github.event.issue.html_url }} + REQUESTER: ${{ github.event.comment.user.login }} + REPOSITORY: ${{ github.repository }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + BRANCH_NAME=$(echo "${COMMENT_BODY}" | sed 's|^/feature-branch ||' | tr -d '[:space:]') + + if [[ -z "${BRANCH_NAME}" ]]; then + echo "No branch name provided" + exit 1 + fi + + FULL_BRANCH="feat/${BRANCH_NAME}" + + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + TAG_PREFIX=$(git describe --tags --long HEAD | sed 's/-g[0-9a-f]*$//') + FEAT_SLUG=$(echo "${FULL_BRANCH}" | tr '/' '-') + TAG="${TAG_PREFIX}-${FEAT_SLUG}" + + git checkout -b "${FULL_BRANCH}" + COMMIT_MSG="feat: initialize ${FULL_BRANCH}" + COMMIT_MSG+=$'\n\n' + COMMIT_MSG+="Requested by @${REQUESTER} on issue #${ISSUE_NUMBER}" + git commit --allow-empty -m "${COMMIT_MSG}" + + git tag "${TAG}" + git push origin "${FULL_BRANCH}" "${TAG}" + + BRANCH_URL="https://github.com/${REPOSITORY}/tree/${FULL_BRANCH}" + COMMENT_BODY="Branch created: [${FULL_BRANCH}](${BRANCH_URL})" + COMMENT_BODY+=$'\n\n' + COMMENT_BODY+="To check out locally:" + COMMENT_BODY+=$'\n' + COMMENT_BODY+='```' + COMMENT_BODY+=$'\n' + COMMENT_BODY+="git fetch upstream && git checkout -b ${FULL_BRANCH} upstream/${FULL_BRANCH}" + COMMENT_BODY+=$'\n' + COMMENT_BODY+='```' + gh issue comment "${ISSUE_NUMBER}" --body "${COMMENT_BODY}" From cbbec2da8841f0352d48f70ceb1c9e1ec0ad47a6 Mon Sep 17 00:00:00 2001 From: nv-dmendoza <117955115+nv-dmendoza@users.noreply.github.com> Date: Mon, 29 Jun 2026 23:31:50 +0000 Subject: [PATCH 2/3] fix: remove whitespace changes --- .github/workflows/ci.yaml | 73 ++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ce053ee85f..9988ce3656 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -34,6 +34,7 @@ env: FF_USE_FASTZIP: "true" GIT_SUBMODULE_STRATEGY: recursive + jobs: changes: name: Detect Core CI Gate @@ -839,7 +840,7 @@ jobs: push: ${{ !contains(github.ref, 'pull-request/') }} load: true scan: true - download_artifacts: true # Download boot and ephemeral artifacts for packaging + download_artifacts: true # Download boot and ephemeral artifacts for packaging build_args: | { "VERSION": "${{ needs.prepare.outputs.version }}", @@ -870,7 +871,7 @@ jobs: push: ${{ !contains(github.ref, 'pull-request/') }} load: true scan: true - download_artifacts: true # Download boot and ephemeral artifacts for packaging + download_artifacts: true # Download boot and ephemeral artifacts for packaging build_args: | { "VERSION": "${{ needs.prepare.outputs.version }}", @@ -896,14 +897,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 with: - fetch-depth: 0 # Full history for secret scanning + 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" + extra-args: '--results=verified,unknown --only-verified' + post-pr-comment: 'false' + fail-on-findings: 'true' security-codeql-scan: name: CodeQL Security Analysis @@ -923,18 +924,20 @@ jobs: - 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 + 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 @@ -949,7 +952,7 @@ jobs: 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 + load: true # load to daemon so the Grype scan can read it on PR builds scan: true secrets: inherit @@ -967,7 +970,7 @@ jobs: 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 + load: true # load to daemon so the Grype scan can read it on PR builds scan: true secrets: inherit @@ -991,7 +994,7 @@ jobs: 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 + load: true # load to daemon so the Grype scan can read it on PR builds scan: true secrets: inherit @@ -1176,8 +1179,8 @@ jobs: uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 with: chart-path: helm - lint: "true" - template: "true" + lint: 'true' + template: 'true' build-push-helm-chart: needs: @@ -1195,7 +1198,7 @@ jobs: chart-path: helm chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: "false" + lint: 'false' ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1213,8 +1216,8 @@ jobs: uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 with: chart-path: helm-prereqs - lint: "true" - template: "true" + lint: 'true' + template: 'true' build-push-helm-prereqs-chart: needs: @@ -1232,7 +1235,7 @@ jobs: chart-path: helm-prereqs chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: "false" + lint: 'false' ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1404,29 +1407,29 @@ jobs: uses: NVIDIA/dsx-github-actions/.github/actions/helm-validate@94bde998f5d7965576b0c663db7d5d709c918167 with: chart-path: bluefield/charts/nico-otelcol - lint: "true" - template: "true" + 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" + 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" + 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" + lint: 'true' + template: 'true' build-push-bluefield-helm-charts: needs: @@ -1444,7 +1447,7 @@ jobs: chart-path: bluefield/charts/nico-otelcol chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: "false" + lint: 'false' ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1455,7 +1458,7 @@ jobs: chart-path: bluefield/charts/nico-dpu-agent chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: "false" + lint: 'false' ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1466,7 +1469,7 @@ jobs: chart-path: bluefield/charts/nico-dhcp-server chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: "false" + lint: 'false' ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1477,7 +1480,7 @@ jobs: chart-path: bluefield/charts/nico-fmds chart-version: ${{ needs.prepare.outputs.helm_version }} app-version: ${{ needs.prepare.outputs.version }} - lint: "false" + lint: 'false' ngc-key: ${{ secrets.NVCR_TOKEN }} ngc-path: 0837451325059433/carbide-dev ngc-duplicate: fail @@ -1607,7 +1610,7 @@ jobs: steps: - uses: NVIDIA/dsx-github-actions/.github/actions/security-container-scan-aggregate@739847ddf00fda38916504ef84e1f504eac3158f with: - post-pr-comment: "true" + post-pr-comment: 'true' # ============================================================================ # NOTIFICATION STAGE From 48c3ee85f8b6b63465b283fe7d1ff7322ed73a00 Mon Sep 17 00:00:00 2001 From: nv-dmendoza <117955115+nv-dmendoza@users.noreply.github.com> Date: Mon, 29 Jun 2026 23:36:58 +0000 Subject: [PATCH 3/3] fix: add changes to rest-ci --- .github/workflows/rest-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rest-ci.yml b/.github/workflows/rest-ci.yml index d5e4395e06..94e1eb3737 100644 --- a/.github/workflows/rest-ci.yml +++ b/.github/workflows/rest-ci.yml @@ -9,6 +9,7 @@ on: branches: - main - 'pull-request/[0-9]+' + - 'feat/*' 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]*"