Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/actions/request-docker-ci/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

name: 'Request Docker CI'
description: >
Starts build.yaml ("Docker + Tests") by toggling the ``ci:run-docker`` label,
which is the only event that workflow triggers on. The token must be a GitHub
App installation token; GitHub does not cascade GITHUB_TOKEN actions into new
workflow runs, so a label applied with GITHUB_TOKEN starts nothing.

inputs:
pr-number:
description: 'Pull request to start Docker CI for'
required: true
token:
description: 'GitHub App installation token with pull-requests: write'
required: true
label:
description: 'Label build.yaml triggers on'
required: false
default: 'ci:run-docker'
expected-head-sha:
description: 'Head commit the caller intends to test; the request is refused if the head moved'
required: true

runs:
using: composite
steps:
- name: Request Docker CI
shell: bash
env:
EXPECTED_HEAD_SHA: ${{ inputs.expected-head-sha }}
GH_TOKEN: ${{ inputs.token }}
LABEL: ${{ inputs.label }}
PR_NUMBER: ${{ inputs.pr-number }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail

# GitHub resolves the head when it processes the label, so labeling a
# PR whose head has already moved on builds a revision nobody asked
# for. Skip the request instead of spending GPU minutes on it.
head_sha="$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER" --jq '.head.sha')"
if [ "$head_sha" != "$EXPECTED_HEAD_SHA" ]; then
echo "::error::PR #$PR_NUMBER moved from ${EXPECTED_HEAD_SHA:0:7} to ${head_sha:0:7} while this request was processed. Comment 'run-ci' again to test the current head."
exit 1
fi

# Removed first because adding an already-present label emits no event,
# and again after so the next request can re-arm it.
endpoint="repos/$REPOSITORY/issues/$PR_NUMBER/labels"
gh api --method DELETE "$endpoint/$LABEL" --silent >/dev/null 2>&1 || true
gh api --method POST "$endpoint" -f "labels[]=$LABEL" --silent
gh api --method DELETE "$endpoint/$LABEL" --silent

# A push can still land between the check above and GitHub processing
# the label; nothing can make those two steps atomic. Re-read the head
# so the mismatch is reported rather than silently testing a revision
# the requester never saw.
built_sha="$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER" --jq '.head.sha')"
if [ "$built_sha" != "$EXPECTED_HEAD_SHA" ]; then
echo "::error::PR #$PR_NUMBER moved to ${built_sha:0:7} as the label was applied, so Docker CI is testing that revision and not the requested ${EXPECTED_HEAD_SHA:0:7}. Comment 'run-ci' again to test the current head."
exit 1
fi

echo "Requested Docker CI for PR #$PR_NUMBER at ${EXPECTED_HEAD_SHA:0:7}." >> "$GITHUB_STEP_SUMMARY"
2 changes: 1 addition & 1 deletion .github/workflows/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
# which the CI credential can reach.
isaacsim_image_name: nvcr.io/0947644777160149/internal/isaac-sim
# Isaac Sim 6.1.0-alpha.50 (b86cf6ce) includes Kit 110.3.0-360924's fix for NVBug 6566677.
isaacsim_image_tag: latest-develop@sha256:1bbd249c2ef8b522bc901d5321a627c750e2e7b609262c56d01b516a60bd7072
isaacsim_image_tag: latest-develop@sha256:769450b03a4c634d709a0f5d4bf96e47bfaf025444b6e4728045b42733575e71
isaaclab_image_name: nvcr.io/0947644777160149/internal/isaac-lab
ovphysx_wheelhouse_image: ""
58 changes: 23 additions & 35 deletions .github/workflows/nightly-isaacsim-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ env:
SOURCE_IMAGE: nvcr.io/0947644777160149/internal/isaac-sim
SOURCE_TAG: latest-develop
TARGET_BRANCH: develop
UPDATE_BRANCH: ci/nightly-isaacsim-image-update
UPDATE_BRANCH: ci/test-nightly-image-update

jobs:
update-image-pin:
Expand All @@ -52,34 +52,13 @@ jobs:
timeout-minutes: 10

