diff --git a/.github/workflows/test-and-deploy.yml b/.github/workflows/test-and-deploy.yml index b585c4c5d0..00773a72e2 100644 --- a/.github/workflows/test-and-deploy.yml +++ b/.github/workflows/test-and-deploy.yml @@ -106,20 +106,10 @@ jobs: VERSION=${GITHUB_REF#refs/tags/} fi - TAGS="--tag ${DOCKER_IMAGE}:${VERSION}" - if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - TAGS="$TAGS --tag ${DOCKER_IMAGE}:latest" - fi - echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT echo "version=${VERSION}" >> $GITHUB_OUTPUT - echo "buildx_args=\ - --build-arg GIT_DESCRIBE_TAGS=$(git describe --tags --long --always) \ - --build-arg VITE_APP_GIT_DESCRIBE=$(git describe --long --always --dirty --all) \ - --cache-from 'type=local,src=/tmp/.buildx-cache' \ - --cache-to 'type=local,dest=/tmp/.buildx-cache' \ - ${TAGS} \ - --file ${{ matrix.docker }}/Dockerfile ./${{ matrix.docker }}" >> $GITHUB_OUTPUT + echo "describe_tags=$(git describe --tags --long --always)" >> "$GITHUB_OUTPUT" + echo "describe=$(git describe --long --always --dirty --all)" >> "$GITHUB_OUTPUT" - name: Set up QEMU uses: docker/setup-qemu-action@v4 @@ -141,27 +131,30 @@ jobs: ${{ runner.os }}-buildx-${{ matrix.docker }}-${{ hashFiles(format('{0}/Dockerfile', matrix.docker)) }} ${{ runner.os }}-buildx-${{ matrix.docker }} - - name: Docker Buildx (build) - run: | - # Pull latest version of image to help with build speed - for platform in $(echo ${{ matrix.platforms }} | tr ',' '\n'); do - docker pull --platform ${platform} ${DOCKER_USERNAME:-bluerobotics}/${{ matrix.project }}-${{ matrix.docker }}:master || true - done - docker buildx build \ - --output "type=image,push=false" \ - --platform ${{ matrix.platforms }} \ - ${{ steps.prepare.outputs.buildx_args }} - - - name: Check core size - if: ${{ matrix.docker == 'core' }} - run: | - # Check if the image size is lower than our limit - docker image list - IMAGE_ID=$(docker images -q ${DOCKER_USERNAME:-bluerobotics}/${{ matrix.project }} | head -n 1) - LIMIT_SIZE_MB=700 - IMAGE_SIZE_MB=$(( $(docker inspect $IMAGE_ID --format {{.Size}})/(2**20) )) - echo "Core size is: $IMAGE_SIZE_MB MB" - ((IMAGE_SIZE_MB < LIMIT_SIZE_MB)) + - name: Docker metadata + id: meta + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0 + with: + images: ${{ env.DOCKER_USERNAME || 'bluerobotics' }}/${{ matrix.project }}-${{ matrix.docker }} + tags: | # If version is semver push it as latest as well + type=ref,event=branch + type=ref,event=tag + type=semver,pattern={{version}} + type=semver,pattern={{version}},value=latest + + - name: Build Docker images + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a #v7.3.0 + with: + context: ./${{ matrix.docker }} + file: ./${{ matrix.docker }}/Dockerfile + platforms: ${{ matrix.platforms }} + push: false + tags: ${{ steps.meta.outputs.tags }} + build-args: | + GIT_DESCRIBE_TAGS=${{ steps.prepare.outputs.describe_tags }} + VITE_APP_GIT_DESCRIBE=${{ steps.prepare.outputs.describe }} + cache-from: type=local,src=/tmp/.buildx-cache # Might worth investigating type=gha,scope=${{ matrix.docker }} + cache-to: type=local,dest=/tmp/.buildx-cache # Might worth investigating type=gha,mode=max,scope=${{ matrix.docker }} - name: Login to DockerHub if: success() && github.event_name != 'pull_request' @@ -170,13 +163,21 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Docker Buildx (push) - if: success() && github.event_name != 'pull_request' - run: | - docker buildx build \ - --output "type=image,push=true" \ - --platform ${{ matrix.platforms }} \ - ${{ steps.prepare.outputs.buildx_args }} + - name: Build and push + if: success() + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a #v7.3.0 + with: + context: ./${{ matrix.docker }} + file: ./${{ matrix.docker }}/Dockerfile + platforms: ${{ matrix.platforms }} + push: ${{ github.event_name != 'pull_request' }} + sbom: true + provenance: mode=max,version=v1 # This is the default value for public repositories + build-args: | + GIT_DESCRIBE_TAGS=${{ steps.prepare.outputs.describe_tags }} + VITE_APP_GIT_DESCRIBE=${{ steps.prepare.outputs.describe }} + cache-from: type=local,src=/tmp/.buildx-cache # Might worth investigating type=gha,scope=${{ matrix.docker }} + cache-to: type=local,dest=/tmp/.buildx-cache # Might worth investigating type=gha,mode=max,scope=${{ matrix.docker }} - name: Inspect image if: always() && github.event_name != 'pull_request' @@ -184,66 +185,52 @@ jobs: docker buildx imagetools \ inspect ${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }} - - name: Create image artifact + - name: Create Standalone Release Tarballs if: success() && matrix.docker == 'core' + env: + DOCKER_TAGS: ${{ steps.meta.outputs.json }} run: | - DOCKER_IMAGE=${DOCKER_USERNAME:-bluerobotics}/${{ matrix.project }}-${{ matrix.docker }} - GIT_HASH_SHORT=$(git rev-parse --short "$GITHUB_SHA") - docker buildx build \ - ${{ steps.prepare.outputs.buildx_args }} \ - --platform "linux/arm64/v8" \ - --tag ${DOCKER_IMAGE}:${GIT_HASH_SHORT} \ - --output "type=docker,dest=BlueOs-core-docker-image-${GIT_HASH_SHORT}-arm64-v8.tar" \ - - - name: Upload artifact arm64-v8 - uses: actions/upload-artifact@v7 - if: success() && matrix.docker == 'core' - with: - name: BlueOS-core-docker-image-arm64-v8 - path: '*arm64-v8.tar' - - - name: Create image artifact - if: success() && matrix.docker == 'core' - run: | - DOCKER_IMAGE=${DOCKER_USERNAME:-bluerobotics}/${{ matrix.project }}-${{ matrix.docker }} - GIT_HASH_SHORT=$(git rev-parse --short "$GITHUB_SHA") - docker buildx build \ - ${{ steps.prepare.outputs.buildx_args }} \ - --platform "linux/arm/v7" \ - --tag ${DOCKER_IMAGE}:${GIT_HASH_SHORT} \ - --output "type=docker,dest=BlueOs-core-docker-image-${GIT_HASH_SHORT}-arm-v7.tar" \ - - - name: Upload artifact arm-v7 - uses: actions/upload-artifact@v7 - if: success() && matrix.docker == 'core' - with: - name: BlueOS-core-docker-image-arm-v7 - path: '*arm-v7.tar' + GIT_HASH_SHORT="$(git rev-parse --short "$GITHUB_SHA")" + echo "GIT_HASH_SHORT=${GIT_HASH_SHORT}" >> "$GITHUB_ENV" + + TAGS=$(echo "$DOCKER_TAGS" | jq -r '.tags[] | "--tag \(.)"') + + echo "Generated all tags via jq:" + echo "$TAGS" + + for plat in amd64 arm64/v8 arm/v7; do + FILE_ARCH=$(echo $plat | tr '/' '-') + echo "Packaging standalone image & metadata for $plat in background..." + + # 1. Build and export the core container tarball + docker buildx build \ + --platform "linux/$plat" \ + --build-arg GIT_DESCRIBE_TAGS=${{ steps.prepare.outputs.describe_tags }} \ + --build-arg VITE_APP_GIT_DESCRIBE=${{ steps.prepare.outputs.describe }} \ + ${TAGS} \ + --file ./${{ matrix.docker }}/Dockerfile \ + --cache-from 'type=local,src=/tmp/.buildx-cache' \ + --cache-to 'type=local,dest=/tmp/.buildx-cache' \ + --output "type=docker,dest=BlueOs-core-docker-image-${GIT_HASH_SHORT}-${FILE_ARCH}.tar" \ + ./${{ matrix.docker }} & + done + wait - - name: Create image artifact - if: success() && matrix.docker == 'core' - run: | - DOCKER_IMAGE=${DOCKER_USERNAME:-bluerobotics}/${{ matrix.project }}-${{ matrix.docker }} - GIT_HASH_SHORT=$(git rev-parse --short "$GITHUB_SHA") - docker buildx build \ - ${{ steps.prepare.outputs.buildx_args }} \ - --platform "linux/amd64" \ - --tag ${DOCKER_IMAGE}:${GIT_HASH_SHORT} \ - --output "type=docker,dest=BlueOs-core-docker-image-${GIT_HASH_SHORT}-amd64.tar" \ - - - name: Upload artifact amd64 - uses: actions/upload-artifact@v7 + - name: Upload artifact for all Docker images from previous step if: success() && matrix.docker == 'core' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 with: - name: BlueOS-core-docker-image-amd64 - path: '*amd64.tar' + name: BlueOS-core-docker-images-${{ env.GIT_HASH_SHORT }} + path: BlueOs-core-docker-image-*.tar + if-no-files-found: error + retention-days: 7 - name: Upload docker image for release uses: svenstaro/upload-release-action@v2 if: startsWith(github.ref, 'refs/tags/') && success() && matrix.docker == 'core' with: repo_token: ${{ secrets.GITHUB_TOKEN }} - file: '*.tar' + file: 'BlueOs-core-docker-image-*.tar' tag: ${{ github.ref }} overwrite: true prerelease: true