ci(environment): pin the real agentenv lane to agentenv-framework 0.9.1431 (#8865)

* ci(environment): pin the real agentenv lane to agentenv-framework 0.9.1431

The real-agentenv lane, its identity check and the docs pinned
agentenv-framework 0.9.1334, 97 releases behind the current 0.9.1431.
Recorded verification notes keep the versions they ran with; the website
catalogs change only the placeholder comment that shows the version.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* docs(environment): describe 0.9.1431's pulled infra images; keep the site on the release

0.9.1431 pulls its gateway and service-db images from ghcr.io by the
digests its release records and builds one only when that pull fails,
so the lane docs, the export guide and the verifier's comments now say
so, and the mirror step fetches only the bases those builds name. The
public site describes the released package, which still runs 0.9.1334,
so its guide and evidence page keep that version until a release ships
the new pin.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Edgar ArakelyanandClaude Opus 5.5 authored and GitHub committed 2026-11-06 01:53:53 +08:00
1 parent dd31958743
commit 0ac6be1a3d
7 files changed
+35 -29

No files matched your search

+8 -7
View File
@@ -54,10 +54,11 @@ jobs:
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
# Public ECR caps anonymous pulls by data per source IP and hosted runners share IPs, so the
# framework's image builds can fail here for hours. mirror.gcr.io serves the same Docker
# official images under the same digests, so each base image the pinned framework builds from
# is pulled there and named as its Dockerfile names it, as the framework's own CI does.
# The pinned framework builds its gateway and service-db images only when pulling them from
# ghcr.io fails, from public ECR base images; public ECR caps anonymous pulls by data per source
# IP and hosted runners share IPs, so such a build can fail here for hours. mirror.gcr.io serves
# the same Docker official images under the same digests, so each base image those Dockerfiles
# name is pulled there and named as its Dockerfile names it, as the framework's own CI does.
# Digest-pinned names are set in containerd, whose images Docker reads only on the containerd
# image store; switching stores restarts dockerd, so it happens before anything uses Docker.
- name: Use the containerd image store
@@ -72,16 +73,16 @@ jobs:
run: |
runner_root="${RUNNER_TEMP}/rea-agentenv-runner"
python -m venv "${runner_root}"
"${runner_root}/bin/python" -m pip install --require-virtualenv --no-cache-dir 'agentenv-framework==0.9.1334'
"${runner_root}/bin/python" -m pip install --require-virtualenv --no-cache-dir 'agentenv-framework==0.9.1431'
"${runner_root}/bin/agent-env" --version
docker version --format '{{.Server.Version}}'
echo "REA_AGENT_ENV_COMMAND=${runner_root}/bin/agent-env" >> "${GITHUB_ENV}"
echo "REA_DOCKER_COMMAND=$(command -v docker)" >> "${GITHUB_ENV}"
- name: Pull the pinned framework's public ECR base images from mirror.gcr.io
- name: Pull the gateway and service-db public ECR base images from mirror.gcr.io
shell: bash
run: |
package="$("${REA_AGENT_ENV_COMMAND%/agent-env}/python" -c 'import agent_env, pathlib; print(pathlib.Path(agent_env.__file__).parent)')"
grep -rhoE '^FROM +public\.ecr\.aws/docker/library/[^ ]+' --include='Dockerfile*' "${package}" | awk '{print $2}' | sort -u |
grep -rhoE '^FROM +public\.ecr\.aws/docker/library/[^ ]+' --include='Dockerfile*' "${package}/env/gateway" "${package}/env/envs/service_db" | awk '{print $2}' | sort -u |
while read -r image; do
name=${image#public.ecr.aws/docker/library/}
source=mirror.gcr.io/library/$name
+1 -1
View File
@@ -19,7 +19,7 @@ records the app you provide; you start it and prepare its test data.
To run the exported environment, install the
[AgentEnv framework](https://github.com/scaleapi/agentenv-framework#install)
and start Docker. REA's [compatibility check](testing.md#exported-environment-bundles)
uses AgentEnv version `0.9.1334` with Python 3.12.
uses AgentEnv version `0.9.1431` with Python 3.12.
There are two ways to build an environment: ask your agent to record the app,
or start from a recording you already have.
+3 -2
View File
@@ -1049,8 +1049,9 @@ unknown recorded status stays unknown; it is not borrowed from another
record). A bundle with no such tool yields a verifier that checks the count
only and says so. `tasks/smoke.json` deploys the env on the local
sandbox and runs that verifier against the env's MCP endpoint; the first run
also builds the framework's own infrastructure, and the run tears everything
down when it ends.
also pulls the framework's published infrastructure images from `ghcr.io`,
building one only if its pull fails, and the run tears everything down when it
ends.
The README written into the bundle records the capture artifact's SHA-256, the
capture and manifest Evidence ids, the manifest view digest, the served tool
@@ -69,7 +69,7 @@ previous increment.
- Add the `agentenv` CI scope, the reusable `real-agentenv.yml` workflow
(`workflow_dispatch` and `workflow_call` with `build_cache_artifact`,
`ubuntu-24.04`, SHA-pinned actions, `setup-python` 3.12, a virtual
environment with `agentenv-framework==0.9.1334`, the runner's Docker, 30
environment with `agentenv-framework==0.9.1431`, the runner's Docker, 30
minutes), the `verify:agentenv:environment` script and
`scripts/verify-agentenv-environment.mjs`, which requires absolute
`REA_AGENT_ENV_COMMAND` and `REA_DOCKER_COMMAND` like every other lane
+14 -10
View File
@@ -1172,9 +1172,10 @@ installed package entrypoint as the script's first argument for package coverage
`npm run verify:agentenv:environment` is the `real-agentenv` lane. It requires
the host's Docker CLI named by absolute `REA_DOCKER_COMMAND`, Python 3.12 with
`agentenv-framework==0.9.1334` installed in a virtual environment whose
`agentenv-framework==0.9.1431` installed in a virtual environment whose
`agent-env` binary is named by absolute `REA_AGENT_ENV_COMMAND`, and outbound
network for `pip` on the runner and for `npm` inside the image build. Both
network for `pip` on the runner, for the framework's image pulls from `ghcr.io`
and for `npm` inside the image build. Both
variables are required; neither upstream executable is resolved from `PATH`,
and the verifier installs nothing. Packing uses the shared npm helper, honoring
`npm_execpath` from the caller's selected npm. Direct Node invocations without
@@ -1186,11 +1187,12 @@ storage, exports both paths and uses the runner's own Docker; no developer host
configuration changes. `agent-env run` attempts share one 22-minute budget
inside the 30-minute job (the first attempt at most 15 minutes), so a hung or
retried run ends with the verifier's failed receipt rather than the runner's
kill. The framework builds its gateway and service-db
images from `public.ecr.aws` on every fresh runner, and hosted runners share
that registry's anonymous pull quota, so the lane first pulls the base images
the pinned framework's Dockerfiles name from `mirror.gcr.io`, which serves the
same Docker official images under the same digests, and names them as those
kill. The pinned framework pulls its gateway and service-db images from
`ghcr.io/scaleapi` by the digests its release records and builds one only when
its pull fails. Those builds start from `public.ecr.aws` base images, and hosted
runners share that registry's anonymous pull quota, so the lane first pulls the
base images the gateway and service-db Dockerfiles name from `mirror.gcr.io`,
which serves the same Docker official images under the same digests, and names them as those
Dockerfiles do (on Docker's containerd image store, so digest-pinned names
resolve), as the framework's own CI does. The quota handling below covers
anything still pulled from that registry. The receipt's `agent_env_run` records the
@@ -1218,9 +1220,11 @@ that served tool count, and that no container exists
after the run that did not exist before; the container inventory runs even when
the run fails or times out, so a failed receipt still lists what it left. The one exception is the framework's
own image-store helper, `agentenv-registry` (or `agentenv-registry-<port>`),
a `registry:2` container the local provider starts on first use and keeps
running across runs; a first run on a fresh host creates it, so the receipt
lists it under `image_store_helpers` instead of counting it as a leak. Images
a `registry:2` container the local provider starts when it first stores an image
it built and keeps running across runs. The pinned framework registers its
published infra images, and a deploy that cannot pull one builds it into the
host's Docker, so a fresh run does not normally create the helper; if one does,
the receipt lists it under `image_store_helpers` instead of counting it as a leak. Images
built by the run remain and are counted in the receipt. Pass an installed
package entrypoint as the script's first argument for package coverage.
+5 -5
View File
@@ -8,10 +8,10 @@ import { PrivateRuntimeRoot } from "../dist/process/PrivateRuntimeRoot.js";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
import { createPackageVerifierCommands } from "./lib/verify-package-commands.mjs";
const AGENTENV_VERSION = "0.9.1334";
const AGENTENV_VERSION = "0.9.1431";
const AGENTENV_PIN = `agentenv-framework ${AGENTENV_VERSION}`;
// The framework builds its infra images from public ECR, whose anonymous pull quota hosted
// runners share; a rate refusal earns one retry, anything else fails at once.
// Only an infra image whose pull fails is built, from public ECR, whose anonymous pull quota
// hosted runners share; a rate refusal earns one retry, anything else fails at once.
const PUBLIC_ECR_QUOTA =
/public\.ecr\.aws[\s\S]{0,400}?(?:429 Too Many Requests|toomanyrequests)/u;
// The anonymous data-transfer cap is counted per source IP, so a pause on the same runner
@@ -31,8 +31,8 @@ for (const key of ["REA_AGENT_ENV_COMMAND", "REA_DOCKER_COMMAND"])
);
const agentEnv = process.env.REA_AGENT_ENV_COMMAND;
const docker = process.env.REA_DOCKER_COMMAND;
// The framework's local image store keeps its registry:2 helper running across runs; a first
// run on a fresh host creates it, so it is reported separately rather than counted as a leak.
// The framework's local image store keeps its registry:2 helper running across runs; a run that
// first stores a build there creates it, so it is reported separately rather than counted as a leak.
const IMAGE_STORE_HELPER = /^agentenv-registry(?:-\d+)?$/u;
await Promise.all([access(agentEnv), access(docker)]);
const entrypoint =
@@ -29,7 +29,7 @@ it.skipIf(process.platform === "win32")(
);
await writeFile(
runner,
"#!/usr/bin/env node\nprocess.stdout.write('agent-env 0.9.1334\\n');\n",
"#!/usr/bin/env node\nprocess.stdout.write('agent-env 0.9.1431\\n');\n",
{ mode: 0o755 },
);
await writeFile(docker, "#!/usr/bin/env node\nprocess.exit(0);\n", {
@@ -70,8 +70,8 @@ it.skipIf(process.platform === "win32")(
// The local framework and these executable shebang fixtures target POSIX hosts.
it.skipIf(process.platform === "win32").each([
["agent-env 0.9.9999", false],
["other-runner 0.9.1334", false],
["agent-env 0.9.1334", true],
["other-runner 0.9.1431", false],
["agent-env 0.9.1431", true],
] as const)(
"admits the observed executable identity %s before Docker: %s",
async (version, accepted) => {