steps:
# Reuse the isaaclab-bot App already used by nightly-changelog.yml.
# Requesting the permissions explicitly makes a missing App permission
# fail here with a focused error instead of later at push or PR creation.
- uses: actions/create-github-app-token@v3
id: app-token
with:
client-id: ${{ secrets.CHANGELOG_APP_CLIENT_ID }}
private-key: ${{ secrets.CHANGELOG_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
permission-workflows: write

- uses: actions/checkout@v6
with:
ref: ${{ env.TARGET_BRANCH }}
token: ${{ steps.app-token.outputs.token }}
token: ${{ secrets.FORK_TEST_TOKEN }}
fetch-depth: 0

- name: Log in to the Isaac Sim registry
env:
NGC_API_KEY: ${{ secrets.NGC_API_KEY }}
run: |
set -euo pipefail
if [ -z "$NGC_API_KEY" ]; then
echo "::error::NGC_API_KEY is required to inspect the private Isaac Sim image."
exit 1
fi
printf '%s' "$NGC_API_KEY" | docker login -u '$oauthtoken' --password-stdin nvcr.io

- name: Resolve and update the image digest
id: pin
Expand All @@ -103,7 +82,7 @@ jobs:
exit 1
fi

digest=$(docker buildx imagetools inspect "$SOURCE_IMAGE:$SOURCE_TAG" --format '{{.Manifest.Digest}}')
digest="sha256:769450b03a4c634d709a0f5d4bf96e47bfaf025444b6e4728045b42733575e71" # FORK TEST STUB
digest=$(echo "$digest" | tr -d '[:space:]')
if ! [[ "$digest" =~ ^sha256:[0-9a-f]{64}$ ]]; then
echo "::error::Registry returned an invalid manifest digest: '$digest'."
Expand Down Expand Up @@ -151,12 +130,13 @@ jobs:
} >> "$GITHUB_OUTPUT"

- name: Commit and push the update branch
id: push
if: ${{ steps.pin.outputs.branch_changed == 'true' && !inputs.dry_run }}
run: |
set -euo pipefail

git config user.name "isaaclab-bot[bot]"
git config user.email "282401363+isaaclab-bot[bot]@users.noreply.github.com"
git config user.name "hujc7"
git config user.email "jichuanh@nvidia.com"
git switch -C "$UPDATE_BRANCH"
git add "$CONFIG_PATH"
git commit -m "Bump Isaac Sim CI image digest"
Expand All @@ -170,10 +150,13 @@ jobs:
git push --force-with-lease="$remote_ref:" origin "HEAD:$remote_ref"
fi

echo "head_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

- name: Open or refresh the draft PR
id: pr
if: ${{ steps.pin.outputs.changed == 'true' && !inputs.dry_run }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GH_TOKEN: ${{ secrets.FORK_TEST_TOKEN }}
REPOSITORY: ${{ github.repository }}
IMAGE: ${{ steps.pin.outputs.image }}
CURRENT_PIN: ${{ steps.pin.outputs.current }}
Expand Down Expand Up @@ -214,18 +197,27 @@ jobs:
-F body=@"$body_file" \
--jq '.html_url')
echo "Refreshed draft PR: $pr_url"
echo "Draft PR: $pr_url" >> "$GITHUB_STEP_SUMMARY"
else
pr_url=$(gh api --method POST "repos/$REPOSITORY/pulls" \
read -r pr_number pr_url < <(gh api --method POST "repos/$REPOSITORY/pulls" \
-f title="$title" \
-f head="$UPDATE_BRANCH" \
-f base="$TARGET_BRANCH" \
-F body=@"$body_file" \
-F draft=true \
--jq '.html_url')
--jq '[.number, .html_url] | @tsv')
echo "Opened draft PR: $pr_url"
echo "Draft PR: $pr_url" >> "$GITHUB_STEP_SUMMARY"
fi
echo "Draft PR: $pr_url" >> "$GITHUB_STEP_SUMMARY"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"

# Gated on branch_changed so an unchanged open PR does not re-spend GPU
# minutes every night.
- uses: $/.github/actions/request-docker-ci
if: ${{ steps.pin.outputs.branch_changed == 'true' && !inputs.dry_run }}
with:
pr-number: ${{ steps.pr.outputs.pr_number }}
token: ${{ secrets.FORK_TEST_TOKEN }}
expected-head-sha: ${{ steps.push.outputs.head_sha }}

- name: Report no-op or dry run
if: ${{ steps.pin.outputs.changed != 'true' || inputs.dry_run }}
Expand All @@ -238,7 +230,3 @@ jobs:
else
echo "Dry run: would update \`$CURRENT_PIN\` to \`$CANDIDATE_PIN\`." >> "$GITHUB_STEP_SUMMARY"
fi

- name: Log out of the Isaac Sim registry
if: ${{ always() }}
run: docker logout nvcr.io || true
34 changes: 34 additions & 0 deletions .github/workflows/probe-app-perms.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

name: Probe App Perms
on: workflow_dispatch
permissions:
contents: read
jobs:
contents:
runs-on: ubuntu-latest
steps:
- uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.CHANGELOG_APP_CLIENT_ID }}
private-key: ${{ secrets.CHANGELOG_APP_PRIVATE_KEY }}
permission-contents: write
pull-requests:
runs-on: ubuntu-latest
steps:
- uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.CHANGELOG_APP_CLIENT_ID }}
private-key: ${{ secrets.CHANGELOG_APP_PRIVATE_KEY }}
permission-pull-requests: write
workflows:
runs-on: ubuntu-latest
steps:
- uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.CHANGELOG_APP_CLIENT_ID }}
private-key: ${{ secrets.CHANGELOG_APP_PRIVATE_KEY }}
permission-workflows: write
44 changes: 10 additions & 34 deletions .github/workflows/run-docker-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,38 +70,14 @@ jobs:
private-key: ${{ secrets.CHANGELOG_APP_PRIVATE_KEY }}
permission-pull-requests: write

