Build Docker Images (Community) #759
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" |