From 7748651f5cb3ee0ccd3d3e6141f315ee5d20454e Mon Sep 17 00:00:00 2001 From: henrygd Date: Mon, 5 Oct 2026 10:53:02 -0400 Subject: [PATCH] ci: build each docker image once and push to both registries Previously the matrix had separate entries for Docker Hub and GHCR, so every image was built twice. Each entry now pushes to both registries from a single build. Docker Hub is skipped when DOCKERHUB_TOKEN is unset (e.g. forks). Also drops the explicit latest tag on the GHCR agent image so latest comes only from latest=auto, and lowers max-parallel to 3. --- .github/workflows/docker-images.yml | 167 +++++++--------------------- 1 file changed, 39 insertions(+), 128 deletions(-) diff --git a/.github/workflows/docker-images.yml b/.github/workflows/docker-images.yml index 2f76718aa..3ced7e448 100644 --- a/.github/workflows/docker-images.yml +++ b/.github/workflows/docker-images.yml @@ -10,42 +10,43 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false - max-parallel: 5 + max-parallel: 3 matrix: include: - # henrygd/beszel - - image: henrygd/beszel + # beszel + - image: beszel dockerfile: ./internal/dockerfile_hub - registry: docker.io - username_secret: DOCKERHUB_USERNAME - password_secret: DOCKERHUB_TOKEN tags: | type=raw,value=edge type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - - # henrygd/beszel-agent:alpine - - image: henrygd/beszel-agent + + # beszel-agent + - image: beszel-agent + dockerfile: ./internal/dockerfile_agent + tags: | + type=raw,value=edge + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} + + # beszel-agent:alpine + - image: beszel-agent dockerfile: ./internal/dockerfile_agent_alpine flavor: latest=false - registry: docker.io - username_secret: DOCKERHUB_USERNAME - password_secret: DOCKERHUB_TOKEN tags: | type=raw,value=alpine type=semver,pattern={{version}}-alpine type=semver,pattern={{major}}.{{minor}}-alpine type=semver,pattern={{major}}-alpine - # henrygd/beszel-agent-nvidia - - image: henrygd/beszel-agent-nvidia + # beszel-agent-nvidia + - image: beszel-agent-nvidia dockerfile: ./internal/dockerfile_agent_nvidia platforms: linux/amd64,linux/arm64 - registry: docker.io - username_secret: DOCKERHUB_USERNAME - password_secret: DOCKERHUB_TOKEN tags: | type=raw,value=edge type=semver,pattern={{version}} @@ -53,122 +54,21 @@ jobs: type=semver,pattern={{major}} type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - # henrygd/beszel-agent-nvidia:slim - - image: henrygd/beszel-agent-nvidia + # beszel-agent-nvidia:slim + - image: beszel-agent-nvidia dockerfile: ./internal/dockerfile_agent_nvidia_slim flavor: latest=false platforms: linux/amd64,linux/arm64 - registry: docker.io - username_secret: DOCKERHUB_USERNAME - password_secret: DOCKERHUB_TOKEN tags: | type=raw,value=slim type=semver,pattern={{version}}-slim type=semver,pattern={{major}}.{{minor}}-slim type=semver,pattern={{major}}-slim - # henrygd/beszel-agent-intel - - image: henrygd/beszel-agent-intel + # beszel-agent-intel + - image: beszel-agent-intel dockerfile: ./internal/dockerfile_agent_intel platforms: linux/amd64 - registry: docker.io - username_secret: DOCKERHUB_USERNAME - password_secret: DOCKERHUB_TOKEN - tags: | - type=raw,value=edge - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - - # ghcr.io/henrygd/beszel - - image: ghcr.io/${{ github.repository }}/beszel - dockerfile: ./internal/dockerfile_hub - registry: ghcr.io - username: ${{ github.actor }} - password_secret: GITHUB_TOKEN - tags: | - type=raw,value=edge - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - - # ghcr.io/henrygd/beszel-agent - - image: ghcr.io/${{ github.repository }}/beszel-agent - dockerfile: ./internal/dockerfile_agent - registry: ghcr.io - username: ${{ github.actor }} - password_secret: GITHUB_TOKEN - tags: | - type=raw,value=edge - type=raw,value=latest - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - - # ghcr.io/henrygd/beszel-agent-nvidia - - image: ghcr.io/${{ github.repository }}/beszel-agent-nvidia - dockerfile: ./internal/dockerfile_agent_nvidia - platforms: linux/amd64,linux/arm64 - registry: ghcr.io - username: ${{ github.actor }} - password_secret: GITHUB_TOKEN - tags: | - type=raw,value=edge - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - - # ghcr.io/henrygd/beszel-agent-nvidia:slim - - image: ghcr.io/${{ github.repository }}/beszel-agent-nvidia - dockerfile: ./internal/dockerfile_agent_nvidia_slim - flavor: latest=false - platforms: linux/amd64,linux/arm64 - registry: ghcr.io - username: ${{ github.actor }} - password_secret: GITHUB_TOKEN - tags: | - type=raw,value=slim - type=semver,pattern={{version}}-slim - type=semver,pattern={{major}}.{{minor}}-slim - type=semver,pattern={{major}}-slim - - # ghcr.io/henrygd/beszel-agent-intel - - image: ghcr.io/${{ github.repository }}/beszel-agent-intel - dockerfile: ./internal/dockerfile_agent_intel - platforms: linux/amd64 - registry: ghcr.io - username: ${{ github.actor }} - password_secret: GITHUB_TOKEN - tags: | - type=raw,value=edge - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value={{sha}},enable=${{ github.ref_type != 'tag' }} - - # ghcr.io/henrygd/beszel-agent:alpine - - image: ghcr.io/${{ github.repository }}/beszel-agent - dockerfile: ./internal/dockerfile_agent_alpine - flavor: latest=false - registry: ghcr.io - username: ${{ github.actor }} - password_secret: GITHUB_TOKEN - tags: | - type=raw,value=alpine - type=semver,pattern={{version}}-alpine - type=semver,pattern={{major}}.{{minor}}-alpine - type=semver,pattern={{major}}-alpine - - # henrygd/beszel-agent - - image: henrygd/beszel-agent - dockerfile: ./internal/dockerfile_agent - registry: docker.io - username_secret: DOCKERHUB_USERNAME - password_secret: DOCKERHUB_TOKEN tags: | type=raw,value=edge type=semver,pattern={{version}} @@ -203,7 +103,11 @@ jobs: id: metadata uses: docker/metadata-action@v6 with: - images: ${{ matrix.image }} + # Each image is built once and pushed to both registries. + # Docker Hub is skipped when its token is missing (e.g. forks). + images: | + name=henrygd/${{ matrix.image }},enable=${{ secrets.DOCKERHUB_TOKEN != '' }} + name=ghcr.io/${{ github.repository }}/${{ matrix.image }} # Variant images must not overwrite the standard image's latest tag. flavor: ${{ matrix.flavor || 'latest=auto' }} tags: ${{ matrix.tags }} @@ -211,13 +115,20 @@ jobs: # https://github.com/docker/login-action - name: Login to Docker Hub env: - password_secret_exists: ${{ secrets[matrix.password_secret] != '' && 'true' || 'false' }} + password_secret_exists: ${{ secrets.DOCKERHUB_TOKEN != '' && 'true' || 'false' }} if: github.event_name != 'pull_request' && env.password_secret_exists == 'true' uses: docker/login-action@v4 with: - username: ${{ matrix.username || secrets[matrix.username_secret] }} - password: ${{ secrets[matrix.password_secret] }} - registry: ${{ matrix.registry }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action @@ -227,7 +138,7 @@ jobs: context: ./ file: ${{ matrix.dockerfile }} platforms: ${{ matrix.platforms || 'linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7' }} - push: ${{ github.ref_type == 'tag' && secrets[matrix.password_secret] != '' }} + push: ${{ github.ref_type == 'tag' }} provenance: mode=max sbom: true tags: ${{ steps.metadata.outputs.tags }}