Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Build-Publish

on:
push:
# Trigger on version tags like v1.0.0
tags:
- 'v*'
# Trigger on pushes to main (typically PR merges)
branches:
- main
# Allow manual trigger
workflow_dispatch:

permissions:
contents: read
packages: write

# Cancel superseded builds so rapid pushes don't queue duplicates.
# Never cancel tag builds — each tag is a distinct release artifact.
concurrency:
group: build-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}

jobs:
build-and-push:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
image_config:
# A2A runner used by the k8s Job in
# exgentic_a2a_runner/k8s/job.yaml.
- name: exgentic-a2a-runner
context: ./exgentic_a2a_runner
dockerfile: ./exgentic_a2a_runner/Dockerfile

steps:
# 1. Checkout code
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

# 2. Set up QEMU for multi-arch builds
- name: Set up QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4

# 3. Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4

# 4. Log in to GitHub Container Registry
- name: Log in to ghcr.io
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# 5. Resolve the image tag:
# - on v* tag → the tag name (e.g. v0.0.1)
# - otherwise → <sanitized-branch>-<sha7>
- name: Generate image tag
id: tag
run: |
if [[ "${{ github.ref_type }}" == "tag" ]]; then
echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
else
BRANCH="${{ github.ref_name }}"
BRANCH="${BRANCH//\//-}"
SHORT_SHA="$(echo "${{ github.sha }}" | cut -c1-7)"
echo "tag=${BRANCH}-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
fi

# 6. Extract Docker metadata. Apply `latest` on v* tag pushes,
# pushes to main, and manual dispatches.
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: ghcr.io/${{ github.repository }}/${{ matrix.image_config.name }}
tags: |
type=raw,value=${{ steps.tag.outputs.tag }}
type=raw,value=latest,enable=${{ (github.ref_type == 'tag' && startsWith(github.ref_name, 'v')) || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' }}

# 7. Build and push image. Note: no build-args here — the runner
# doesn't need any today, and specifying `build-args:` twice (as
# cortex's build.yaml does) silently drops matrix-level args
# because the second key wins.
- name: Build and push ${{ matrix.image_config.name }}
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
with:
context: ${{ matrix.image_config.context }}
file: ${{ matrix.image_config.dockerfile }}
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
42 changes: 33 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -906,15 +906,11 @@ The runner can execute entirely inside the cluster as a Kubernetes Job — no lo

`k8s/job.yaml` is the launch template. It references secrets for credentials and passes benchmark/agent flags as container `args`. The job container uses cluster-internal DNS to reach the Kagenti API, Keycloak, MCP server, and agent — no port-forwarding is required. MLflow tracing switches automatically to HTTP/protobuf when `KUBERNETES_SERVICE_HOST` is set.

### Step 1 — Build and push the runner image
### Step 1 — Pull (or build) the runner image

```bash
cd exgentic_a2a_runner
docker build -t ghcr.io/exgentic/runner:latest .
docker push ghcr.io/exgentic/runner:latest
```
Prebuilt multi-arch images are published to GHCR on every push to `main` and every `v*` tag — see [Container images](#container-images) below. `k8s/job.yaml` points at `:latest` (which tracks `main`) by default, so no build is required.

Replace `ghcr.io/exgentic/runner:latest` with your own registry path if needed, and update `k8s/job.yaml` → `image:` to match.
To build locally instead — for example, to test unreleased changes — see [Iterating with a locally-built image](#iterating-with-a-locally-built-image).

### Step 2 — Set up required secrets

Expand Down Expand Up @@ -996,12 +992,40 @@ AGENT PROCESSING LATENCY
To test a local image change without pushing to a registry, sync it into the kind cluster first:

```bash
export REMOTE_IMAGE_NAME=ghcr.io/exgentic/runner:dev
cd exgentic_a2a_runner
docker build -t ghcr.io/rossoctl/workload-harness/exgentic-a2a-runner:dev .
export REMOTE_IMAGE_NAME=ghcr.io/rossoctl/workload-harness/exgentic-a2a-runner:dev
export KIND_CLUSTER_NAME=kagenti
source ./sync-image-to-cluster.sh
```

Then set `imagePullPolicy: IfNotPresent` in `k8s/job.yaml` and submit as above.
Update `k8s/job.yaml` → `image:` to match your local tag, set `imagePullPolicy: IfNotPresent`, and submit as above.

## Container images

The runner image is built and published by [`.github/workflows/build.yaml`](.github/workflows/build.yaml) on every push to `main`, every `v*` tag, and manual workflow dispatch. Images are multi-arch (`linux/amd64`, `linux/arm64`).

| Image | Source |
|-------|--------|
| `ghcr.io/rossoctl/workload-harness/exgentic-a2a-runner` | [`exgentic_a2a_runner/Dockerfile`](exgentic_a2a_runner/Dockerfile) |

**Tags:**

| Ref pushed | Tags produced |
|------------|---------------|
| `v*` tag (e.g. `v0.0.1`) | `v0.0.1`, `latest` |
| Push to `main` | `main-<sha7>`, `latest` |
| Manual dispatch on any branch | `<branch>-<sha7>`, `latest` |
| Push to any other branch | `<branch>-<sha7>` |

`latest` tracks `main` — pin to a `v*` or `main-<sha7>` tag for reproducible deploys.

**Build locally:**

```bash
cd exgentic_a2a_runner
docker build -t ghcr.io/rossoctl/workload-harness/exgentic-a2a-runner:dev .
```

## E2E Test Script

Expand Down
4 changes: 3 additions & 1 deletion exgentic_a2a_runner/k8s/job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ spec:
# All cluster interaction goes through the Kagenti API and Keycloak over HTTP.
containers:
- name: runner
image: ghcr.io/exgentic/runner:latest
# Published by .github/workflows/build.yaml. `:latest` tracks
# main; use a `main-<sha7>` or `v*` tag to pin a specific build.
image: ghcr.io/rossoctl/workload-harness/exgentic-a2a-runner:latest
imagePullPolicy: IfNotPresent
args:
- "--benchmark"
Expand Down