-
Notifications
You must be signed in to change notification settings - Fork 0
Prebuilt GHCR image for E2E CI #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,92 @@ | ||||||||||||||||||
| # Copyright (c) 2026, The Isaac AutoData Project Developers. | ||||||||||||||||||
| # All rights reserved. | ||||||||||||||||||
| # | ||||||||||||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||
|
|
||||||||||||||||||
| name: Build Isaac AutoData image | ||||||||||||||||||
|
|
||||||||||||||||||
| # Publishes the prebuilt GPU test image to GHCR so premerge E2E can skip the | ||||||||||||||||||
| # ~30-minute from-scratch build. The tag is a content hash | ||||||||||||||||||
| # (scripts/ci/image_tag.sh), so it rebuilds only when an image input changes. | ||||||||||||||||||
| on: | ||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||
| push: | ||||||||||||||||||
| branches: [ "main" ] | ||||||||||||||||||
| paths: | ||||||||||||||||||
| - "docker/**" | ||||||||||||||||||
| - ".gitmodules" | ||||||||||||||||||
| - "submodules/IsaacLab-Arena" | ||||||||||||||||||
| - "setup.py" | ||||||||||||||||||
| - "pyproject.toml" | ||||||||||||||||||
| - "scripts/ci/image_tag.sh" | ||||||||||||||||||
| - ".github/workflows/build-image.yml" | ||||||||||||||||||
|
|
||||||||||||||||||
| concurrency: | ||||||||||||||||||
| group: ${{ github.workflow }}-${{ github.ref }} | ||||||||||||||||||
| cancel-in-progress: false | ||||||||||||||||||
|
|
||||||||||||||||||
| permissions: | ||||||||||||||||||
| contents: read | ||||||||||||||||||
| packages: write | ||||||||||||||||||
|
Comment on lines
+28
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Scope GHCR write access to the publishing job. Move 🔐 Proposed fix-permissions:
- contents: read
- packages: write
-
jobs:
build_and_push:
+ permissions:
+ contents: read
+ packages: write📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[error] 31-31: overly broad permissions (excessive-permissions): packages: write is overly broad at the workflow level (excessive-permissions) [warning] 31-31: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment (undocumented-permissions) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||
|
|
||||||||||||||||||
| jobs: | ||||||||||||||||||
| build_and_push: | ||||||||||||||||||
| name: Build & push prebuilt image (GHCR) | ||||||||||||||||||
| runs-on: [self-hosted, gpu] | ||||||||||||||||||
| timeout-minutes: 120 | ||||||||||||||||||
|
|
||||||||||||||||||
| # cuRobo arch baked into the image. Keep in sync with IMAGE_CUDA_ARCH in | ||||||||||||||||||
| # scripts/ci/image_tag.sh so the published tag matches what consumers pull. | ||||||||||||||||||
| env: | ||||||||||||||||||
| TORCH_CUDA_ARCH_LIST: "8.9+PTX" | ||||||||||||||||||
|
|
||||||||||||||||||
|
Comment on lines
+38
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win Enforce one CUDA-architecture input across tagging and building.
Proposed guard env:
+ IMAGE_CUDA_ARCH: "8.9+PTX"
TORCH_CUDA_ARCH_LIST: "8.9+PTX"🤖 Prompt for AI Agents |
||||||||||||||||||
| steps: | ||||||||||||||||||
| - name: nvidia-smi | ||||||||||||||||||
| run: nvidia-smi | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Clean up submodules directory | ||||||||||||||||||
| run: | | ||||||||||||||||||
| rm -f .git/modules/submodules/IsaacLab-Arena/index.lock || true | ||||||||||||||||||
| rm -rf submodules/* || true | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Mark repo as safe for git | ||||||||||||||||||
| run: git config --global --add safe.directory "$PWD" | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Checkout (recursive submodules) | ||||||||||||||||||
| uses: actions/checkout@v5 | ||||||||||||||||||
| with: | ||||||||||||||||||
| submodules: recursive | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Pull LFS files | ||||||||||||||||||
| run: | | ||||||||||||||||||
| git lfs install --local | ||||||||||||||||||
| git lfs pull | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Resolve image tag | ||||||||||||||||||
| id: tag | ||||||||||||||||||
| run: echo "ref=$(./scripts/ci/image_tag.sh)" >> "$GITHUB_OUTPUT" | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Log in to GHCR | ||||||||||||||||||
| env: | ||||||||||||||||||
| GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||
| run: echo "$GHCR_TOKEN" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin | ||||||||||||||||||
|
Comment on lines
+69
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Log out of GHCR on every job exit. This self-hosted runner is reusable, and Proposed cleanup - name: Log out of GHCR
if: always()
run: docker logout ghcr.io || true🧰 Tools🪛 zizmor (1.26.1)[error] 72-72: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| - name: Check whether this image is already published | ||||||||||||||||||
| id: exists | ||||||||||||||||||
| run: | | ||||||||||||||||||
| if docker manifest inspect "${{ steps.tag.outputs.ref }}" >/dev/null 2>&1; then | ||||||||||||||||||
| echo "build=false" >> "$GITHUB_OUTPUT" | ||||||||||||||||||
| echo "Image ${{ steps.tag.outputs.ref }} already published; nothing to do." | ||||||||||||||||||
| else | ||||||||||||||||||
| echo "build=true" >> "$GITHUB_OUTPUT" | ||||||||||||||||||
| fi | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Build image | ||||||||||||||||||
| if: steps.exists.outputs.build == 'true' | ||||||||||||||||||
| run: ./docker/run_docker.sh -c -b | ||||||||||||||||||
|
Comment on lines
+84
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Force a fresh build before publishing. Because this runs on a persistent self-hosted runner, Proposed fix- run: ./docker/run_docker.sh -c -b
+ run: ./docker/run_docker.sh -c -r -b📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| - name: Tag & push to GHCR | ||||||||||||||||||
| if: steps.exists.outputs.build == 'true' | ||||||||||||||||||
| run: | | ||||||||||||||||||
| docker tag isaac_autodata:curobo "${{ steps.tag.outputs.ref }}" | ||||||||||||||||||
| docker push "${{ steps.tag.outputs.ref }}" | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -17,6 +17,7 @@ concurrency: | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||
| packages: read | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Scope This permission is currently workflow-wide, so unrelated jobs such as Proposed permission scope permissions:
contents: read
- packages: read
jobs:
test_e2e:
+ permissions:
+ contents: read
+ # Required to pull the prebuilt image from GHCR.
+ packages: read📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[warning] 20-20: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment (undocumented-permissions) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -97,5 +98,15 @@ jobs: | |||||||||||||||||||||
| git lfs install --local | ||||||||||||||||||||||
| git lfs pull | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Fast path: reuse the prebuilt GHCR image when its content hash matches. | ||||||||||||||||||||||
| # On a miss, run_docker.sh builds locally, so this never gates correctness. | ||||||||||||||||||||||
| - name: Log in to GHCR | ||||||||||||||||||||||
| env: | ||||||||||||||||||||||
| GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||
| run: echo "$GHCR_TOKEN" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin | ||||||||||||||||||||||
|
Comment on lines
+103
to
+106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Log out of GHCR after the E2E job. The self-hosted runner is reused, and Proposed cleanup - name: Log out of GHCR
if: always()
run: docker logout ghcr.io || true🧰 Tools🪛 zizmor (1.26.1)[error] 106-106: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| - name: Pull prebuilt image (fast path) | ||||||||||||||||||||||
| run: ./scripts/ci/pull_or_build_image.sh | ||||||||||||||||||||||
|
Comment on lines
+108
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Make GHCR authentication best-effort. A failed 🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| - name: Run E2E tests | ||||||||||||||||||||||
| run: ./scripts/ci/run_tests.sh | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #!/bin/bash | ||
| # Copyright (c) 2026, The Isaac AutoData Project Developers. | ||
| # All rights reserved. | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Print the GHCR reference for the prebuilt Isaac AutoData test image. | ||
| # | ||
| # The tag is a content hash of the inputs that determine the image: the docker/ | ||
| # tree, the pinned IsaacLab-Arena submodule (which transitively pins IsaacLab), | ||
| # packaging metadata, and the CUDA arch. The build workflow and the E2E pull step | ||
| # both call this, so an unchanged PR resolves to the tag main published (a cache | ||
| # hit). Ids come from the git tree, so no submodule checkout is needed. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| # GHCR repo for the prebuilt image (must be lowercase). | ||
| IMAGE_REPO="${IMAGE_REPO:-ghcr.io/isaac-sim/isaac-autodata}" | ||
| # cuRobo is compiled for this arch and baked into the image (L40S = 8.9). | ||
| # Keep in sync with TORCH_CUDA_ARCH_LIST in .github/workflows/build-image.yml. | ||
| IMAGE_CUDA_ARCH="${IMAGE_CUDA_ARCH:-8.9+PTX}" | ||
|
|
||
| inputs=$(git rev-parse \ | ||
| "HEAD:docker" \ | ||
| "HEAD:.gitmodules" \ | ||
| "HEAD:submodules/IsaacLab-Arena" \ | ||
| "HEAD:setup.py" \ | ||
| "HEAD:pyproject.toml") | ||
|
|
||
| hash=$(printf '%s\n%s\n' "${inputs}" "${IMAGE_CUDA_ARCH}" | sha256sum | cut -c1-16) | ||
| echo "${IMAGE_REPO}:curobo-${hash}" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,24 @@ | ||||||||||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||||||||||
| # Copyright (c) 2026, The Isaac AutoData Project Developers. | ||||||||||||||||||||||||||||
| # All rights reserved. | ||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||
| # Pull the prebuilt E2E image from GHCR (keyed by content hash) and tag it | ||||||||||||||||||||||||||||
| # isaac_autodata:curobo so run_docker.sh reuses it. On any miss, do nothing and | ||||||||||||||||||||||||||||
| # let run_docker.sh build locally, so correctness never depends on the cache. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) | ||||||||||||||||||||||||||||
| LOCAL_TAG="isaac_autodata:curobo" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| REMOTE=$("${SCRIPT_DIR}/image_tag.sh") | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| echo ">>> Prebuilt image: ${REMOTE}" | ||||||||||||||||||||||||||||
| if docker pull "${REMOTE}"; then | ||||||||||||||||||||||||||||
| docker tag "${REMOTE}" "${LOCAL_TAG}" | ||||||||||||||||||||||||||||
| echo ">>> Tagged as ${LOCAL_TAG}; run_docker.sh will reuse it (no build)." | ||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||
| echo ">>> Prebuilt image unavailable (cache miss); run_docker.sh will build locally." | ||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Invalidate stale local images on pull failure. If 🐛 Proposed fix else
+ docker image rm -f "${LOCAL_TAG}" >/dev/null 2>&1 || true
echo ">>> Prebuilt image unavailable (cache miss); run_docker.sh will build locally."
fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the reported YAML lint error.
Use
[main]instead of[ "main" ]; if the truthy-value rule is enforced, quote theonkey or adjust the yamllint configuration.🧰 Tools
🪛 YAMLlint (1.37.1)
[warning] 12-12: truthy value should be one of [false, true]
(truthy)
[error] 15-15: too many spaces inside brackets
(brackets)
[error] 15-15: too many spaces inside brackets
(brackets)
🤖 Prompt for AI Agents
Source: Linters/SAST tools