Merge pull request #4 from maggiezha/k8s-autoscaling #1
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 | |
| # Build and push the sandbox base images to GHCR. | |
| # | |
| # Triggers: | |
| # - Push to main when a base-image workflow input changes | |
| # - Manual dispatch for ad-hoc rebuilds | |
| # | |
| # The base image contains the expensive, rarely-changing layers (apt, gosu, | |
| # user setup, openclaw CLI). The production Dockerfile layers PR-specific | |
| # code on top via: FROM ghcr.io/nvidia/nemoclaw/sandbox-base:<tag> | |
| name: Images / Base Images | |
| on: | |
| push: | |
| branches: [main] | |
| tags: | |
| - "v*" | |
| paths: | |
| # Re-run when this workflow gains or changes a publisher so the new path | |
| # takes effect immediately after merge instead of waiting for another tag. | |
| - ".github/workflows/base-image.yaml" | |
| - "Dockerfile.base" | |
| - "agents/hermes/Dockerfile.base" | |
| - "agents/langchain-deepagents-code/Dockerfile.base" | |
| - "agents/langchain-deepagents-code/manifest.yaml" | |
| - "agents/langchain-deepagents-code/requirements.lock" | |
| - "agents/openclaw/mcporter-runtime/package.json" | |
| - "agents/openclaw/mcporter-runtime/package-lock.json" | |
| # Dockerfile.base validates min_openclaw_version from this file at build time. | |
| - "nemoclaw-blueprint/blueprint.yaml" | |
| - "scripts/lib/openclaw-npm-remediation.mts" | |
| - "scripts/lib/reviewed-npm-archive.mts" | |
| - "scripts/checks/node-tar-image-scan.mts" | |
| - "scripts/patch-bundled-npm-tar.mts" | |
| - "scripts/lib/sandbox-rlimits.sh" | |
| workflow_dispatch: | |
| inputs: | |
| openclaw_version: | |
| description: "OpenClaw version to install (leave blank to use the default in Dockerfile.base)" | |
| required: false | |
| default: "" | |
| permissions: | |
| contents: read | |
| packages: write | |
| concurrency: | |
| group: base-image | |
| cancel-in-progress: true | |
| env: | |
| REGISTRY: ghcr.io | |
| jobs: | |
| # Keep one declarative publisher configuration while giving each base image | |
| # an independently observable matrix job and registry cache namespace. | |
| build-and-push: | |
| name: Build and push ${{ matrix.display_name }} base image | |
| if: github.repository == 'NVIDIA/NemoClaw' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - agent: openclaw | |
| display_name: OpenClaw | |
| dockerfile: Dockerfile.base | |
| image: nvidia/nemoclaw/sandbox-base | |
| - agent: hermes | |
| display_name: Hermes | |
| dockerfile: agents/hermes/Dockerfile.base | |
| image: nvidia/nemoclaw/hermes-sandbox-base | |
| - agent: langchain-deepagents-code | |
| display_name: Deep Agents Code | |
| dockerfile: agents/langchain-deepagents-code/Dockerfile.base | |
| image: nvidia/nemoclaw/langchain-deepagents-code-sandbox-base | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Set up QEMU (arm64 emulation) | |
| uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0 | |
| env: | |
| DOCKER_METADATA_SHORT_SHA_LENGTH: 8 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ matrix.image }} | |
| tags: | | |
| type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} | |
| type=ref,event=tag | |
| type=sha,prefix=,format=short | |
| - name: Validate production Docker build args | |
| id: production-build-args | |
| env: | |
| AGENT: ${{ matrix.agent }} | |
| OPENCLAW_VERSION_INPUT: ${{ inputs.openclaw_version }} | |
| run: | | |
| set -euo pipefail | |
| build_args=() | |
| openclaw_build_arg="" | |
| if [ "$AGENT" = "openclaw" ] && [ -n "${OPENCLAW_VERSION_INPUT}" ]; then | |
| openclaw_build_arg="OPENCLAW_VERSION=${OPENCLAW_VERSION_INPUT}" | |
| build_args+=(--build-arg "$openclaw_build_arg") | |
| fi | |
| if [ "${#build_args[@]}" -gt 0 ]; then | |
| scripts/check-production-build-args.sh "${build_args[@]}" | |
| else | |
| scripts/check-production-build-args.sh | |
| fi | |
| if [ "$AGENT" = "openclaw" ] && [ -n "${OPENCLAW_VERSION_INPUT}" ]; then | |
| if [[ "$OPENCLAW_VERSION_INPUT" == *$'\r'* || "$OPENCLAW_VERSION_INPUT" == *$'\n'* ]]; then | |
| echo "ERROR: OpenClaw version must not contain CR or LF characters." >&2 | |
| exit 1 | |
| fi | |
| if [[ ! "$OPENCLAW_VERSION_INPUT" =~ ^[0-9]+([.][0-9]+)*$ ]]; then | |
| echo "ERROR: OpenClaw version must be a whole decimal dotted version (for example, 2026.6.10)." >&2 | |
| exit 1 | |
| fi | |
| fi | |
| printf 'openclaw_build_arg=%s\n' "$openclaw_build_arg" >> "$GITHUB_OUTPUT" | |
| - name: Build and push | |
| uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 | |
| with: | |
| context: . | |
| file: ${{ matrix.dockerfile }} | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ matrix.image }}:buildcache | |
| cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ matrix.image }}:buildcache,mode=max | |
| build-args: ${{ steps.production-build-args.outputs.openclaw_build_arg }} |