# Copyright 2024 RustFS Team # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. name: Docker Images on: push: tags: ["*"] branches: [main] paths-ignore: - "**.md" - "**.txt" - ".github/**" - "docs/**" - "deploy/**" - "scripts/dev_*.sh" - "LICENSE*" - "README*" - "**/*.png" - "**/*.jpg" - "**/*.svg" - ".gitignore" - ".dockerignore" pull_request: branches: [main] paths-ignore: - "**.md" - "**.txt" - ".github/**" - "docs/**" - "deploy/**" - "scripts/dev_*.sh" - "LICENSE*" - "README*" - "**/*.png" - "**/*.jpg" - "**/*.svg" - ".gitignore" - ".dockerignore" workflow_dispatch: inputs: push_images: description: "Push images to registries" required: false default: true type: boolean env: CARGO_TERM_COLOR: always REGISTRY_DOCKERHUB: rustfs/rustfs REGISTRY_GHCR: ghcr.io/${{ github.repository }} jobs: # Check if we should build build-check: name: Build Check runs-on: ubuntu-latest outputs: should_build: ${{ steps.check.outputs.should_build }} should_push: ${{ steps.check.outputs.should_push }} steps: - name: Check build conditions id: check run: | should_build=false should_push=false # Always build on workflow_dispatch or when changes detected if [[ "${{ github.event_name }}" == "workflow_dispatch" ]] || \ [[ "${{ github.event_name }}" == "push" ]] || \ [[ "${{ github.event_name }}" == "pull_request" ]]; then should_build=true fi # Push only on main branch, tags, or manual trigger if [[ "${{ github.ref }}" == "refs/heads/main" ]] || \ [[ "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]] || \ [[ "${{ github.event.inputs.push_images }}" == "true" ]]; then should_push=true fi echo "should_build=$should_build" >> $GITHUB_OUTPUT echo "should_push=$should_push" >> $GITHUB_OUTPUT echo "Build: $should_build, Push: $should_push" # Build multi-arch Docker images build-docker: name: Build Docker Images needs: build-check if: needs.build-check.outputs.should_build == 'true' runs-on: ubuntu-latest timeout-minutes: 60 strategy: fail-fast: false matrix: variant: - name: production dockerfile: Dockerfile platforms: linux/amd64,linux/arm64 - name: ubuntu dockerfile: .docker/Dockerfile.ubuntu22.04 platforms: linux/amd64,linux/arm64 - name: alpine dockerfile: .docker/Dockerfile.alpine platforms: linux/amd64,linux/arm64 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Login to Docker Hub if: needs.build-check.outputs.should_push == 'true' && secrets.DOCKERHUB_USERNAME != '' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry if: needs.build-check.outputs.should_push == 'true' uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: | ${{ env.REGISTRY_DOCKERHUB }} ${{ env.REGISTRY_GHCR }} tags: | type=ref,event=branch,suffix=-${{ matrix.variant.name }} type=ref,event=pr,suffix=-${{ matrix.variant.name }} type=semver,pattern={{version}},suffix=-${{ matrix.variant.name }} type=semver,pattern={{major}}.{{minor}},suffix=-${{ matrix.variant.name }} type=raw,value=latest,suffix=-${{ matrix.variant.name }},enable={{is_default_branch}} flavor: | latest=false - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . file: ${{ matrix.variant.dockerfile }} platforms: ${{ matrix.variant.platforms }} push: ${{ needs.build-check.outputs.should_push == 'true' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha,scope=docker-${{ matrix.variant.name }} cache-to: type=gha,mode=max,scope=docker-${{ matrix.variant.name }} build-args: | BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} # Create manifest for main production image create-manifest: name: Create Manifest needs: [build-check, build-docker] if: needs.build-check.outputs.should_push == 'true' && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - name: Login to Docker Hub if: secrets.DOCKERHUB_USERNAME != '' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Create and push manifest run: | VERSION=${GITHUB_REF#refs/tags/} # Create main image tag (without variant suffix) if [[ -n "${{ secrets.DOCKERHUB_USERNAME }}" ]]; then docker buildx imagetools create \ -t ${{ env.REGISTRY_DOCKERHUB }}:${VERSION} \ -t ${{ env.REGISTRY_DOCKERHUB }}:latest \ ${{ env.REGISTRY_DOCKERHUB }}:${VERSION}-production fi docker buildx imagetools create \ -t ${{ env.REGISTRY_GHCR }}:${VERSION} \ -t ${{ env.REGISTRY_GHCR }}:latest \ ${{ env.REGISTRY_GHCR }}:${VERSION}-production