- name: Trigger Docker CI
env:
EXPECTED_HEAD_SHA: ${{ steps.authorize.outputs.head_sha }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
LABEL: ci:run-docker
PR_NUMBER: ${{ github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail

# GitHub resolves the head when it processes the label, so labeling a
# PR whose head has already moved on builds a revision nobody asked
# for. Skip the request instead of spending GPU minutes on it.
head_sha="$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER" --jq '.head.sha')"
if [ "$head_sha" != "$EXPECTED_HEAD_SHA" ]; then
echo "::error::PR #$PR_NUMBER moved from ${EXPECTED_HEAD_SHA:0:7} to ${head_sha:0:7} while this request was processed. Comment 'run-ci' again to test the current head."
exit 1
fi

endpoint="repos/$REPOSITORY/issues/$PR_NUMBER/labels"
gh api --method DELETE "$endpoint/$LABEL" --silent >/dev/null 2>&1 || true
gh api --method POST "$endpoint" -f "labels[]=$LABEL" --silent
gh api --method DELETE "$endpoint/$LABEL" --silent

# A push can still land between the check above and GitHub processing
# the label; nothing can make those two steps atomic. Re-read the head
# so the mismatch is reported rather than silently testing a revision
# the requester never saw.
built_sha="$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER" --jq '.head.sha')"
if [ "$built_sha" != "$EXPECTED_HEAD_SHA" ]; then
echo "::error::PR #$PR_NUMBER moved to ${built_sha:0:7} as the label was applied, so Docker CI is testing that revision and not the requested ${EXPECTED_HEAD_SHA:0:7}. Comment 'run-ci' again to test the current head."
exit 1
fi
- uses: actions/checkout@v6
with:
fetch-depth: 1
sparse-checkout: .github/actions/request-docker-ci
sparse-checkout-cone-mode: false

echo "Requested Docker CI for PR #$PR_NUMBER at ${EXPECTED_HEAD_SHA:0:7}." >> "$GITHUB_STEP_SUMMARY"
- uses: ./.github/actions/request-docker-ci
with:
pr-number: ${{ github.event.issue.number }}
token: ${{ steps.app-token.outputs.token }}
expected-head-sha: ${{ steps.authorize.outputs.head_sha }}
Loading