feat: hello world, nemoclaw community #22
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) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| name: Build Sandbox Images | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "sandboxes/**" | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - "sandboxes/**" | |
| workflow_dispatch: | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_PREFIX: ${{ github.repository }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Detect which sandbox images have changed | |
| # --------------------------------------------------------------------------- | |
| detect-changes: | |
| name: Detect changed sandboxes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| base-changed: ${{ steps.changes.outputs.base_changed }} | |
| sandboxes: ${{ steps.changes.outputs.sandboxes }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine changed sandboxes | |
| id: changes | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| # Build everything on manual trigger | |
| BASE_CHANGED="true" | |
| SANDBOXES=$(find sandboxes -mindepth 1 -maxdepth 1 -type d -name '*.base' -prune -o -exec test -f {}/Dockerfile \; -print \ | |
| | xargs -I{} basename {} \ | |
| | grep -v '^base$' \ | |
| | jq -R -s -c 'split("\n") | map(select(length > 0))') | |
| else | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| BASE_SHA="${{ github.event.pull_request.base.sha }}" | |
| else | |
| BASE_SHA="${{ github.event.before }}" | |
| fi | |
| CHANGED=$(git diff --name-only "$BASE_SHA" "${{ github.sha }}" -- sandboxes/) | |
| # Check if base changed | |
| if echo "$CHANGED" | grep -q '^sandboxes/base/'; then | |
| BASE_CHANGED="true" | |
| # When base changes, rebuild all sandboxes that have a Dockerfile | |
| SANDBOXES=$(find sandboxes -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Dockerfile \; -print \ | |
| | xargs -I{} basename {} \ | |
| | grep -v '^base$' \ | |
| | jq -R -s -c 'split("\n") | map(select(length > 0))') | |
| else | |
| BASE_CHANGED="false" | |
| SANDBOXES=$(echo "$CHANGED" \ | |
| | cut -d'/' -f2 \ | |
| | sort -u \ | |
| | while read -r name; do | |
| if [ "$name" != "base" ] && [ -f "sandboxes/${name}/Dockerfile" ]; then echo "$name"; fi | |
| done \ | |
| | jq -R -s -c 'split("\n") | map(select(length > 0))') | |
| fi | |
| fi | |
| echo "base_changed=${BASE_CHANGED}" >> "$GITHUB_OUTPUT" | |
| echo "sandboxes=${SANDBOXES}" >> "$GITHUB_OUTPUT" | |
| echo "Base changed: ${BASE_CHANGED}" | |
| echo "Will build: ${SANDBOXES}" | |
| # --------------------------------------------------------------------------- | |
| # Build the base sandbox image (other sandboxes depend on this) | |
| # --------------------------------------------------------------------------- | |
| build-base: | |
| name: Build base | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.base-changed == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate image metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/sandboxes/base | |
| tags: | | |
| type=sha,prefix= | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Build and push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: sandboxes/base | |
| platforms: linux/amd64,linux/arm64 | |
| push: ${{ github.ref == 'refs/heads/main' }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=base | |
| cache-to: type=gha,mode=max,scope=base | |
| # --------------------------------------------------------------------------- | |
| # Build dependent sandbox images (after base completes) | |
| # --------------------------------------------------------------------------- | |
| build: | |
| name: Build ${{ matrix.sandbox }} | |
| needs: [detect-changes, build-base] | |
| if: | | |
| always() && | |
| needs.detect-changes.result == 'success' && | |
| (needs.build-base.result == 'success' || needs.build-base.result == 'skipped') && | |
| needs.detect-changes.outputs.sandboxes != '[]' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| sandbox: ${{ fromJson(needs.detect-changes.outputs.sandboxes) }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate image metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/sandboxes/${{ matrix.sandbox }} | |
| tags: | | |
| type=sha,prefix= | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Build and push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: sandboxes/${{ matrix.sandbox }} | |
| platforms: linux/amd64,linux/arm64 | |
| push: ${{ github.ref == 'refs/heads/main' }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| build-args: | | |
| BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/sandboxes/base:latest | |
| cache-from: type=gha,scope=${{ matrix.sandbox }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.sandbox }} |