aboutsummaryrefslogtreecommitdiff
path: root/.github/workflows/container_release_unified.yml
blob: 3d3a24d6c88e355bd39f24d8a3d6511db0ee2165 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
name: "docker: build all release containers (unified)"

on:
  push:
    tags:
      - '*'
  workflow_dispatch: {}

permissions:
  contents: read

# Limit concurrent builds to avoid rate limits
concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      # Build sequentially to avoid rate limits
      max-parallel: 2
      matrix:
        include:
          # Normal volume - multi-arch
          - variant: normal
            platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386
            dockerfile: ./docker/Dockerfile.go_build
            build_args: ""
            tag_suffix: ""
            
          # Large disk - multi-arch  
          - variant: large_disk
            platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386
            dockerfile: ./docker/Dockerfile.go_build
            build_args: TAGS=5BytesOffset
            tag_suffix: _large_disk
            
          # Full tags - amd64 only
          - variant: full
            platforms: linux/amd64
            dockerfile: ./docker/Dockerfile.go_build
            build_args: TAGS=elastic,gocdk,rclone,sqlite,tarantool,tikv,ydb
            tag_suffix: _full
            
          # Large disk + full tags - amd64 only
          - variant: large_disk_full
            platforms: linux/amd64
            dockerfile: ./docker/Dockerfile.go_build
            build_args: TAGS=5BytesOffset,elastic,gocdk,rclone,sqlite,tarantool,tikv,ydb
            tag_suffix: _large_disk_full
            
          # RocksDB large disk - amd64 only
          - variant: rocksdb
            platforms: linux/amd64
            dockerfile: ./docker/Dockerfile.rocksdb_large
            build_args: ""
            tag_suffix: _large_disk_rocksdb
            
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Free Disk Space
        run: |
          echo "Available disk space before cleanup:"
          df -h
          sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
          sudo apt-get clean
          sudo rm -rf /var/lib/apt/lists/*
          sudo docker system prune -af --volumes
          [ -d ~/.cache/go-build ] && rm -rf ~/.cache/go-build || true
          [ -d /go/pkg ] && rm -rf /go/pkg || true
          echo "Available disk space after cleanup:"
          df -h
          
      - name: Docker meta
        id: docker_meta
        uses: docker/metadata-action@v5
        with:
          images: |
            chrislusf/seaweedfs
            ghcr.io/chrislusf/seaweedfs
          tags: type=ref,event=tag,suffix=${{ matrix.tag_suffix }}
          flavor: latest=false
          labels: |
            org.opencontainers.image.title=seaweedfs
            org.opencontainers.image.description=SeaweedFS is a distributed storage system for blobs, objects, files, and data lake, to store and serve billions of files fast!
            org.opencontainers.image.vendor=Chris Lu
            
      - name: Set up QEMU
        if: contains(matrix.platforms, 'arm')
        uses: docker/setup-qemu-action@v3
        
      - name: Create BuildKit config
        run: |
          cat > /tmp/buildkitd.toml <<EOF
          [registry."docker.io"]
            mirrors = ["https://mirror.gcr.io"]
          EOF
          
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          buildkitd-config: /tmp/buildkitd.toml
          
      - name: Login to Docker Hub
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
          
      - name: Login to GHCR
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ secrets.GHCR_USERNAME }}
          password: ${{ secrets.GHCR_TOKEN }}
          
      - name: Build and push ${{ matrix.variant }}
        uses: docker/build-push-action@v5
        env:
          DOCKER_BUILDKIT: 1
        with:
          context: ./docker
          push: ${{ github.event_name != 'pull_request' }}
          file: ${{ matrix.dockerfile }}
          platforms: ${{ matrix.platforms }}
          # Push to GHCR to avoid Docker Hub rate limits on pulls
          tags: |
            ghcr.io/chrislusf/seaweedfs:${{ github.ref_name }}${{ matrix.tag_suffix }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha,scope=${{ matrix.variant }}
          cache-to: type=gha,mode=max,scope=${{ matrix.variant }}
          build-args: |
            ${{ matrix.build_args }}
            BUILDKIT_INLINE_CACHE=1
            BRANCH=${{ github.sha }}
            
      - name: Clean up build artifacts
        if: always()
        run: |
          sudo docker system prune -f
          sudo rm -rf /tmp/go-build*

  copy-to-dockerhub:
    runs-on: ubuntu-latest
    needs: [build]
    if: github.event_name != 'pull_request'
    strategy:
      matrix:
        variant: [normal, large_disk, full, large_disk_full, rocksdb]
        include:
          - variant: normal
            tag_suffix: ""
          - variant: large_disk
            tag_suffix: _large_disk
          - variant: full
            tag_suffix: _full
          - variant: large_disk_full
            tag_suffix: _large_disk_full
          - variant: rocksdb
            tag_suffix: _large_disk_rocksdb
            
    steps:
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
          
      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ secrets.GHCR_USERNAME }}
          password: ${{ secrets.GHCR_TOKEN }}
          
      - name: Install crane
        run: |
          cd $(mktemp -d)
          curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz" | tar xz
          sudo mv crane /usr/local/bin/
          crane version
          
      - name: Copy ${{ matrix.variant }} from GHCR to Docker Hub
        run: |
          # Function to retry with exponential backoff
          retry_with_backoff() {
            local max_attempts=5
            local timeout=1
            local attempt=1
            local exit_code=0
            
            while [ $attempt -le $max_attempts ]; do
              if "$@"; then
                return 0
              else
                exit_code=$?
              fi
              
              if [ $attempt -lt $max_attempts ]; then
                echo "Attempt $attempt failed. Retrying in ${timeout}s..." >&2
                sleep $timeout
                timeout=$((timeout * 2))
              fi
              
              attempt=$((attempt + 1))
            done
            
            echo "Command failed after $max_attempts attempts" >&2
            return $exit_code
          }
          
          # Copy multi-arch image from GHCR to Docker Hub with retry
          # This is much more efficient than pulling/pushing individual arch images
          echo "Copying ${{ matrix.variant }} from GHCR to Docker Hub..."
          retry_with_backoff crane copy \
            ghcr.io/chrislusf/seaweedfs:${{ github.ref_name }}${{ matrix.tag_suffix }} \
            chrislusf/seaweedfs:${{ github.ref_name }}${{ matrix.tag_suffix }}
          
          echo "✓ Successfully copied ${{ matrix.variant }} to Docker Hub"