@@ -44,32 +44,40 @@ jobs:
4444 chmod +x scripts/version-check.sh
4545 ./scripts/version-check.sh
4646
47+ - name : Unit tests (release-utils.sh)
48+ run : bash tests/test_release_utils.sh
49+
4750 smoke :
4851 name : Installer Smoke Test
4952 runs-on : ubuntu-latest
5053 steps :
5154 - name : Checkout
5255 uses : actions/checkout@v4
5356
54- - name : Setup Node
55- uses : actions/setup-node@v4
56- with :
57- node-version : " 22"
58-
59- - name : Resolve tool versions
60- id : versions
61- env :
62- GH_TOKEN : ${{ github.token }}
63- run : bash ./scripts/resolve-tool-versions.sh
57+ - name : Load pinned versions
58+ id : pins
59+ shell : bash
60+ run : |
61+ set -euo pipefail
62+ source ./scripts/version-pins.sh
63+ load_version_pins
64+ emit_github_outputs "$GITHUB_OUTPUT"
6465
6566 - name : Build local smoke image
6667 run : |
6768 docker build -t deva-smoke:ci \
68- --build-arg CLAUDE_CODE_VERSION="${{ steps.versions.outputs.claude_code_version }}" \
69- --build-arg CODEX_VERSION="${{ steps.versions.outputs.codex_version }}" \
70- --build-arg GEMINI_CLI_VERSION="${{ steps.versions.outputs.gemini_cli_version }}" \
71- --build-arg ATLAS_CLI_VERSION="${{ steps.versions.outputs.atlas_cli_version }}" \
72- --build-arg COPILOT_API_VERSION="${{ steps.versions.outputs.copilot_api_version }}" \
69+ --build-arg NODE_MAJOR="${{ steps.pins.outputs.node_major }}" \
70+ --build-arg GO_VERSION="${{ steps.pins.outputs.go_version }}" \
71+ --build-arg PYTHON_VERSION="${{ steps.pins.outputs.python_version }}" \
72+ --build-arg DELTA_VERSION="${{ steps.pins.outputs.delta_version }}" \
73+ --build-arg TMUX_VERSION="${{ steps.pins.outputs.tmux_version }}" \
74+ --build-arg TMUX_SHA256="${{ steps.pins.outputs.tmux_sha256 }}" \
75+ --build-arg CLAUDE_CODE_VERSION="${{ steps.pins.outputs.claude_code_version }}" \
76+ --build-arg CLAUDE_TRACE_VERSION="${{ steps.pins.outputs.claude_trace_version }}" \
77+ --build-arg CODEX_VERSION="${{ steps.pins.outputs.codex_version }}" \
78+ --build-arg GEMINI_CLI_VERSION="${{ steps.pins.outputs.gemini_cli_version }}" \
79+ --build-arg ATLAS_CLI_VERSION="${{ steps.pins.outputs.atlas_cli_version }}" \
80+ --build-arg COPILOT_API_VERSION="${{ steps.pins.outputs.copilot_api_version }}" \
7381 .
7482
7583 - name : Build core and rust images via Makefile
@@ -79,11 +87,22 @@ jobs:
7987 TAG=ci \
8088 CORE_TAG=ci-core \
8189 RUST_TAG=ci-rust \
82- CLAUDE_CODE_VERSION="${{ steps.versions.outputs.claude_code_version }}" \
83- CODEX_VERSION="${{ steps.versions.outputs.codex_version }}" \
84- GEMINI_CLI_VERSION="${{ steps.versions.outputs.gemini_cli_version }}" \
85- ATLAS_CLI_VERSION="${{ steps.versions.outputs.atlas_cli_version }}" \
86- COPILOT_API_VERSION="${{ steps.versions.outputs.copilot_api_version }}"
90+ NODE_MAJOR="${{ steps.pins.outputs.node_major }}" \
91+ GO_VERSION="${{ steps.pins.outputs.go_version }}" \
92+ PYTHON_VERSION="${{ steps.pins.outputs.python_version }}" \
93+ DELTA_VERSION="${{ steps.pins.outputs.delta_version }}" \
94+ TMUX_VERSION="${{ steps.pins.outputs.tmux_version }}" \
95+ TMUX_SHA256="${{ steps.pins.outputs.tmux_sha256 }}" \
96+ CLAUDE_CODE_VERSION="${{ steps.pins.outputs.claude_code_version }}" \
97+ CLAUDE_TRACE_VERSION="${{ steps.pins.outputs.claude_trace_version }}" \
98+ CODEX_VERSION="${{ steps.pins.outputs.codex_version }}" \
99+ GEMINI_CLI_VERSION="${{ steps.pins.outputs.gemini_cli_version }}" \
100+ ATLAS_CLI_VERSION="${{ steps.pins.outputs.atlas_cli_version }}" \
101+ COPILOT_API_VERSION="${{ steps.pins.outputs.copilot_api_version }}" \
102+ PLAYWRIGHT_VERSION="${{ steps.pins.outputs.playwright_version }}" \
103+ RUST_TOOLCHAINS="${{ steps.pins.outputs.rust_toolchains }}" \
104+ RUST_DEFAULT_TOOLCHAIN="${{ steps.pins.outputs.rust_default_toolchain }}" \
105+ RUST_TARGETS="${{ steps.pins.outputs.rust_targets }}"
87106
88107 - name : Install and launch each agent without a TTY
89108 shell : bash
@@ -127,6 +146,26 @@ jobs:
127146 grep -F -- "$bridge_dir:/deva-host-chrome-bridge" <<<"$dry_run"
128147 grep -F -- "$profile_dir/Extensions:/home/deva/.config/google-chrome/Default/Extensions:ro" <<<"$dry_run"
129148
149+ - name : Smoke bind mount shape guard
150+ shell : bash
151+ run : |
152+ set -euo pipefail
153+ DEVA_DOCKER_IMAGE=deva-smoke \
154+ DEVA_DOCKER_TAG=ci \
155+ ./scripts/test-mount-shape.sh
156+
157+ - name : Smoke agent tooling installer
158+ shell : bash
159+ run : |
160+ set -euo pipefail
161+ ./scripts/test-install-agent-tooling.sh
162+
163+ - name : Smoke version targets
164+ shell : bash
165+ run : |
166+ set -euo pipefail
167+ ./scripts/test-version-targets.sh
168+
130169 - name : Smoke Chrome bridge entrypoint symlink
131170 shell : bash
132171 run : |
@@ -147,6 +186,44 @@ jobs:
147186 deva-smoke:ci \
148187 bash -lc 'link="/tmp/claude-mcp-browser-bridge-$(id -un)"; test -L "$link"; test "$(readlink "$link")" = "/deva-host-chrome-bridge"'
149188
189+ - name : Smoke tmux-bridge CLI surface
190+ shell : bash
191+ run : |
192+ set -euo pipefail
193+ # tmux-bridge is the layer-2 agent comms CLI vendored from smux.
194+ # We assert it's installed, executable, runs outside a tmux pane for
195+ # the version/help/id error paths, and that tmux itself is present
196+ # so a future operator can drive tmux-bridge against host tmux.
197+ docker run --rm deva-smoke:ci bash -lc '
198+ set -euo pipefail
199+ command -v tmux-bridge
200+ command -v tmux
201+ tmux-bridge version
202+ tmux-bridge --help | grep -q "cross-pane communication"
203+ # id requires $TMUX_PANE; outside tmux it must error cleanly.
204+ if tmux-bridge id 2>/dev/null; then
205+ echo "tmux-bridge id should fail outside a tmux pane" >&2
206+ exit 1
207+ fi
208+ # Ephemeral tmux server to prove list/name/read/type work end-to-end.
209+ sock="/tmp/tmux-smoke.sock"
210+ tmux -S "$sock" new-session -d -s smoke "sleep 30"
211+ export TMUX_BRIDGE_SOCKET="$sock"
212+ tmux-bridge list | tee /tmp/list.out
213+ grep -q "smoke:0" /tmp/list.out
214+ target="$(tmux -S "$sock" display-message -p "#{pane_id}")"
215+ tmux-bridge name "$target" smoke-worker
216+ tmux-bridge resolve smoke-worker
217+ tmux-bridge read "$target" 5 >/dev/null
218+ # read-guard: must read before type; second type without read must fail
219+ tmux-bridge type smoke-worker "echo hi"
220+ if tmux-bridge type smoke-worker "echo twice" 2>/dev/null; then
221+ echo "read-guard should have blocked second type without read" >&2
222+ exit 1
223+ fi
224+ tmux -S "$sock" kill-server
225+ '
226+
150227 docs :
151228 name : Docs Build
152229 runs-on : ubuntu-latest
0 commit comments