Skip to content

Build and push service images to multiple registries #35

Build and push service images to multiple registries

Build and push service images to multiple registries #35

name: Build and push service images to multiple registries
on:
push:
tags:
- 'v*'
- 'tgo-*-v*'
workflow_dispatch:
inputs:
services:
description: 'Services to build (comma-separated, or leave empty for all). Example: tgo-api,tgo-web'
required: false
default: ''
permissions:
contents: read
packages: write
jobs:
discover-services:
name: Discover service directories under repos/
runs-on: ubuntu-latest
outputs:
services: ${{ steps.discover.outputs.services }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Discover services
id: discover
run: |
set -euo pipefail
echo "=== Service Discovery ==="
echo "Trigger: ${{ github.event_name }}"
echo "Ref: ${{ github.ref_name }}"
echo ""
# Priority 1: workflow_dispatch with specified services
if [ -n "${{ github.event.inputs.services }}" ]; then
services_input="${{ github.event.inputs.services }}"
echo "✓ Using manually specified services: $services_input"
json="["
first=1
for s in $(echo "$services_input" | tr ',' '\n'); do
s=$(echo "$s" | xargs) # Remove leading/trailing whitespace
if [ -z "$s" ]; then continue; fi
if [ $first -eq 0 ]; then
json="$json,"
fi
json="$json\"$s\""
first=0
done
json="$json]"
echo "Services to build: $json"
echo "services=$json" >> "$GITHUB_OUTPUT"
exit 0
fi
# Priority 2: Tag prefix (e.g., tgo-api-v1.0.0)
tag="${{ github.ref_name }}"
if [[ $tag =~ ^(tgo-[a-z-]+)-v ]]; then
service="${BASH_REMATCH[1]}"
echo "✓ Tag prefix detected: $tag"
echo "✓ Building specific service: $service"
echo "services=[\"$service\"]" >> "$GITHUB_OUTPUT"
exit 0
fi
# Priority 3: Auto-discover all services
echo "✓ Auto-discovering all services..."
if [ ! -d "repos" ]; then
echo "repos directory not found" >&2
exit 1
fi
services=()
for dir in repos/*/; do
[ -d "$dir" ] || continue
name="${dir#repos/}"
name="${name%/}"
# Ensure the service has a Dockerfile
if [ -f "repos/$name/Dockerfile" ]; then
services+=("$name")
fi
done
if [ "${#services[@]}" -eq 0 ]; then
echo "No service directories with Dockerfile found under repos/" >&2
exit 1
fi
json="["
first=1
for s in "${services[@]}"; do
if [ $first -eq 0 ]; then
json="$json,"
fi
json="$json\"$s\""
first=0
done
json="$json]"
echo "Discovered services: $json"
echo "services=$json" >> "$GITHUB_OUTPUT"
build-and-push:
name: Build and push Docker images
needs: discover-services
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service: ${{ fromJson(needs.discover-services.outputs.services) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Display build information
run: |
echo "=== Build Information ==="
echo "Service: ${{ matrix.service }}"
echo "Tag/Version: ${{ github.ref_name }}"
echo "Commit SHA: ${{ github.sha }}"
echo "Repository: ${{ github.repository }}"
echo "Trigger: ${{ github.event_name }}"
echo ""
- name: Set build metadata
run: |
echo "BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: Free up disk space
if: matrix.service == 'tgo-rag'
run: |
echo "Disk space before cleanup:"
df -h
# Remove unnecessary pre-installed software
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo rm -rf /usr/local/share/boost
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
# Clean up apt cache
sudo apt-get clean
sudo apt-get autoremove -y
sudo apt-get autoclean -y
# Clean up Docker system
docker system prune -af --volumes
echo "Disk space after cleanup:"
df -h
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to Alibaba Cloud Container Registry
uses: docker/login-action@v3
with:
registry: registry.cn-shanghai.aliyuncs.com
username: ${{ secrets.ALIYUN_REGISTRY_USERNAME }}
password: ${{ secrets.ALIYUN_REGISTRY_PASSWORD }}
- name: Build and push image for ${{ matrix.service }}
uses: docker/build-push-action@v6
with:
context: ./repos/${{ matrix.service }}
file: ./repos/${{ matrix.service }}/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.service }}:${{ github.ref_name }}
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.service }}:latest
tgoai/${{ matrix.service }}:${{ github.ref_name }}
tgoai/${{ matrix.service }}:latest
registry.cn-shanghai.aliyuncs.com/tgoai/${{ matrix.service }}:${{ github.ref_name }}
registry.cn-shanghai.aliyuncs.com/tgoai/${{ matrix.service }}:latest
labels: |
org.opencontainers.image.source=${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.version=${{ github.ref_name }}
org.opencontainers.image.title=${{ matrix.service }}
build-args: |
SERVICE_NAME=${{ matrix.service }}
IMAGE_TAG=${{ github.ref_name }}
GIT_SHA=${{ github.sha }}
APP_VERSION=${{ github.ref_name }}
GIT_COMMIT=${{ github.sha }}
BUILD_TIME=${{ env.BUILD_TIME }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Verify multi-architecture manifest
run: |
echo "Verifying multi-architecture manifest for ${{ matrix.service }}..."
# Check GHCR manifest
docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.service }}:latest
# Verify both architectures are present
if docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.service }}:latest | grep -q "linux/amd64"; then
echo "✓ AMD64 architecture found"
else
echo "✗ AMD64 architecture missing"
exit 1
fi
if docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.service }}:latest | grep -q "linux/arm64"; then
echo "✓ ARM64 architecture found"
else
echo "✗ ARM64 architecture missing"
exit 1
fi
echo "Multi-architecture build verified successfully!"