diff --git a/.github/workflows/publish-images.yaml b/.github/workflows/publish-images.yaml index 30fe4f22772d..2dee4303e8db 100644 --- a/.github/workflows/publish-images.yaml +++ b/.github/workflows/publish-images.yaml @@ -54,7 +54,7 @@ jobs: echo "Resolved branches: $arr" build-and-push-images: - name: Build and Push (${{ matrix.branch }}) + name: Build and Push (${{ matrix.branch }} / ${{ matrix.image.key }}) needs: resolve-branches runs-on: [self-hosted, gpu] timeout-minutes: 180 @@ -62,8 +62,25 @@ jobs: fail-fast: false matrix: branch: ${{ fromJson(needs.resolve-branches.outputs.branches) }} + image: + - key: base + tag_suffix: "" + dockerfile: docker/Dockerfile.base + isaacsim_base: "true" + # Empty: follow whatever the Isaac Sim base image supports. + platforms: "" + build_args: --build-arg DOCKER_USER_HOME_ARG=/root + - key: kitless + # Same repository as the base image, distinguished by a tag suffix. + tag_suffix: "-kitless" + dockerfile: docker/Dockerfile.kitless + # Builds on ubuntu, so it takes none of the Isaac Sim build arguments. + isaacsim_base: "false" + # No arm64 GPU runner validates this build yet. + platforms: linux/amd64 + build_args: --build-arg DOCKER_USER_HOME_ARG=/home/isaaclab concurrency: - group: publish-images-${{ matrix.branch }} + group: publish-images-${{ matrix.branch }}-${{ matrix.image.key }} cancel-in-progress: true environment: name: postmerge-production @@ -133,6 +150,15 @@ jobs: run: | IMAGE_BASE_VERSION="${{ steps.config.outputs.isaacsim_image_tag }}" IMAGE="${{ steps.config.outputs.isaaclab_image_name }}" + DOCKERFILE="${{ matrix.image.dockerfile }}" + SUFFIX="${{ matrix.image.tag_suffix }}" + + # Not every publishable branch carries every Dockerfile. A branch cut + # before an image was introduced skips it instead of failing the run. + if [ ! -f "$DOCKERFILE" ]; then + echo "🟠 $DOCKERFILE does not exist on '$BRANCH_NAME'; nothing to publish." + exit 0 + fi # Use the SHA actually checked out for this branch (the matrix ref), not # github.sha — on a scheduled run github.sha is the default branch HEAD, @@ -161,14 +187,14 @@ jobs: case "$BRANCH_NAME" in develop) - MOVING_TAG="$IMAGE:latest-develop" - IMMUTABLE_TAG="$IMAGE:latest-develop-$FULL_SHA" + MOVING_TAG="$IMAGE:latest-develop$SUFFIX" + IMMUTABLE_TAG="$IMAGE:latest-develop-$FULL_SHA$SUFFIX" ;; release/*) # Sanitize the part after release/ for use as a Docker tag suffix. RELEASE_SUFFIX=$(echo "${BRANCH_NAME#release/}" | sed 's/[^a-zA-Z0-9._-]/-/g') - MOVING_TAG="$IMAGE:latest-release-$RELEASE_SUFFIX" - IMMUTABLE_TAG="$IMAGE:latest-release-$RELEASE_SUFFIX-$FULL_SHA" + MOVING_TAG="$IMAGE:latest-release-$RELEASE_SUFFIX$SUFFIX" + IMMUTABLE_TAG="$IMAGE:latest-release-$RELEASE_SUFFIX-$FULL_SHA$SUFFIX" ;; main) # main is intentionally not published here; see postmerge-ci.yml for main. @@ -195,8 +221,14 @@ jobs: echo "🔵 Checking if base image supports multiarch..." BASE_IMAGE_FULL="${{ steps.config.outputs.isaacsim_image_name }}:${IMAGE_BASE_VERSION}" ARCHITECTURES=$(docker manifest inspect "$BASE_IMAGE_FULL" 2>/dev/null | grep -o '"architecture": "[^"]*"' | cut -d'"' -f4 | sort -u) + EXPLICIT_PLATFORMS="${{ matrix.image.platforms }}" - if [ -z "$ARCHITECTURES" ]; then + if [ -n "$EXPLICIT_PLATFORMS" ]; then + # An image that does not build on the Isaac Sim base pins its own + # platforms; the probe above does not describe it. + BUILD_PLATFORMS="$EXPLICIT_PLATFORMS" + echo "Using explicit platforms: $BUILD_PLATFORMS" + elif [ -z "$ARCHITECTURES" ]; then echo "🟠 Could not inspect base image manifest: $BASE_IMAGE_FULL - defaulting to linux/amd64 only" BUILD_PLATFORMS="linux/amd64" else @@ -231,19 +263,29 @@ jobs: TAG_ARGS+=("-t" "$t") done + BUILD_ARG_FLAGS=( + --build-arg "ISAACLAB_PATH_ARG=/workspace/isaaclab" + ${{ matrix.image.build_args }} + ) + # Only the Isaac Sim-based image declares these; passing them to an image + # that does not leaves unconsumed build arguments in the build log. + if [ "${{ matrix.image.isaacsim_base }}" = "true" ]; then + BUILD_ARG_FLAGS+=( + --build-arg "ISAACSIM_BASE_IMAGE_ARG=${{ steps.config.outputs.isaacsim_image_name }}" + --build-arg "ISAACSIM_VERSION_ARG=$IMAGE_BASE_VERSION" + --build-arg "ISAACSIM_ROOT_PATH_ARG=/isaac-sim" + ) + fi + echo "🔵 Building and pushing image with tags listed above..." if ! docker buildx build \ --platform "$BUILD_PLATFORMS" \ --progress=plain \ "${TAG_ARGS[@]}" \ - --build-arg ISAACSIM_BASE_IMAGE_ARG=${{ steps.config.outputs.isaacsim_image_name }} \ - --build-arg ISAACSIM_VERSION_ARG="$IMAGE_BASE_VERSION" \ - --build-arg ISAACSIM_ROOT_PATH_ARG=/isaac-sim \ - --build-arg ISAACLAB_PATH_ARG=/workspace/isaaclab \ - --build-arg DOCKER_USER_HOME_ARG=/root \ - --cache-from type=gha \ - --cache-to type=gha,mode=max \ - -f docker/Dockerfile.base \ + "${BUILD_ARG_FLAGS[@]}" \ + --cache-from type=gha,scope=publish-${{ matrix.image.key }} \ + --cache-to type=gha,mode=max,scope=publish-${{ matrix.image.key }} \ + -f "$DOCKERFILE" \ --push .; then echo "🔴 docker buildx build/push failed for tags:" printf ' - %s\n' "${TAGS[@]}"