openrag/.github/workflows/build-multiarch.yml
2025-12-15 16:35:09 -05:00

258 lines
8.7 KiB
YAML

name: Release + Docker Images (multi-arch)
on:
push:
branches:
- main
paths:
- 'pyproject.toml'
workflow_dispatch:
jobs:
check-version:
runs-on: ubuntu-latest
outputs:
skip_release: ${{ steps.version.outputs.skip_release }}
version: ${{ steps.version.outputs.version }}
docker_version: ${{ steps.version.outputs.docker_version }}
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Extract version from pyproject.toml
id: version
run: |
VERSION=$(grep '^version = ' pyproject.toml | cut -d '"' -f 2)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
# Normalize version per PEP 440 for Docker tags
# e.g., "0.1.53-rc2" -> "0.1.53rc2" to match Python's importlib.metadata
DOCKER_VERSION=$(echo "$VERSION" | sed -E 's/-?(rc|alpha|beta|dev|post)/\1/g')
echo "docker_version=$DOCKER_VERSION" >> $GITHUB_OUTPUT
echo "Docker Version: $DOCKER_VERSION"
# Check if tag already exists
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
echo "Tag v$VERSION already exists, skipping release"
echo "skip_release=true" >> $GITHUB_OUTPUT
exit 0
fi
echo "skip_release=false" >> $GITHUB_OUTPUT
# Check if version is numeric (e.g., 0.1.16) vs prerelease (e.g., 0.1.16-rc1)
if [[ "$VERSION" =~ ^[0-9.-]+$ ]]; then
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "Release type: Production"
else
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "Release type: Prerelease"
fi
build:
needs: check-version
if: needs.check-version.outputs.skip_release != 'true'
strategy:
fail-fast: false
matrix:
include:
# backend
- image: backend
file: ./Dockerfile.backend
tag: langflowai/openrag-backend
platform: linux/amd64
arch: amd64
runs-on: ubuntu-latest-16-cores
- image: backend
file: ./Dockerfile.backend
tag: langflowai/openrag-backend
platform: linux/arm64
arch: arm64
#runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-2]
runs-on: RagRunner
# frontend
- image: frontend
file: ./Dockerfile.frontend
tag: langflowai/openrag-frontend
platform: linux/amd64
arch: amd64
runs-on: ubuntu-latest-16-cores
- image: frontend
file: ./Dockerfile.frontend
tag: langflowai/openrag-frontend
platform: linux/arm64
arch: arm64
#runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-2]
runs-on: RagRunner
# langflow
- image: langflow
file: ./Dockerfile.langflow
tag: langflowai/openrag-langflow
platform: linux/amd64
arch: amd64
runs-on: ubuntu-latest-16-cores
- image: langflow
file: ./Dockerfile.langflow
tag: langflowai/openrag-langflow
platform: linux/arm64
arch: arm64
#runs-on: self-hosted
runs-on: RagRunner
# opensearch
- image: opensearch
file: ./Dockerfile
tag: langflowai/openrag-opensearch
platform: linux/amd64
arch: amd64
runs-on: ubuntu-latest-16-cores
- image: opensearch
file: ./Dockerfile
tag: langflowai/openrag-opensearch
platform: linux/arm64
arch: arm64
#runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-2]
#runs-on: self-hosted
runs-on: RagRunner
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- 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: Build and push ${{ matrix.image }} (${{ matrix.arch }})
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.file }}
platforms: ${{ matrix.platform }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ matrix.tag }}:${{ needs.check-version.outputs.docker_version }}-${{ matrix.arch }}
cache-from: type=gha,scope=${{ matrix.image }}-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=${{ matrix.image }}-${{ matrix.arch }}
manifest:
needs: [build, check-version]
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' && needs.check-version.outputs.skip_release != 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Create and push multi-arch manifests
run: |
VERSION=${{ needs.check-version.outputs.docker_version }}
# Create versioned tags
docker buildx imagetools create -t langflowai/openrag-backend:$VERSION \
langflowai/openrag-backend:$VERSION-amd64 \
langflowai/openrag-backend:$VERSION-arm64
docker buildx imagetools create -t langflowai/openrag-frontend:$VERSION \
langflowai/openrag-frontend:$VERSION-amd64 \
langflowai/openrag-frontend:$VERSION-arm64
docker buildx imagetools create -t langflowai/openrag-langflow:$VERSION \
langflowai/openrag-langflow:$VERSION-amd64 \
langflowai/openrag-langflow:$VERSION-arm64
docker buildx imagetools create -t langflowai/openrag-opensearch:$VERSION \
langflowai/openrag-opensearch:$VERSION-amd64 \
langflowai/openrag-opensearch:$VERSION-arm64
# Only update latest tags if version is numeric
if [[ "$VERSION" =~ ^[0-9.-]+$ ]]; then
echo "Updating latest tags for production release: $VERSION"
docker buildx imagetools create -t langflowai/openrag-backend:latest \
langflowai/openrag-backend:$VERSION-amd64 \
langflowai/openrag-backend:$VERSION-arm64
docker buildx imagetools create -t langflowai/openrag-frontend:latest \
langflowai/openrag-frontend:$VERSION-amd64 \
langflowai/openrag-frontend:$VERSION-arm64
docker buildx imagetools create -t langflowai/openrag-langflow:latest \
langflowai/openrag-langflow:$VERSION-amd64 \
langflowai/openrag-langflow:$VERSION-arm64
docker buildx imagetools create -t langflowai/openrag-opensearch:latest \
langflowai/openrag-opensearch:$VERSION-amd64 \
langflowai/openrag-opensearch:$VERSION-arm64
else
echo "Skipping latest tags - version: $VERSION (not numeric)"
fi
build-python-packages:
needs: [manifest, check-version]
runs-on: ubuntu-latest
if: needs.check-version.outputs.skip_release != 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Build wheel and source distribution
run: |
uv build
- name: List built artifacts
run: |
ls -la dist/
echo "Built artifacts:"
for file in dist/*; do
echo " - $(basename $file) ($(stat -c%s $file | numfmt --to=iec-i)B)"
done
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: python-packages
path: dist/
retention-days: 30
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.check-version.outputs.version }}
name: Release ${{ needs.check-version.outputs.version }}
draft: false
prerelease: ${{ needs.check-version.outputs.is_prerelease }}
generate_release_notes: true
files: |
dist/*.whl
dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# - name: Publish to PyPI
# run: |
# uv publish
# env:
# UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }}