diff --git a/.docker/docker-bake.hcl b/.docker/docker-bake.hcl new file mode 100644 index 00000000..34864353 --- /dev/null +++ b/.docker/docker-bake.hcl @@ -0,0 +1,88 @@ +# +# Override these variables with environment variables +# e.g. +# +# BLUE_ROS_DISTRO=iron docker buildx bake +# +# or +# +# export BLUE_ROS_DISTRO=iron +# docker buildx bake +# +variable "BLUE_ROS_DISTRO" { default = "rolling" } +variable "BLUE_GITHUB_REPO" { default = "robotic-decision-making-lab/blue" } + +group "default" { + targets = ["ci", "robot", "desktop", "desktop-nvidia"] +} + +# In Github CI, populated by metadata-action Github action +target "docker-metadata-action" {} + +# +# All images can pull cache from the images published at Github +# or local storage (within the Buildkit image) +# +# ... and push cache to local storage +# +target "ci" { + inherits = ["docker-metadata-action"] + dockerfile = ".docker/Dockerfile" + target = "ci" + context = ".." + args = { + ROS_DISTRO = "${BLUE_ROS_DISTRO}" + } + tags = [ + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-ci" + ] + labels = { + "org.opencontainers.image.source" = "https://github.com/${BLUE_GITHUB_REPO}" + } + cache_from =[ + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-ci", + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-robot", + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-desktop", + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-desktop-nvidia", + "type=local,dest=.docker-cache" + ] + cache_to = [ + "type=local,dest=.docker-cache" + ] + platforms = ["linux/amd64", "linux/arm64"] +} + +target "robot" { + inherits = [ "ci" ] + target = "robot" + tags = [ + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-robot" + ] + cache_to = [ + "type=local,dest=.docker-cache" + ] +} + +target "desktop" { + inherits = [ "ci" ] + target = "desktop" + tags = [ + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-desktop" + ] + cache_to = [ + "type=local,dest=.docker-cache" + ] + # amd64 only builds for desktop and desktop-nvidia + platforms = ["linux/amd64"] +} + +target "desktop-nvidia" { + inherits = [ "desktop" ] + target = "desktop-nvidia" + tags = [ + "ghcr.io/${BLUE_GITHUB_REPO}:${BLUE_ROS_DISTRO}-desktop-nvidia" + ] + cache_to = [ + "type=local,dest=.docker-cache" + ] +} diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 356e4ee2..3c7fe489 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -1,8 +1,9 @@ name: Docker on: - schedule: - - cron: "0 17 * * 6" + # Disable schedule for preliminary testing + # schedule: + # - cron: "0 17 * * 6" push: branches: - main @@ -18,174 +19,102 @@ env: PUSH: ${{ (github.event_name != 'pull_request') && (github.repository == 'Robotic-Decision-Making-Lab/blue') }} jobs: - ci: + docker_build: strategy: fail-fast: false matrix: ROS_DISTRO: [rolling] + stage: ["ci", "robot", "desktop", "desktop-nvidia"] runs-on: ubuntu-latest permissions: packages: write contents: read steps: - - name: Checkout repository + - + name: Checkout repository uses: actions/checkout@v4 - - name: Log into registry - if: env.PUSH == 'true' - uses: docker/login-action@v3.3.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract Docker metadata - if: env.PUSH == 'true' - id: meta - uses: docker/metadata-action@v5.5.1 - with: - images: ghcr.io/${{ github.repository }} - tags: | - type=raw,value=${{ matrix.ROS_DISTRO }}-${{ github.job }} - - - name: Build and push Docker image - uses: docker/build-push-action@v6.7.0 - with: - context: . - file: .docker/Dockerfile - build-args: ROS_DISTRO=${{ matrix.ROS_DISTRO }} - target: ${{ github.job }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - push: ${{ env.PUSH }} - - robot: - strategy: - fail-fast: false - matrix: - ROS_DISTRO: [rolling] - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@v4 + - + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + name: Set up QEMU + uses: docker/setup-qemu-action@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3.2.0 - - - name: Set up Docker Buildx + - + name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log into registry - if: env.PUSH == 'true' - uses: docker/login-action@v3.3.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract Docker metadata - if: env.PUSH == 'true' - id: meta - uses: docker/metadata-action@v5.5.1 - with: - images: ghcr.io/${{ github.repository }} - tags: | - type=raw,value=${{ matrix.ROS_DISTRO }}-${{ github.job }} - - - name: Build and push Docker image - uses: docker/build-push-action@v6.7.0 - with: - context: . - file: .docker/Dockerfile - build-args: ROS_DISTRO=${{ matrix.ROS_DISTRO }} - target: ${{ github.job }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - push: ${{ env.PUSH }} - platforms: linux/amd64 - #platforms: linux/amd64,linux/arm64 - - desktop: - strategy: - fail-fast: false - matrix: - ROS_DISTRO: [rolling] - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Log into registry + - if: env.PUSH == 'true' + name: Log into registry uses: docker/login-action@v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract Docker metadata + - id: lower-repo + name: Repository to lowercase + run: | + echo "repository=${GITHUB_REPOSITORY@L}" >> $GITHUB_OUTPUT + + # tbd: not sure how to update this for buildx + # + # metadata-action can be used with bake: + # https://github.com/docker/metadata-action?tab=readme-ov-file#bake-definition + # + # But not quite sure how to handle multiple targets given we don't iterate + # through the stages at this level (it happens within bake) + # + - + name: Extract Docker metadata if: env.PUSH == 'true' id: meta uses: docker/metadata-action@v5.5.1 with: images: ghcr.io/${{ github.repository }} tags: | - type=raw,value=${{ matrix.ROS_DISTRO }}-${{ github.job }} - - - name: Build and push Docker image - uses: docker/build-push-action@v6.7.0 + type=raw,value=${{ matrix.ROS_DISTRO }}-${{ matrix.stage }} + + - if: github.event_name == 'push' + name: Build and push (non PR) + uses: docker/bake-action@v5.5.0 + env: + BLUE_ROS_DISTRO: ${{ matrix.ROS_DISTRO }} + BLUE_GITHUB_REPO: ${{ steps.lower-repo.outputs.repository }} with: - context: . - file: .docker/Dockerfile - build-args: ROS_DISTRO=${{ matrix.ROS_DISTRO }} - target: ${{ github.job }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + workdir: .docker + files: | + ./docker-bake.hcl + ${{ steps.meta.outputs.bake-file }} + targets: | + ${{ matrix.stage }} push: ${{ env.PUSH }} - - desktop-nvidia: - strategy: - fail-fast: false - matrix: - ROS_DISTRO: [rolling] - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Log into registry - if: env.PUSH == 'true' - uses: docker/login-action@v3.3.0 + set: | + *.cache-from=type=gha,scope=ci + *.cache-from=type=gha,scope=robot + *.cache-from=type=gha,scope=desktop + *.cache-from=type=gha,scope=desktop-nvidia + ${{ matrix.stage }}.cache-to=type=gha,mode=max,scope=${{ matrix.stage }} + + # Pull request builds are not cached; and only built for AMD64 + - if: github.event_name == 'pull_request' + name: Build and push (PR) + uses: docker/bake-action@v5.5.0 + env: + BLUE_ROS_DISTRO: ${{ matrix.ROS_DISTRO }} + BLUE_GITHUB_REPO: ${{ steps.lower-repo.outputs.repository }} with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract Docker metadata - if: env.PUSH == 'true' - id: meta - uses: docker/metadata-action@v5.5.1 - with: - images: ghcr.io/${{ github.repository }} - tags: | - type=raw,value=${{ matrix.ROS_DISTRO }}-${{ github.job }} - - - name: Build and push Docker image - uses: docker/build-push-action@v6.7.0 - with: - context: . - file: .docker/Dockerfile - build-args: ROS_DISTRO=${{ matrix.ROS_DISTRO }} - target: ${{ github.job }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - push: ${{ env.PUSH }} + workdir: .docker + files: | + ./docker-bake.hcl + ${{ steps.meta.outputs.bake-file }} + targets: | + ${{ matrix.stage }} + set: | + *.platform=linux/amd64 + *.cache-from=type=gha,scope=ci + *.cache-from=type=gha,scope=robot + *.cache-from=type=gha,scope=desktop + *.cache-from=type=gha,scope=desktop-nvidia + *.cache-to= diff --git a/.gitignore b/.gitignore index eb28dd58..fce2ec85 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ mav.parm mav.tlog mav.tlog.raw logs/ + +# Allow overrides in docker-bake +.docker/docker-bake.override.hcl