Repository navigation
feat(env): set up the infra envs from their published images, building only what isn't published #1239
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: 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 |