name: Release Docker on: push: tags: - "v[0-9]*" workflow_dispatch: inputs: tag: description: "Image tag (e.g. 1.0.0, no v prefix). Defaults to latest commit SHA." required: false jobs: docker: runs-on: docker-builder steps: - uses: actions/checkout@v4 - name: Resolve image tag id: meta run: | SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT" if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then TAG="${{ github.event.inputs.tag }}" if [ -z "$TAG" ]; then TAG="${{ github.sha }}" fi else # Docker convention: git tag v1.2.3 -> image tag 1.2.3 TAG="${{ github.ref_name }}" TAG="${TAG#v}" fi echo "tag=$TAG" >> "$GITHUB_OUTPUT" TAGS="lerkolabs/uptop:${TAG}" TAGS="${TAGS},lerkolabs/uptop:sha-${SHORT_SHA}" # :latest only for real releases — rc rehearsal tags must not move it if [ "${{ github.ref_type }}" = "tag" ]; then case "$TAG" in *-*) ;; *) TAGS="${TAGS},lerkolabs/uptop:latest" ;; esac fi echo "tags=$TAGS" >> "$GITHUB_OUTPUT" - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} # Scan must gate the push: build amd64 locally, scan it, and only then run # the multi-arch push (amd64 layers come from the builder cache, so the # second build only adds the arm64 work). - name: Build for scan (amd64, local) uses: docker/build-push-action@v5 with: context: . load: true platforms: linux/amd64 tags: uptop-scan:${{ steps.meta.outputs.tag }} build-args: | VERSION=${{ steps.meta.outputs.tag }} COMMIT=${{ github.sha }} BUILD_DATE=${{ github.event.head_commit.timestamp }} - name: Scan image for CVEs run: | curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.114.0 grype uptop-scan:${{ steps.meta.outputs.tag }} --fail-on critical --output table - name: Build and push uses: docker/build-push-action@v5 with: context: . push: true platforms: linux/amd64,linux/arm64 sbom: true provenance: mode=max tags: ${{ steps.meta.outputs.tags }} build-args: | VERSION=${{ steps.meta.outputs.tag }} COMMIT=${{ github.sha }} BUILD_DATE=${{ github.event.head_commit.timestamp }} - name: Update Docker Hub description uses: peter-evans/dockerhub-description@v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} repository: lerkolabs/uptop - name: Cleanup Docker artifacts if: always() run: | # the scan image is tagged, so image prune won't catch it docker image rm "uptop-scan:${{ steps.meta.outputs.tag }}" 2>/dev/null || true docker image prune -f docker builder prune -f --keep-storage=2GB