Windows 설치 화면을 사람이 클릭할 수 없으므로 전 과정을 무인으로 짰다. autounattend.xml 이 설치와 OOBE 를 끝내고, provision.ps1 이 virtio 드라이버를 오프라인으로 넣어 네트워크를 살리고, 상주 agent.ps1 이 호스트 HTTP 에서 stage2.ps1 을 받아 Git/pwsh7/Python/Node/CMake/act_runner 를 설치한다. 설치 내용을 ISO 에 박지 않고 호스트가 HTTP 로 내려주는 구조로 한 이유는 ISO 를 한 번 구우면 못 고쳐서, 한 줄 고칠 때마다 Windows 재설치가 되기 때문이다. stage2.ps1 만 고치면 게스트가 20초 안에 반영한다. - 시스템 디스크는 SATA. virtio-blk 로 하면 Setup 이 디스크를 못 봐서 WinPE 드라이버 주입이 필요해진다 - VM 은 systemd --user 트랜지언트 유닛으로 띄워 봇 cgroup 밖에 둔다 (MemoryHigh=16G 안에 8G VM 이 들어가면 봇이 OOM 으로 죽는 전례) - Node 포함. act_runner host 모드가 JS 액션을 PATH 의 node 로 돌린다
29 lines
1.2 KiB
Bash
Executable File
29 lines
1.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# VM 화면의 좌표를 클릭한다 (usb-tablet 절대좌표).
|
|
# 사용법: ./click.sh <x> <y> [화면폭 화면높이] 기본 1280x800
|
|
set -euo pipefail
|
|
python3 - "$@" <<'PY'
|
|
import json, socket, sys, time
|
|
x, y = int(sys.argv[1]), int(sys.argv[2])
|
|
W = int(sys.argv[3]) if len(sys.argv) > 3 else 1280
|
|
H = int(sys.argv[4]) if len(sys.argv) > 4 else 800
|
|
s = socket.socket(socket.AF_UNIX); s.settimeout(20)
|
|
s.connect("/home/claude/win-ci/qmp.sock"); f = s.makefile("rwb"); f.readline()
|
|
def cmd(o):
|
|
f.write((json.dumps(o)+"\n").encode()); f.flush()
|
|
while True:
|
|
m = json.loads(f.readline())
|
|
if "return" in m or "error" in m: return m
|
|
cmd({"execute": "qmp_capabilities"})
|
|
ax, ay = int(x / W * 32767), int(y / H * 32767)
|
|
ev = [{"type": "abs", "data": {"axis": "x", "value": ax}},
|
|
{"type": "abs", "data": {"axis": "y", "value": ay}}]
|
|
print(cmd({"execute": "input-send-event", "arguments": {"events": ev}}))
|
|
time.sleep(0.3)
|
|
print(cmd({"execute": "input-send-event", "arguments": {"events": [
|
|
{"type": "btn", "data": {"down": True, "button": "left"}}]}}))
|
|
time.sleep(0.15)
|
|
print(cmd({"execute": "input-send-event", "arguments": {"events": [
|
|
{"type": "btn", "data": {"down": False, "button": "left"}}]}}))
|
|
PY
|