Skip to content

Build Docker Images (Community) #759

Build Docker Images (Community)

Build Docker Images (Community) #759

Workflow file for this run

name: Build Docker Images (Community)
# Community build workflow - builds and tests Docker images locally.
# Does NOT push to any registry - users build and run locally.
#
# Runs ONLY in the public `axonflow` (community-mirror) repo. In the
# `axonflow-enterprise` repo this workflow is a no-op — every job is gated on
# `github.repository == 'getaxonflow/axonflow'`. The community-edition images
# this workflow produces are not deployed from `axonflow-enterprise` (build.yml
# defaults to EDITION=enterprise; the only enterprise consumers are the ECR
# push targets), so building them here was duplicate work. The workflow file
# still syncs to community via `sync-community-repo.yml`, where it builds the
# images locally for users running the mirror. Saved ~1,462 billable min/14d
# in enterprise.
on:
push:
branches:
- main
paths:
- 'platform/*/Dockerfile'
- 'platform/agent/**/*.go'
- 'platform/orchestrator/**/*.go'
- 'platform/connectors/**/*.go'
- 'platform/common/**/*.go'
- 'platform/cmd/**/*.go'
- 'platform/**/go.mod'
- 'platform/**/go.sum'
- 'migrations/core/**/*.sql'
- '.github/workflows/build-community.yml'
# Pull requests: Run detect-changes and Build Summary on ALL PRs
# This ensures the required Build Summary check is present for merge queue entry.
# Actual builds are skipped on PRs - only validated in merge queue.
pull_request:
branches:
- main
merge_group:
branches:
- main
workflow_dispatch:
# Cancel orphaned PR runs when a new commit is pushed. Pushes to main / merge_group
# runs use the SHA so they never share a group and never cancel each other.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
AXONFLOW_TELEMETRY: 'off'
jobs:
# =============================================================================
# Change Detection (merge_group and pull_request)
# =============================================================================
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
if: |
github.repository == 'getaxonflow/axonflow' &&
(github.event_name == 'merge_group' || github.event_name == 'pull_request')
permissions:
contents: read
pull-requests: read
outputs:
agent: ${{ steps.filter.outputs.agent }}
orchestrator: ${{ steps.filter.outputs.orchestrator }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Detect file changes
uses: dorny/paths-filter@v4
id: filter
with:
filters: |
agent:
- 'platform/agent/**'
- 'platform/common/**'
- 'platform/cmd/**'
- 'platform/connectors/**'
- 'platform/**/go.mod'
- 'platform/**/go.sum'
- 'migrations/core/**/*.sql'
- '.github/workflows/build-community.yml'
orchestrator:
- 'platform/orchestrator/**'
- 'platform/common/**'
- 'platform/cmd/**'
- 'platform/**/go.mod'
- 'platform/**/go.sum'
- 'migrations/core/**/*.sql'
- '.github/workflows/build-community.yml'
# =============================================================================
# Build Jobs (Community - Local Only)
# =============================================================================
build-agent:
name: Build Agent Image
needs: [detect-changes]
# Run if: NOT a PR AND (detect-changes was skipped OR succeeded with agent=true)
# Skip if: PR, detect-changes failed, or succeeded with agent=false
if: |
github.repository == 'getaxonflow/axonflow' &&
always() &&
github.event_name != 'pull_request' &&
needs.detect-changes.result != 'failure' &&
(needs.detect-changes.result == 'skipped' || needs.detect-changes.outputs.agent == 'true')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build Agent Image
uses: docker/build-push-action@v7
with:
context: .
file: platform/agent/Dockerfile
push: false
load: true
tags: axonflow/agent:local
build-args: |
EDITION=community
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test Agent Image
run: |
docker run --rm axonflow/agent:local --version || echo "Version check complete"
echo "Agent image built successfully"
build-orchestrator:
name: Build Orchestrator Image
needs: [detect-changes]
# Run if: NOT a PR AND (detect-changes was skipped OR succeeded with orchestrator=true)
# Skip if: PR, detect-changes failed, or succeeded with orchestrator=false
if: |
github.repository == 'getaxonflow/axonflow' &&
always() &&
github.event_name != 'pull_request' &&
needs.detect-changes.result != 'failure' &&
(needs.detect-changes.result == 'skipped' || needs.detect-changes.outputs.orchestrator == 'true')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build Orchestrator Image
uses: docker/build-push-action@v7
with:
context: .
file: platform/orchestrator/Dockerfile
push: false
load: true
tags: axonflow/orchestrator:local
build-args: |
EDITION=community
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test Orchestrator Image
run: |
docker run --rm axonflow/orchestrator:local --version || echo "Version check complete"
echo "Orchestrator image built successfully"
# =============================================================================
# Docker Compose Integration Test
# =============================================================================
docker-compose-test:
name: Test Docker Compose Stack
runs-on: ubuntu-latest
needs: [build-agent, build-orchestrator]
# Skip on PRs - only run on push/merge_group when builds succeed
if: |
github.repository == 'getaxonflow/axonflow' &&
always() &&
github.event_name != 'pull_request' &&
(needs.build-agent.result == 'success' || needs.build-agent.result == 'skipped') &&
(needs.build-orchestrator.result == 'success' || needs.build-orchestrator.result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build and Start Stack
run: |
docker compose build
docker compose up -d
- name: Wait for Services
run: |
echo "Waiting for services to be healthy..."
sleep 30
- name: Health Check - Agent
run: |
for i in {1..10}; do
if curl -sf http://localhost:8080/health; then
echo "Agent is healthy"
exit 0
fi
echo "Waiting for agent... ($i/10)"
sleep 5
done
echo "Agent health check failed"
docker compose logs axonflow-agent
exit 1
- name: Health Check - Orchestrator
run: |
for i in {1..10}; do
if curl -sf http://localhost:8081/health; then
echo "Orchestrator is healthy"
exit 0
fi
echo "Waiting for orchestrator... ($i/10)"
sleep 5
done
echo "Orchestrator health check failed"
docker compose logs axonflow-orchestrator
exit 1
- name: Run Demo Script
run: |
if [ -f "examples/demo/demo.sh" ]; then
chmod +x examples/demo/demo.sh
./examples/demo/demo.sh || echo "Demo completed"
else
echo "Demo script not found, skipping"
fi
- name: Cleanup
if: always()
run: docker compose down -v
# =============================================================================
# Build Summary
# =============================================================================
build-summary:
name: Build Summary
runs-on: ubuntu-latest
needs: [detect-changes, build-agent, build-orchestrator, docker-compose-test]
if: always()
steps:
- name: Check Results
run: |
echo "=============================================="
echo "Community Docker Build Summary"
echo "=============================================="
echo ""
if [[ "${{ github.event_name }}" == "merge_group" ]]; then
echo "=== Change Detection ==="
echo "Status: ${{ needs.detect-changes.result }}"
if [[ "${{ needs.detect-changes.result }}" == "failure" ]]; then
echo "ERROR: Change detection failed"
exit 1
fi
echo ""
echo "=== Changes Detected ==="
echo "Agent: ${{ needs.detect-changes.outputs.agent }}"
echo "Orchestrator: ${{ needs.detect-changes.outputs.orchestrator }}"
echo ""
fi
echo "=== Build Results ==="
echo "Agent: ${{ needs.build-agent.result }}"
echo "Orchestrator: ${{ needs.build-orchestrator.result }}"
echo "Docker Compose: ${{ needs.docker-compose-test.result }}"
echo ""
# Check for failures
check_result() {
local result="$1"
local name="$2"
if [[ "$result" == "success" ]] || [[ "$result" == "skipped" ]]; then
return 0
fi
echo "FAILED: $name (result: $result)"
return 1
}
FAILED=false
check_result "${{ needs.build-agent.result }}" "Agent" || FAILED=true
check_result "${{ needs.build-orchestrator.result }}" "Orchestrator" || FAILED=true
check_result "${{ needs.docker-compose-test.result }}" "Docker Compose" || FAILED=true
echo ""
if [[ "$FAILED" == "true" ]]; then
echo "=============================================="
echo "BUILD FAILED"
echo "=============================================="
exit 1
fi
echo "=============================================="
if [[ "${{ github.event_name }}" == "merge_group" ]]; then
echo "MERGE QUEUE VALIDATION PASSED"
else
echo "BUILD SUCCESSFUL"
fi
echo "=============================================="
echo ""
echo "To run locally:"
echo " docker compose up -d"
echo ""
echo "Images built:"
echo " - axonflow/agent:local"
echo " - axonflow/orchestrator:local"