Skip to content
Merged
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
21 changes: 19 additions & 2 deletions .github/actions/docker-build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,34 @@ runs:
steps:
- name: NGC Login
shell: sh
env:
BASE_IMAGE_REF: ${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}
run: |
# Only attempt NGC login if API key is available
if [ -n "${{ env.NGC_API_KEY }}" ]; then
if [ -n "${NGC_API_KEY:-}" ]; then
echo "Logging into NGC registry..."
docker login -u \$oauthtoken -p ${{ env.NGC_API_KEY }} nvcr.io
printf '%s' "${NGC_API_KEY}" | docker login -u '$oauthtoken' --password-stdin nvcr.io
echo "✅ Successfully logged into NGC registry"
else
echo "⚠️ NGC_API_KEY not available - skipping NGC login"
echo "This is normal for PRs from forks or when secrets are not configured"
fi

# NGC declines the runner's inherited private-org credentials a pull token
# for the public nvidia/* catalog, so keep those credentials only while
# they can read the base image this build was asked for.
if ! docker buildx imagetools inspect "${BASE_IMAGE_REF}" >/dev/null 2>&1; then
ANON_CONFIG_DIR=$(mktemp -d)
echo '{"credsStore":"","auths":{}}' > "${ANON_CONFIG_DIR}/config.json"
if DOCKER_CONFIG="${ANON_CONFIG_DIR}" docker buildx imagetools inspect \
"${BASE_IMAGE_REF}" >/dev/null 2>&1; then
echo "⚠️ Inherited credentials cannot read ${BASE_IMAGE_REF}; using anonymous access"
echo "DOCKER_CONFIG=${ANON_CONFIG_DIR}" >> "$GITHUB_ENV"
else
rm -rf "${ANON_CONFIG_DIR}"
fi
fi

- name: Build Docker Image
shell: sh
run: |
Expand Down
60 changes: 48 additions & 12 deletions .github/actions/ecr-build-push-pull/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,43 @@ runs:

- name: Setup docker config and login to nvcr.io
shell: bash
env:
BASE_IMAGE_REF: ${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}
run: |
DOCKER_CONFIG_DIR=$(mktemp -d)
if [ -f "${HOME}/.docker/config.json" ]; then
python3 -c "import json; cfg=json.load(open('${HOME}/.docker/config.json')); cfg['credsStore']=''; cfg.pop('credHelpers',None); json.dump(cfg,open('${DOCKER_CONFIG_DIR}/config.json','w'))"
else
echo '{"credsStore":""}' > "${DOCKER_CONFIG_DIR}/config.json"
fi
echo "DOCKER_CONFIG=${DOCKER_CONFIG_DIR}" >> "$GITHUB_ENV"
export DOCKER_CONFIG="${DOCKER_CONFIG_DIR}"

if [ -n "${{ env.NGC_API_KEY }}" ]; then
if [ -n "${NGC_API_KEY:-}" ]; then
echo "🔵 Logging into nvcr.io..."
docker login -u \$oauthtoken -p ${{ env.NGC_API_KEY }} nvcr.io
printf '%s' "${NGC_API_KEY}" | docker login -u '$oauthtoken' --password-stdin nvcr.io
else
echo "🟠 NGC_API_KEY not set - skipping nvcr.io login (normal for fork PRs)"
fi

# NGC refuses the runner's inherited private-org credentials a pull token
# for the public nvidia/* catalog rather than downgrading to anonymous,
# so keep them only if they can actually read the base image.
if ! docker buildx imagetools inspect "${BASE_IMAGE_REF}" >/dev/null 2>&1; then
ANON_CONFIG_DIR=$(mktemp -d)
echo '{"credsStore":"","auths":{}}' > "${ANON_CONFIG_DIR}/config.json"
if DOCKER_CONFIG="${ANON_CONFIG_DIR}" docker buildx imagetools inspect \
"${BASE_IMAGE_REF}" >/dev/null 2>&1; then
echo "🟠 Inherited credentials cannot read ${BASE_IMAGE_REF}; using anonymous access"
rm -rf "${DOCKER_CONFIG_DIR}"
DOCKER_CONFIG_DIR="${ANON_CONFIG_DIR}"
export DOCKER_CONFIG="${DOCKER_CONFIG_DIR}"
else
rm -rf "${ANON_CONFIG_DIR}"
fi
fi

echo "DOCKER_CONFIG=${DOCKER_CONFIG_DIR}" >> "$GITHUB_ENV"

##### 2: Resolve ECR URL #####

# Tries: explicit input >> ECR_CACHE_URL env var >> SSM parameter on EC2.
Expand Down Expand Up @@ -208,16 +228,32 @@ runs:
DEPS_MANIFEST_PATTERN='(setup\.py|pyproject\.toml|setup\.cfg|extension\.toml|requirements[^/]*\.txt|uv\.lock)$'

# Resolve the actual base image digest so a new push of a mutable tag
# (e.g. latest-develop) invalidates the deps cache automatically.
BASE_IMAGE_DIGEST=$(docker buildx imagetools inspect \
"${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}" \
--format '{{json .Manifest.Digest}}' 2>/dev/null | tr -d '"' || true)
if [ -n "${BASE_IMAGE_DIGEST}" ]; then
BASE_IMAGE_UNIQ_ID="${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}:${BASE_IMAGE_DIGEST}"
else
echo "🟠 Could not resolve base image digest, falling back to tag string"
BASE_IMAGE_UNIQ_ID="${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}"
# (e.g. latest-develop) invalidates the deps cache. Failing is deliberate;
# stderr is kept off stdout so diagnostics can never reach the digest.
BASE_IMAGE_DIGEST=""
INSPECT_ERR="$(mktemp)"
for attempt in 1 2 3; do
INSPECT_OUT=$(docker buildx imagetools inspect \
"${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}" \
--format '{{json .Manifest.Digest}}' 2>"${INSPECT_ERR}" || true)
CANDIDATE=$(printf '%s' "${INSPECT_OUT}" | tr -d '"')
case "${CANDIDATE}" in
sha256:*)
BASE_IMAGE_DIGEST="${CANDIDATE}"
break
;;
esac
echo "🟠 Base image manifest read attempt ${attempt}/3 failed: $(tr '\n' ' ' < "${INSPECT_ERR}")"
if [ "${attempt}" -lt 3 ]; then
sleep $((attempt * 5))
fi
done
rm -f "${INSPECT_ERR}"
if [ -z "${BASE_IMAGE_DIGEST}" ]; then
echo "::error::Cannot read the manifest for ${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }} after 3 attempts (see the attempt logs above)."
exit 1
fi
BASE_IMAGE_UNIQ_ID="${{ inputs.isaacsim-base-image }}:${{ inputs.isaacsim-version }}:${BASE_IMAGE_DIGEST}"

echo "🔵 Base image ID: ${BASE_IMAGE_UNIQ_ID}"

Expand Down
Loading