ACP readiness probe returned 000 for the full retry window on
xworkmate-bridge-ubuntu-26 (nothing listening = adapter crash-loop), but the
play aborted at the probe so the real cause never reached the CI log.
- systemd unit: add Environment=PATH ({{ acp_opencode_path }}, parity with the
launchd plist) so the lazily-spawned opencode/node CLI resolves; replace the
hardcoded --opencode-bin /usr/bin/opencode with {{ acp_opencode_binary_path }}
({{ npm_global_bin }}/opencode), matching the gemini/codex roles and macOS.
- validate.yml: wrap the readiness probe in block/rescue that dumps systemctl
status + journalctl on failure, so the adapter crash reason is visible.
- fix latent undefined var in the summary (acp_opencode_adapter_http ->
acp_opencode_adapter_probe), which would have errored once the endpoint came up.
Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
96 lines
4.1 KiB
YAML
96 lines
4.1 KiB
YAML
---
|
||
- name: Validate Caddy configuration
|
||
ansible.builtin.command: caddy validate --config "{{ acp_opencode_caddyfile_path }}"
|
||
changed_when: false
|
||
when: acp_opencode_manage_caddy | bool
|
||
|
||
- name: Check OpenCode ACP listener
|
||
ansible.builtin.shell: |
|
||
if command -v ss >/dev/null 2>&1; then
|
||
ss -ltnp
|
||
else
|
||
lsof -nP -iTCP -sTCP:LISTEN 2>/dev/null || true
|
||
fi
|
||
args:
|
||
executable: /bin/bash
|
||
register: acp_opencode_ss
|
||
changed_when: false
|
||
failed_when: false
|
||
|
||
# 用 curl 重试循环替代 uri:服务刚 (重)启时 adapter 会先 accept TCP 但短时间内不
|
||
# 应答(读挂起),而 uri 默认 30s 超时 + retries/until 在连接超时上不可靠循环(实测
|
||
# 仅试一次即失败)。每次 5s 上限、真重试,给冷启动足够时间(adapter 就绪后 ~4ms 回 200)。
|
||
# 包在 block/rescue:探针失败时把 systemctl status + journalctl 打到 CI 日志,
|
||
# 否则 play 在此中止,看不到 adapter 进程真正的崩溃原因(如 last code 000)。
|
||
- name: Validate OpenCode local ACP endpoint
|
||
block:
|
||
- name: Validate OpenCode local ACP endpoint (readiness retry)
|
||
ansible.builtin.shell: |
|
||
set -eu
|
||
url="http://{{ acp_opencode_listen_host }}:{{ acp_opencode_listen_port }}/acp/rpc"
|
||
body='{"jsonrpc":"2.0","id":1,"method":"acp.capabilities","params":{}}'
|
||
code=""
|
||
for i in $(seq 1 30); do
|
||
code="$(curl -s -m 5 -o /dev/null -w '%{http_code}' -X POST "$url" \
|
||
-H 'Content-Type: application/json' -d "$body" 2>/dev/null || true)"
|
||
if [ "$code" = "200" ]; then
|
||
echo "OpenCode ACP endpoint ready after ${i} attempt(s)"
|
||
exit 0
|
||
fi
|
||
sleep 2
|
||
done
|
||
echo "OpenCode ACP endpoint ${url} not ready after retries (last code: ${code:-none})" >&2
|
||
exit 1
|
||
args:
|
||
executable: /bin/bash
|
||
changed_when: false
|
||
register: acp_opencode_adapter_probe
|
||
rescue:
|
||
- name: Capture OpenCode ACP service status on failure
|
||
ansible.builtin.command: systemctl status "{{ acp_opencode_service_name }}" --no-pager --full
|
||
register: acp_opencode_status_fail
|
||
changed_when: false
|
||
failed_when: false
|
||
when: ansible_os_family != 'Darwin'
|
||
|
||
- name: Capture recent OpenCode ACP service logs on failure
|
||
ansible.builtin.command: journalctl -u "{{ acp_opencode_service_name }}" -n 80 --no-pager
|
||
register: acp_opencode_journal_fail
|
||
changed_when: false
|
||
failed_when: false
|
||
when: ansible_os_family != 'Darwin'
|
||
|
||
- name: Show OpenCode ACP failure diagnostics
|
||
ansible.builtin.debug:
|
||
msg:
|
||
- "Probe stderr: {{ acp_opencode_adapter_probe.stderr | default('N/A') }}"
|
||
- "Listeners: {{ acp_opencode_ss.stdout | default('N/A') }}"
|
||
- "Service status: {{ acp_opencode_status_fail.stdout | default('N/A') }}"
|
||
- "Recent logs: {{ acp_opencode_journal_fail.stdout | default('N/A') }}"
|
||
|
||
- name: Fail after emitting OpenCode ACP diagnostics
|
||
ansible.builtin.fail:
|
||
msg: >-
|
||
OpenCode ACP endpoint
|
||
{{ acp_opencode_listen_host }}:{{ acp_opencode_listen_port }} did not
|
||
become ready. See the diagnostics above (service status + journal) for
|
||
the adapter crash cause.
|
||
|
||
- name: Show OpenCode ACP status
|
||
ansible.builtin.command: systemctl status "{{ acp_opencode_service_name }}" --no-pager
|
||
register: acp_opencode_status
|
||
changed_when: false
|
||
failed_when: false
|
||
when: ansible_os_family != 'Darwin'
|
||
|
||
- name: Show OpenCode ACP validation summary
|
||
ansible.builtin.debug:
|
||
msg:
|
||
- "OpenCode public base URL: {{ acp_opencode_public_base_url }}"
|
||
- "Preferred WebSocket endpoint: {{ acp_opencode_public_base_url }}/acp"
|
||
- "Compatibility HTTP RPC endpoint: {{ acp_opencode_public_base_url }}/acp/rpc"
|
||
- "OpenCode ACP adapter listener: {{ acp_opencode_listen_host }}:{{ acp_opencode_listen_port }}"
|
||
- "Readiness probe: {{ acp_opencode_adapter_probe.stdout | default('N/A') }}"
|
||
- "Service: {{ acp_opencode_status.stdout | default('N/A') }}"
|
||
- "Socket: {{ acp_opencode_ss.stdout | default('N/A') }}"
|