diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index dd3ffca12..752c5c71b 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -384,10 +384,35 @@ jobs: run: uv run --no-sync python .github/scripts/infra_images.py public # A release's wheel names only images the registry serves under their tags. + # The explorer's built UI, which the framework job ships in the wheel: built here, so the job publishing to PyPI runs + # no npm. + explorer-ui: + needs: main-ci + if: github.event_name == 'push' + runs-on: ubuntu-latest + timeout-minutes: 15 + defaults: + run: + working-directory: src/agent_env/explorer/ui + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "22" + - run: npm ci + - run: npm run build:static + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: explorer-ui + path: src/agent_env/explorer/ui/out + if-no-files-found: error + framework: - needs: [protocol, infra-plan, infra-record] + needs: [protocol, infra-plan, infra-record, explorer-ui] if: >- - !cancelled() && needs.protocol.result == 'success' + !cancelled() && needs.protocol.result == 'success' && needs.explorer-ui.result == 'success' && (needs.infra-plan.result == 'skipped' || (needs.infra-plan.result == 'success' && needs.infra-record.result == 'success')) runs-on: ubuntu-latest @@ -419,6 +444,11 @@ jobs: echo "$GHCR_TOKEN" | docker login ghcr.io --username "$GITHUB_ACTOR" --password-stdin python3 .github/scripts/infra_build.py verify-record src/agent_env/env/published_images.json echo "record=$RECORD" >> "$GITHUB_OUTPUT" + - name: Put the explorer's UI in the wheel + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: explorer-ui + path: src/agent_env/explorer/static - name: Build agentenv-framework, pinned to this release's agentenv-framework-protocol run: | # The framework's requirement on the protocol keeps its extras, which core imports from. @@ -426,6 +456,8 @@ jobs: # Each shipped bundle's images install the protocol this release ships with, keeping its extras. python3 .github/scripts/shipped_bundles.py pin uv build --no-sources --out-dir dist + unzip -l dist/agentenv_framework-*.whl | grep -q agent_env/explorer/static/index.html \ + || { echo "::error::the wheel has no explorer UI"; exit 1; } - name: Check its metadata renders run: uvx --index-url https://pypi.org/simple twine check --strict dist/* - name: Publish agentenv-framework diff --git a/.gitignore b/.gitignore index d875c2f10..696f4e89b 100644 --- a/.gitignore +++ b/.gitignore @@ -170,3 +170,4 @@ cython_debug/ # Written by the release workflow into the wheels it publishes src/agent_env/env/published_images.json +src/agent_env/explorer/static/ diff --git a/pyproject.toml b/pyproject.toml index 5c562f7e3..c4ecc3a7b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -142,14 +142,14 @@ Changelog = "https://github.com/scaleapi/agentenv-framework/releases" packages = ["src/agent_env"] # The explorer UI *source* lives at src/agent_env/explorer/ui/ (a Next.js project). # Keep it out of the wheel — only its built output ships, copied to explorer/static/ -# by the UI build step. node_modules/out/.next are already .gitignore-excluded. +# by the release workflow. node_modules/out/.next are already .gitignore-excluded. exclude = ["src/agent_env/explorer/ui"] -# The release workflow writes it and git ignores it; a build ships it when it's there. -artifacts = ["src/agent_env/env/published_images.json"] +# The release workflow writes these and git ignores them; a build ships them when they're there. +artifacts = ["src/agent_env/env/published_images.json", "src/agent_env/explorer/static"] [tool.hatch.build.targets.sdist] only-include = ["src", "tst", "packages/agentenv-protocol", ".github/scripts"] -artifacts = ["src/agent_env/env/published_images.json"] +artifacts = ["src/agent_env/env/published_images.json", "src/agent_env/explorer/static"] [tool.uv.workspace] members = ["packages/agentenv-protocol"] diff --git a/src/agent_env/explorer/ui/README.md b/src/agent_env/explorer/ui/README.md index 31f9df7e0..d8892a191 100644 --- a/src/agent_env/explorer/ui/README.md +++ b/src/agent_env/explorer/ui/README.md @@ -23,5 +23,7 @@ explorer's default address. To point it somewhere else, copy `.env.example` to ` npm run build:static # writes out/ ``` -`agent-env up` serves the built UI when `[explorer] static_dir` in `.agentenv/config.toml` points -at `out/`. Checks: `npm run typecheck`, `npm run test:smoke` and `npm run lint`. +A release ships the built UI in the wheel, so an installed `agent-env up` serves it as is. From a +source checkout, `agent-env up` serves the built UI when `[explorer] static_dir` in +`.agentenv/config.toml` points at `out/`. Checks: `npm run typecheck`, `npm run test:smoke` and +`npm run lint`.