diff --git a/.github/workflows/container_latest.yml b/.github/workflows/container_latest.yml index 771e92545..2e476ebbd 100644 --- a/.github/workflows/container_latest.yml +++ b/.github/workflows/container_latest.yml @@ -449,7 +449,7 @@ jobs: variant: ${{ fromJSON(needs.setup.outputs.variants) }} steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.source_ref || github.ref }} @@ -464,19 +464,19 @@ jobs: - name: Docker meta id: docker_meta - uses: docker/metadata-action@v6 + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6 with: images: | chrislusf/seaweedfs ghcr.io/chrislusf/seaweedfs tags: type=raw,value=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.image_tag || 'latest' }},suffix=${{ steps.config.outputs.tag_suffix }} - name: Login to Docker Hub - uses: docker/login-action@v4.6.0 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GHCR - uses: docker/login-action@v4.6.0 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io username: ${{ secrets.GHCR_USERNAME }} @@ -485,10 +485,13 @@ jobs: run: | # Install crane for efficient multi-arch image copying cd $(mktemp -d) - curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz" | tar xz + curl -sLO https://github.com/google/go-containerregistry/releases/download/v0.22.0/go-containerregistry_Linux_x86_64.tar.gz + echo "edb74d53fad9a596860f59d1c5d04a43dfb5f441dc71f57060dd0bf39483c833 go-containerregistry_Linux_x86_64.tar.gz" | sha256sum -c - + tar xzf go-containerregistry_Linux_x86_64.tar.gz crane sudo mv crane /usr/local/bin/ crane version - name: Create and push manifest + id: manifest env: BASE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.image_tag || 'latest' }} run: | @@ -501,6 +504,9 @@ jobs: ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX}-arm64 \ ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX}-arm \ ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX}-386 + # The copy and the signature below use this digest, not whatever the tag points at by then. + DIGEST=$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX}) + echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT" # Copy the complete multi-arch image from GHCR to Docker Hub # This only requires one pull from GHCR (no rate limit) and one push to Docker Hub @@ -536,10 +542,10 @@ jobs: # Use crane or skopeo to copy, fallback to docker if not available if command -v crane &> /dev/null; then echo "Using crane to copy..." - retry_with_backoff crane copy ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX} chrislusf/seaweedfs:${BASE_TAG}${SUFFIX} + retry_with_backoff crane copy ghcr.io/chrislusf/seaweedfs@${DIGEST} chrislusf/seaweedfs:${BASE_TAG}${SUFFIX} elif command -v skopeo &> /dev/null; then echo "Using skopeo to copy..." - retry_with_backoff skopeo copy --all docker://ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX} docker://chrislusf/seaweedfs:${BASE_TAG}${SUFFIX} + retry_with_backoff skopeo copy --all docker://ghcr.io/chrislusf/seaweedfs@${DIGEST} docker://chrislusf/seaweedfs:${BASE_TAG}${SUFFIX} else echo "Using docker buildx imagetools (pulling 4 images from Docker Hub)..." # Fallback: create manifest directly on Docker Hub (pulls from Docker Hub - rate limited) @@ -550,16 +556,9 @@ jobs: ghcr.io/chrislusf/seaweedfs:${BASE_TAG}${SUFFIX}-386 fi - - name: Resolve the published digests - id: digests - env: - BASE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.image_tag || 'latest' }} - SUFFIX: ${{ steps.config.outputs.tag_suffix }} - run: | - tag="${BASE_TAG}${SUFFIX}" - echo "images=ghcr.io/chrislusf/seaweedfs@$(crane digest "ghcr.io/chrislusf/seaweedfs:${tag}") chrislusf/seaweedfs@$(crane digest "chrislusf/seaweedfs:${tag}")" >> "$GITHUB_OUTPUT" - - name: Sign uses: ./.github/actions/sign-image with: - images: ${{ steps.digests.outputs.images }} + images: >- + ghcr.io/chrislusf/seaweedfs@${{ steps.manifest.outputs.digest }} + chrislusf/seaweedfs@${{ steps.manifest.outputs.digest }} diff --git a/.github/workflows/container_release_unified.yml b/.github/workflows/container_release_unified.yml index 752135912..64831a4e0 100644 --- a/.github/workflows/container_release_unified.yml +++ b/.github/workflows/container_release_unified.yml @@ -318,10 +318,11 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: sparse-checkout: .github/actions + persist-credentials: false - name: Download digests if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: pattern: digest-${{ matrix.variant }}-* merge-multiple: true @@ -329,11 +330,11 @@ jobs: - name: Set up Docker Buildx if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4 - name: Login to GHCR if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - uses: docker/login-action@v4.6.0 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io username: ${{ secrets.GHCR_USERNAME }} @@ -341,16 +342,19 @@ jobs: - name: Create multi-arch tag on GHCR if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant + id: manifest working-directory: /tmp/digests run: | docker buildx imagetools create \ -t ${{ env.IMAGE }}:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }} \ $(printf '${{ env.IMAGE }}@sha256:%s ' *) docker buildx imagetools inspect ${{ env.IMAGE }}:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }} + # The copy and the signature below use this digest, not whatever the tag points at by then. + echo "digest=$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' ${{ env.IMAGE }}:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }})" >> "$GITHUB_OUTPUT" - name: Login to Docker Hub if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - uses: docker/login-action@v4.6.0 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -359,7 +363,9 @@ jobs: if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant run: | cd $(mktemp -d) - curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz" | tar xz + curl -sLO https://github.com/google/go-containerregistry/releases/download/v0.22.0/go-containerregistry_Linux_x86_64.tar.gz + echo "edb74d53fad9a596860f59d1c5d04a43dfb5f441dc71f57060dd0bf39483c833 go-containerregistry_Linux_x86_64.tar.gz" | sha256sum -c - + tar xzf go-containerregistry_Linux_x86_64.tar.gz crane sudo mv crane /usr/local/bin/ crane version @@ -390,22 +396,17 @@ jobs: echo "Copying ${{ matrix.variant }} from GHCR to Docker Hub..." retry_with_backoff crane copy \ - ${{ env.IMAGE }}:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }} \ + ${{ env.IMAGE }}@${{ steps.manifest.outputs.digest }} \ chrislusf/seaweedfs:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }} echo "Copied ${{ matrix.variant }} to Docker Hub" - - name: Resolve the published digests - if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - id: digests - run: | - tag="${RELEASE_TAG}${{ matrix.tag_suffix }}" - echo "images=${IMAGE}@$(crane digest "${IMAGE}:${tag}") chrislusf/seaweedfs@$(crane digest "chrislusf/seaweedfs:${tag}")" >> "$GITHUB_OUTPUT" - - name: Sign ${{ matrix.variant }} if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant uses: ./.github/actions/sign-image with: - images: ${{ steps.digests.outputs.images }} + images: >- + ${{ env.IMAGE }}@${{ steps.manifest.outputs.digest }} + chrislusf/seaweedfs@${{ steps.manifest.outputs.digest }} # Report-only trivy scan: uploads fixable HIGH/CRITICAL findings to GitHub # Security for visibility, but never blocks the release. Releases (including @@ -492,7 +493,9 @@ jobs: - 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 + curl -sLO https://github.com/google/go-containerregistry/releases/download/v0.22.0/go-containerregistry_Linux_x86_64.tar.gz + echo "edb74d53fad9a596860f59d1c5d04a43dfb5f441dc71f57060dd0bf39483c833 go-containerregistry_Linux_x86_64.tar.gz" | sha256sum -c - + tar xzf go-containerregistry_Linux_x86_64.tar.gz crane sudo mv crane /usr/local/bin/ crane version