diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7a9807941..870244bbc 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,9 +42,17 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: cpp-build: - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -54,7 +62,13 @@ jobs: script: ci/build_cpp.sh python-build: needs: [cpp-build] - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/conda-python-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -64,15 +78,29 @@ jobs: script: ci/build_python.sh upload-conda: needs: [cpp-build, python-build] - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/conda-upload-packages.yaml@main + secrets: + CONDA_RAPIDSAI_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_NIGHTLY_TOKEN }} + CONDA_RAPIDSAI_TOKEN: ${{ secrets.CONDA_RAPIDSAI_TOKEN }} with: build_type: ${{ inputs.build_type || 'branch' }} branch: ${{ inputs.branch }} date: ${{ inputs.date }} sha: ${{ inputs.sha }} wheel-build-cuopt-mps-parser: - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -87,8 +115,16 @@ jobs: matrix_filter: 'group_by([.ARCH, (.PY_VER |split(".") | map(tonumber))])|map(max_by([(.CUDA_VER|split(".")|map(tonumber))]))' wheel-publish-cuopt-mps-parser: needs: wheel-build-cuopt-mps-parser - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@main + secrets: + CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }} + RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }} with: build_type: ${{ inputs.build_type || 'branch' }} branch: ${{ inputs.branch }} @@ -98,7 +134,13 @@ jobs: package-type: python wheel-build-libcuopt: needs: wheel-build-cuopt-mps-parser - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -111,8 +153,16 @@ jobs: matrix_filter: group_by([.ARCH, (.CUDA_VER|split(".")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(".")|map(tonumber))) wheel-publish-libcuopt: needs: wheel-build-libcuopt - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@main + secrets: + CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }} + RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }} with: build_type: ${{ inputs.build_type || 'branch' }} branch: ${{ inputs.branch }} @@ -122,7 +172,13 @@ jobs: package-type: cpp wheel-build-cuopt: needs: [wheel-build-cuopt-mps-parser, wheel-build-libcuopt] - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -134,8 +190,16 @@ jobs: package-type: python wheel-publish-cuopt: needs: wheel-build-cuopt - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@main + secrets: + CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }} + RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }} with: build_type: ${{ inputs.build_type || 'branch' }} branch: ${{ inputs.branch }} @@ -144,7 +208,13 @@ jobs: package-name: cuopt package-type: python wheel-build-cuopt-server: - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -159,8 +229,16 @@ jobs: matrix_filter: map(select(.ARCH == "amd64")) | group_by(.CUDA_VER|split(".")|map(tonumber)|.[0]) | map(max_by([(.PY_VER|split(".")|map(tonumber)), (.CUDA_VER|split(".")|map(tonumber))])) wheel-publish-cuopt-server: needs: wheel-build-cuopt-server - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@main + secrets: + CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }} + RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }} with: build_type: ${{ inputs.build_type || 'branch' }} branch: ${{ inputs.branch }} @@ -170,7 +248,13 @@ jobs: package-type: python docs-build: needs: [python-build] - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -184,7 +268,13 @@ jobs: container_image: "rapidsai/ci-conda:26.06-latest" script: "ci/build_docs.sh" wheel-build-cuopt-sh-client: - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: ${{ inputs.build_type || 'branch' }} @@ -200,8 +290,16 @@ jobs: matrix_filter: '[map(select(.ARCH == "amd64")) | min_by((.PY_VER | split(".") | map(tonumber)), (.CUDA_VER | split(".") | map(-tonumber)))]' wheel-publish-cuopt-sh-client: needs: wheel-build-cuopt-sh-client - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@main + secrets: + CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }} + RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }} with: build_type: ${{ inputs.build_type || 'branch' }} branch: ${{ inputs.branch }} @@ -220,6 +318,9 @@ jobs: - wheel-publish-cuopt-sh-client - wheel-publish-libcuopt if: inputs.trigger-tests + permissions: + actions: write + contents: read runs-on: ubuntu-latest # ref: https://docs.github.com/en/actions/reference/security/secure-use#use-an-intermediate-environment-variable env: @@ -235,7 +336,7 @@ jobs: # to pull the actual cuOpt source code from gh workflow run \ --repo NVIDIA/cuopt \ - --ref "${{ github.ref }}" \ + --ref "$GITHUB_REF" \ 'test.yaml' \ -f branch="${INPUT_BRANCH}" \ -f build_type="${INPUT_BUILD_TYPE}" \ @@ -248,13 +349,16 @@ jobs: - tests - build-images - docs-build + permissions: + contents: read runs-on: linux-amd64-cpu4 container: image: python:3.14-slim steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ inputs.sha }} + persist-credentials: false - name: Install dependencies run: apt-get update && apt-get install -y --no-install-recommends curl - name: Send build summary @@ -273,8 +377,14 @@ jobs: - wheel-publish-cuopt - wheel-publish-cuopt-server - wheel-publish-cuopt-sh-client + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: ./.github/workflows/build_test_publish_images.yaml - secrets: inherit + secrets: inherit # zizmor: ignore[secrets-inherit] with: branch: ${{ inputs.branch }} sha: ${{ inputs.sha }} diff --git a/.github/workflows/build_images.yaml b/.github/workflows/build_images.yaml index 78a965efd..63adc882e 100644 --- a/.github/workflows/build_images.yaml +++ b/.github/workflows/build_images.yaml @@ -41,12 +41,13 @@ jobs: runs-on: "linux-${{ matrix.ARCH }}-cpu4" steps: - name: Checkout code repo - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 ref: ${{ inputs.sha }} + persist-credentials: false - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.CUOPT_DOCKERHUB_USERNAME }} password: ${{ secrets.CUOPT_DOCKERHUB_TOKEN }} @@ -61,7 +62,7 @@ jobs: git rev-parse HEAD > ./ci/docker/context/COMMIT_SHA git log -n1 --pretty='%ct' > ./ci/docker/context/COMMIT_TIME - name: Login to NGC - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: "nvcr.io" username: "$oauthtoken" @@ -71,17 +72,20 @@ jobs: run: | docker context create builders - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 with: driver: docker endpoint: ./ci/docker/context - name: Trim CUDA and Python versions id: trim + env: + CUDA_VER: ${{ inputs.CUDA_VER }} + PYTHON_VER: ${{ inputs.PYTHON_VER }} run: | - echo "CUDA_SHORT=$(echo '${{ inputs.CUDA_VER }}' | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT - echo "PYTHON_SHORT=$(echo '${{ inputs.PYTHON_VER }}' | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT + echo "CUDA_SHORT=$(echo "$CUDA_VER" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT + echo "PYTHON_SHORT=$(echo "$PYTHON_VER" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT - name: Build image and push to DockerHub and NGC - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: ./ci/docker/context file: ./ci/docker/Dockerfile @@ -99,6 +103,11 @@ jobs: tags: nvidia/cuopt:${{ inputs.IMAGE_TAG_PREFIX }}-cuda${{ steps.trim.outputs.CUDA_SHORT }}-py${{ steps.trim.outputs.PYTHON_SHORT }}-${{ matrix.ARCH }} - name: Push image to NGC + env: + IMAGE_TAG_PREFIX: ${{ inputs.IMAGE_TAG_PREFIX }} + ARCH: ${{ matrix.ARCH }} + CUDA_SHORT: ${{ steps.trim.outputs.CUDA_SHORT }} + PYTHON_SHORT: ${{ steps.trim.outputs.PYTHON_SHORT }} run: | - docker tag nvidia/cuopt:${{ inputs.IMAGE_TAG_PREFIX }}-cuda${{ steps.trim.outputs.CUDA_SHORT }}-py${{ steps.trim.outputs.PYTHON_SHORT }}-${{ matrix.ARCH }} nvcr.io/nvstaging/nvaie/cuopt:${{ inputs.IMAGE_TAG_PREFIX }}-cuda${{ steps.trim.outputs.CUDA_SHORT }}-py${{ steps.trim.outputs.PYTHON_SHORT }}-${{ matrix.ARCH }} - docker push nvcr.io/nvstaging/nvaie/cuopt:${{ inputs.IMAGE_TAG_PREFIX }}-cuda${{ steps.trim.outputs.CUDA_SHORT }}-py${{ steps.trim.outputs.PYTHON_SHORT }}-${{ matrix.ARCH }} + docker tag "nvidia/cuopt:${IMAGE_TAG_PREFIX}-cuda${CUDA_SHORT}-py${PYTHON_SHORT}-${ARCH}" "nvcr.io/nvstaging/nvaie/cuopt:${IMAGE_TAG_PREFIX}-cuda${CUDA_SHORT}-py${PYTHON_SHORT}-${ARCH}" + docker push "nvcr.io/nvstaging/nvaie/cuopt:${IMAGE_TAG_PREFIX}-cuda${CUDA_SHORT}-py${PYTHON_SHORT}-${ARCH}" diff --git a/.github/workflows/build_test_publish_images.yaml b/.github/workflows/build_test_publish_images.yaml index 85bea2547..de56634cd 100644 --- a/.github/workflows/build_test_publish_images.yaml +++ b/.github/workflows/build_test_publish_images.yaml @@ -63,7 +63,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 # unshallow fetch for setuptools-scm persist-credentials: false @@ -71,13 +71,18 @@ jobs: - name: Compute matrix id: compute-matrix + env: + ARCH: ${{ inputs.arch }} + CUDA_VER: ${{ inputs.cuda_ver }} + PYTHON_VER: ${{ inputs.python_ver }} + LINUX_VER: ${{ inputs.linux_ver }} run: | MATRIX=$(jq -c '.' <> $GITHUB_OUTPUT - echo "PYTHON_SHORT=$(echo '${{ matrix.PYTHON_VER }}' | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT + echo "CUDA_SHORT=$(echo "$CUDA_VER" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT + echo "PYTHON_SHORT=$(echo "$PYTHON_VER" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/')" >> $GITHUB_OUTPUT - name: Create multiarch manifest shell: bash env: @@ -162,7 +171,7 @@ jobs: test-images: name: Test images needs: [build-cuopt-multiarch-manifest, compute-matrix] - secrets: inherit + secrets: inherit # zizmor: ignore[secrets-inherit] strategy: matrix: CUDA_VER: ${{ fromJson(needs.compute-matrix.outputs.MATRIX).cuda_ver }} diff --git a/.github/workflows/cloud_ci.yaml b/.github/workflows/cloud_ci.yaml index ff73fb1f8..e1c5eb0ea 100644 --- a/.github/workflows/cloud_ci.yaml +++ b/.github/workflows/cloud_ci.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. All rights reserved. # SPDX-License-Identifier: Apache-2.0 name: cloud_ci_checker @@ -8,12 +8,17 @@ on: - ${GITHUB_REF##*/} paths: - 'cloud-scripts' + +permissions: {} + jobs: conditional_step: + permissions: + contents: read runs-on: 'ubuntu-22.04' steps: - run: echo "Starting GitHub Actions Job for Cloud CI test notification" - - uses: cinotify/github-action@main + - uses: cinotify/github-action@92a15ed24b17cce1bb185b985c0d463859c5b800 # v1.6.0 with: to: 'cuopt-eng@nvidia.com' subject: 'Cloud scripts change notification' diff --git a/.github/workflows/inactivity_reminder.yaml b/.github/workflows/inactivity_reminder.yaml index 8b65b7806..665c90cd0 100644 --- a/.github/workflows/inactivity_reminder.yaml +++ b/.github/workflows/inactivity_reminder.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 name: Inactivity Reminder with Different Times @@ -7,12 +7,17 @@ on: schedule: - cron: '0 9 * * *' # Runs daily at 09:00 UTC +permissions: {} + jobs: remind: + permissions: + issues: write + pull-requests: write runs-on: ubuntu-latest steps: - name: Remind inactive issues and PRs - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | const MS_IN_DAY = 24 * 60 * 60 * 1000; diff --git a/.github/workflows/issue_automation.yaml b/.github/workflows/issue_automation.yaml index 00e75ba8d..22585a684 100644 --- a/.github/workflows/issue_automation.yaml +++ b/.github/workflows/issue_automation.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 name: Auto-label and Round-Robin Assign Issues @@ -7,12 +7,16 @@ on: issues: types: [opened] +permissions: {} + jobs: auto-label: + permissions: + issues: write runs-on: ubuntu-latest steps: - name: Add awaiting response label to new issues - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | // Only process issues (not PRs) @@ -35,10 +39,12 @@ jobs: } round-robin-assign: + permissions: + issues: write runs-on: ubuntu-latest steps: - name: Assign issue round-robin only if unassigned - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | // Only process issues (not PRs) diff --git a/.github/workflows/nightly-summary.yaml b/.github/workflows/nightly-summary.yaml index 9b745820d..96ffe144c 100644 --- a/.github/workflows/nightly-summary.yaml +++ b/.github/workflows/nightly-summary.yaml @@ -52,15 +52,20 @@ on: CUOPT_SLACK_MENTION_ID: required: false +permissions: {} + jobs: nightly-summary: + permissions: + contents: read runs-on: linux-amd64-cpu4 container: image: python:3.14-slim steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ inputs.sha }} + persist-credentials: false - name: Install dependencies run: | apt-get update && apt-get install -y --no-install-recommends curl diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index b64016851..3e80a2130 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -9,8 +9,13 @@ on: - cron: "0 5 * * *" # 5am UTC / 1am EST +permissions: {} + jobs: trigger-nightly-builds-and-tests: + permissions: + actions: write + contents: read runs-on: ubuntu-latest timeout-minutes: 30 strategy: @@ -19,7 +24,9 @@ jobs: - "main" - "release/26.06" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Trigger Pipeline env: GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 4a1f29319..b0e13243a 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -12,6 +12,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: pr-builder: needs: @@ -33,12 +35,16 @@ jobs: - wheel-build-cuopt-mps-parser - wheel-build-cuopt-sh-client - test-self-hosted-server - secrets: inherit + permissions: + contents: read uses: rapidsai/shared-workflows/.github/workflows/pr-builder.yaml@main if: always() with: needs: ${{ toJSON(needs) }} check-lean-ci: + permissions: + contents: read + pull-requests: read runs-on: ubuntu-latest outputs: lean_ci_enabled: ${{ steps.check-label.outputs.lean_ci_enabled }} @@ -49,7 +55,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: | # Extract PR number from branch name (pull-request/123 -> 123) - PR_NUMBER=$(echo "${{ github.ref }}" | sed 's|refs/heads/pull-request/||') + PR_NUMBER=$(echo "$GITHUB_REF" | sed 's|refs/heads/pull-request/||') echo "Checking PR #$PR_NUMBER for lean-ci label..." # Check if the PR has the 'lean-ci' label @@ -62,12 +68,16 @@ jobs: fi prevent-merge-with-lean-ci: + permissions: + contents: read runs-on: ubuntu-latest needs: check-lean-ci steps: - name: Check lean-ci status + env: + LEAN_CI: ${{ steps.check-lean-ci.outputs.lean_ci_enabled }} run: | - if [ "${{ needs.check-lean-ci.outputs.lean_ci_enabled }}" == "true" ]; then + if [ "$LEAN_CI" == "true" ]; then echo "❌ ERROR: This PR has the 'lean-ci' label enabled." echo "Lean CI is only for testing purposes and should not be merged." echo "Please remove the 'lean-ci' label and run full CI before merging." @@ -78,6 +88,8 @@ jobs: fi compute-matrix-filters: needs: check-lean-ci + permissions: + contents: read runs-on: ubuntu-latest outputs: conda_lean_filter: ${{ steps.set-filters.outputs.conda_lean_filter }} @@ -90,8 +102,10 @@ jobs: steps: - name: Set matrix filters id: set-filters + env: + LEAN_CI: ${{ steps.check-lean-ci.outputs.lean_ci_enabled }} run: | - if [ "${{ needs.check-lean-ci.outputs.lean_ci_enabled }}" == "true" ]; then + if [ "$LEAN_CI" == "true" ]; then echo "conda_lean_filter=[map(select(.ARCH == \"amd64\" and .PY_VER == \"3.11\")) | max_by(.CUDA_VER | split(\".\") | map(tonumber))]" >> $GITHUB_OUTPUT echo "conda_test_filter=[map(select(.ARCH == \"amd64\" and .PY_VER == \"3.13\")) | max_by(.CUDA_VER | split(\".\") | map(tonumber))]" >> $GITHUB_OUTPUT echo "wheel_lean_filter=[map(select(.ARCH == \"amd64\" and .PY_VER == \"3.12\")) | max_by(.CUDA_VER | split(\".\") | map(tonumber))]" >> $GITHUB_OUTPUT @@ -110,7 +124,11 @@ jobs: fi changed-files: - secrets: inherit + permissions: + actions: read + contents: read + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/changed-files.yaml@main with: files_yaml: | @@ -355,7 +373,8 @@ jobs: - '!ucf/**' - '!utilities/**' checks: - secrets: inherit + permissions: + contents: read uses: rapidsai/shared-workflows/.github/workflows/checks.yaml@main with: enable_check_generated_files: false @@ -366,7 +385,13 @@ jobs: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp || fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda || fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-build.yaml@main with: build_type: pull-request @@ -374,6 +399,12 @@ jobs: matrix_filter: ${{ needs.compute-matrix-filters.outputs.conda_lean_filter }} conda-cpp-tests: needs: [conda-cpp-build, changed-files, compute-matrix-filters] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-tests.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp with: @@ -393,7 +424,13 @@ jobs: if: >- fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda || fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/conda-python-build.yaml@main with: build_type: pull-request @@ -401,6 +438,12 @@ jobs: matrix_filter: ${{ needs.compute-matrix-filters.outputs.conda_test_filter }} conda-python-tests: needs: [conda-python-build, changed-files, compute-matrix-filters] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/conda-python-tests.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda with: @@ -417,7 +460,13 @@ jobs: script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} docs-build: needs: [conda-python-build, changed-files] - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs with: @@ -432,7 +481,13 @@ jobs: needs: [compute-matrix-filters, changed-files] # All wheel-build-* jobs feed the wheel test jobs, so they gate on the same group. if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: pull-request @@ -445,7 +500,13 @@ jobs: wheel-build-libcuopt: needs: [wheel-build-cuopt-mps-parser, compute-matrix-filters, changed-files] if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: # build for every combination of arch and CUDA version, but only for the latest Python @@ -457,7 +518,13 @@ jobs: wheel-build-cuopt: needs: [wheel-build-cuopt-mps-parser, wheel-build-libcuopt, compute-matrix-filters, changed-files] if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: pull-request @@ -467,6 +534,12 @@ jobs: matrix_filter: ${{ needs.compute-matrix-filters.outputs.wheel_lean_filter }} wheel-tests-cuopt: needs: [wheel-build-cuopt, wheel-build-cuopt-mps-parser, wheel-build-cuopt-sh-client, changed-files, compute-matrix-filters] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels with: @@ -483,7 +556,13 @@ jobs: wheel-build-cuopt-server: needs: [checks, compute-matrix-filters, changed-files] if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: pull-request @@ -496,7 +575,13 @@ jobs: wheel-build-cuopt-sh-client: needs: [compute-matrix-filters, changed-files] if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main with: build_type: pull-request @@ -509,6 +594,12 @@ jobs: matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_sh_client_filter }} wheel-tests-cuopt-server: needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files, compute-matrix-filters] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels with: @@ -524,7 +615,13 @@ jobs: script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} test-self-hosted-server: needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files] - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: ./.github/workflows/self_hosted_service_test.yaml if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels with: diff --git a/.github/workflows/self_hosted_service_test.yaml b/.github/workflows/self_hosted_service_test.yaml index 0761a653f..edb42cf2e 100644 --- a/.github/workflows/self_hosted_service_test.yaml +++ b/.github/workflows/self_hosted_service_test.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 name: Test self-hosted service on local-setup @@ -66,7 +66,7 @@ jobs: - /tmp/asset_dir/:/tmp/asset_dir/ - /tmp/response_dir/:/tmp/response_dir/ steps: - - uses: aws-actions/configure-aws-credentials@v1-node16 + - uses: aws-actions/configure-aws-credentials@023daa7fe5f7f817faa31fc0fc4a8d0fb6224ed0 # v1-node16 with: role-to-assume: ${{ vars.AWS_ROLE_ARN }} aws-region: ${{ vars.AWS_REGION }} @@ -78,7 +78,7 @@ jobs: run: printf 'machine pypi.k8s.rapids.ai\n\tlogin cibuildwheel\n\tpassword ${{ secrets.RAPIDSAI_PYPI_CI_PASSWORD }}\n' > ~/.netrc - name: checkout code repo - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ inputs.repo }} ref: ${{ inputs.sha }} @@ -94,4 +94,6 @@ jobs: sha: ${{ inputs.sha }} - name: Run tests - run: ${{ inputs.script }} + env: + SCRIPT: ${{ inputs.script }} + run: bash "$SCRIPT" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d2d1b5171..8a39c587e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -25,8 +25,16 @@ on: type: string default: nightly +permissions: {} + jobs: conda-cpp-tests: + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-tests.yaml@main with: build_type: ${{ inputs.build_type }} @@ -43,6 +51,12 @@ jobs: script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} conda-python-tests: + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/conda-python-tests.yaml@main with: run_codecov: false @@ -60,6 +74,12 @@ jobs: script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} wheel-tests-cuopt: + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main with: build_type: ${{ inputs.build_type }} @@ -76,6 +96,12 @@ jobs: script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} wheel-tests-cuopt-server: + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main with: build_type: ${{ inputs.build_type }} @@ -92,7 +118,13 @@ jobs: script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} conda-notebook-tests: - secrets: inherit + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main with: build_type: ${{ inputs.build_type }} @@ -104,6 +136,8 @@ jobs: container_image: "rapidsai/ci-conda:26.06-latest" script: ci/test_notebooks.sh nightly-summary: + permissions: + contents: read if: ${{ always() && inputs.build_type == 'nightly' }} needs: - conda-cpp-tests diff --git a/.github/workflows/test_images.yaml b/.github/workflows/test_images.yaml index 66cbce036..501768009 100644 --- a/.github/workflows/test_images.yaml +++ b/.github/workflows/test_images.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,9 +43,12 @@ jobs: steps: - name: Trim versions id: trim + env: + CUDA_VER: ${{ inputs.CUDA_VER }} + PYTHON_VER: ${{ inputs.PYTHON_VER }} run: | - CUDA_SHORT=$(echo "${{ inputs.CUDA_VER }}" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/') - PYTHON_SHORT=$(echo "${{ inputs.PYTHON_VER }}" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/') + CUDA_SHORT=$(echo "$CUDA_VER" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/') + PYTHON_SHORT=$(echo "$PYTHON_VER" | sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+/\1/') echo "CUDA_SHORT=$CUDA_SHORT" >> $GITHUB_OUTPUT echo "PYTHON_SHORT=$PYTHON_SHORT" >> $GITHUB_OUTPUT @@ -58,10 +61,11 @@ jobs: image: "nvidia/cuopt:${{ inputs.IMAGE_TAG_PREFIX }}-cuda${{ needs.prepare.outputs.CUDA_SHORT }}-py${{ needs.prepare.outputs.PYTHON_SHORT }}" steps: - name: Checkout code repo - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 ref: ${{ inputs.sha }} + persist-credentials: false - name: Test cuopt run: | bash ./ci/docker/test_image.sh diff --git a/.github/workflows/trigger-breaking-change-alert.yaml b/.github/workflows/trigger-breaking-change-alert.yaml index 57b178740..0347178e3 100644 --- a/.github/workflows/trigger-breaking-change-alert.yaml +++ b/.github/workflows/trigger-breaking-change-alert.yaml @@ -3,7 +3,10 @@ name: Trigger Breaking Change Notifications -on: +# `zizmor` always flags these triggers because they are easy to use +# incorrectly. These usages are ok and don't execute any PR-specific +# code (and so aren't susceptible to exploits from forked PRs) +on: # zizmor: ignore[dangerous-triggers] pull_request_target: types: - closed @@ -11,11 +14,16 @@ on: - labeled - unlabeled +permissions: {} + jobs: trigger-notifier: if: contains(github.event.pull_request.labels.*.name, 'breaking') - secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/breaking-change-alert.yaml@main + secrets: + NV_SLACK_BREAKING_CHANGE_ALERT: ${{ secrets.NV_SLACK_BREAKING_CHANGE_ALERT }} + permissions: + contents: read with: sender_login: ${{ github.event.sender.login }} sender_avatar: ${{ github.event.sender.avatar_url }} diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 000000000..1b6ea1e53 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,9 @@ +rules: + unpinned-uses: + config: + policies: + # We require SHA-pinning for all workflows and actions _except_ for those from + # rapidsai/shared-workflows and rapidsai/shared-actions + "rapidsai/shared-workflows/*": any + "rapidsai/shared-actions/*": any + "*": hash-pin diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 24ea8782d..4b5c57d69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -99,6 +99,10 @@ repos: ^[.]cursor-plugin/plugin[.]json$| ^[.]claude-plugin/marketplace[.]json$| ^gemini-extension[.]json$ + - repo: https://github.com/zizmorcore/zizmor-pre-commit + rev: v1.24.1 + hooks: + - id: zizmor - repo: local hooks: - id: update-versions