Skip to content

feat(env): set up the infra envs from their published images, building only what isn't published #1239

feat(env): set up the infra envs from their published images, building only what isn't published

feat(env): set up the infra envs from their published images, building only what isn't published #1239

Workflow file for this run

name: Local backends
# The public tier: the unit suite and the backend-agnostic integration suite under the built-in
# local defaults (SQLite, filesystem objects, a local registry, Docker sandboxes), with no secrets
# and no external services. Tests whose assertions are about one particular backend live with
# that backend's own suite, not here.
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
# One group per pull request, so a newer push cancels the superseded run; one group per commit on
# main, so no push to main is ever cancelled or queued behind another (a group holds at most one
# pending run, and the version bump lands seconds after every merge).
concurrency:
group: local-backends-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
AGENT_ENV_ENVIRONMENT: dev
PIP_DISABLE_PIP_VERSION_CHECK: "1"
jobs:
unit:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install from uv.lock
run: |
python -m pip install --quiet -r .github/ci-requirements.txt
uv sync --locked --extra dev --python "$(command -v python)"
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- name: Lockfile resolves from PyPI only
run: |
if grep 'source = { registry = ' uv.lock | grep -v 'registry = "https://pypi.org/simple"' | grep -q .; then echo "uv.lock has a registry source other than PyPI"; exit 1; fi
grep -A2 '^name = "agentenv-framework-protocol"$' uv.lock | grep -q 'source = { editable = "packages/agentenv-protocol" }'
- name: Lockfile is current, before and after a release bump
run: |
uv lock --check
uv run --no-project --with tomlkit python scripts/bump_version.py
uv lock --check
git checkout -- pyproject.toml packages/agentenv-protocol/pyproject.toml uv.lock
- name: Lint
run: .venv/bin/ruff check
- name: Unit tier
run: .venv/bin/python -m pytest tst/unit packages/agentenv-protocol/tests -n auto -q --timeout=300 --junitxml=junit-unit.xml
ui:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: src/agent_env/explorer/ui
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"
cache: npm
cache-dependency-path: src/agent_env/explorer/ui/package-lock.json
- run: npm ci
- name: Typecheck
run: npm run typecheck
- name: Lint
run: npm run lint
- name: Smoke suite
run: npm run test:smoke
- name: Static export
run: npm run build:static
integration-local:
runs-on: ubuntu-latest
timeout-minutes: 45
services:
registry:
image: mirror.gcr.io/library/registry:2
ports:
- 5000:5000
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install from uv.lock
run: |
python -m pip install --quiet -r .github/ci-requirements.txt
uv sync --locked --extra dev --python "$(command -v python)"
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- name: Integration tier on the local defaults
run: |
.venv/bin/python -m pytest -m 'not int_test_slow' -rA --timeout=900 --junitxml=junit-integration.xml \
tst/integration
- name: Skips must be declared capability gaps
if: always()
run: |
.venv/bin/python .github/scripts/check_skip_policy.py junit-integration.xml \
--allow model_endpoint_configured remote_sandbox \
--no-skips-under tst/integration/store/
# The slow tier: builds the env images and the echo A2A agent (tst/data/a2a_agent) and deploys
# them on the runner's Docker. The tests that need a real model, a remote sandbox, a registered
# default A2A agent or MCP server sources from outside this repository skip with the capability reason.
# The gateway tests take as long as the rest of the tier, so they run beside it as a check of their own.
integration-local-slow:
name: ${{ matrix.check }}
strategy:
fail-fast: false
matrix:
include:
- check: integration-local-slow
tests: tst/integration --ignore=tst/integration/env/gateway/gateway_test.py
- check: integration-local-gateway
tests: tst/integration/env/gateway/gateway_test.py
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install from uv.lock
run: |
python -m pip install --quiet -r .github/ci-requirements.txt
uv sync --locked --extra dev --python "$(command -v python)"
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
# ECR Public's anonymous pulls fail here for hours at a time. This can restart dockerd, so the registry
# starts afterwards.
- name: Pull the base images from mirror.gcr.io
run: python3 .github/scripts/mirror_base_images.py src tst
- name: Start the local registry
run: |
docker run --detach --name registry --publish 5000:5000 mirror.gcr.io/library/registry:2
timeout 30 sh -c 'until curl -sf http://localhost:5000/v2/ >/dev/null; do sleep 1; done'
- name: Slow integration tier on the local defaults
run: |
.venv/bin/python -m pytest -m int_test_slow -rA --timeout=1200 --junitxml=junit-integration-slow.xml \
${{ matrix.tests }}
- name: Skips must be declared capability gaps
if: always()
run: |
.venv/bin/python .github/scripts/check_skip_policy.py junit-integration-slow.xml \
--allow model_endpoint_configured remote_sandbox default_a2a_agent mcp_server_sources
# Whether this change touches the code the installer tier covers; the tier costs minutes, so
# it runs only then. A skipped job reports as passed to a required check.
changes:
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
plugins: ${{ steps.diff.outputs.plugins }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 0
- id: diff
env:
# A pull request's merge ref sits on the current base, which base.sha lags once the base
# moves; diffing against base.sha would count the base's own later commits as changes.
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || github.event.before }}
run: |
paths='^(src/agent_env/cli/(__init__|__main__|_installers|_plugin_changes|plugin)\.py|src/agent_env/(plugins|config)/|src/agent_env/py\.typed|packages/agentenv-protocol/|tst/installer/|tst/util/capabilities\.py|pyproject\.toml|uv\.lock|Makefile|\.github/(ci-requirements\.txt|workflows/local-backends\.yml|scripts/check_skip_policy\.py))'
if ! changed=$(git diff --name-only "$BASE" HEAD 2>/dev/null); then
echo "plugins=true" >> "$GITHUB_OUTPUT"
elif grep -qE "$paths" <<< "$changed"; then
echo "plugins=true" >> "$GITHUB_OUTPUT"
else
echo "plugins=false" >> "$GITHUB_OUTPUT"
fi
# `plugin add` and `remove` through the real pip, uv and pipx, offline against wheels built from
# this checkout; the dependencies are downloaded from PyPI once, before the tests go offline.
installer:
needs: changes
if: needs.changes.outputs.plugins == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install from uv.lock
run: |
python -m pip install --quiet -r .github/ci-requirements.txt pipx
uv sync --locked --extra dev --python "$(command -v python)"
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- name: Installer tier
run: .venv/bin/python -m pytest tst/installer -n auto -rA --timeout=900 --junitxml=junit-installer.xml
- name: Skips must be declared capability gaps
if: always()
run: .venv/bin/python .github/scripts/check_skip_policy.py junit-installer.xml