Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6af975a
feat: USBキーボード入力をBLE HIDへ転送
RarkHopper May 15, 2026
911324d
docs: USB入力中継のセットアップ手順を更新
RarkHopper May 15, 2026
a751d80
feat: HID入力をhidraw report転送へ切り替え
RarkHopper May 15, 2026
e6111ec
docs: hidrawデバイス設定手順を反映
RarkHopper May 15, 2026
597fe14
fix: hidraw descriptor size取得を正す
RarkHopper May 17, 2026
b2f11c9
fix: BLE広告のdiscoverable指定を反映
RarkHopper May 17, 2026
51ea4c1
fix: Report ID付きkeyboard reportをBoot Inputへ通知
RarkHopper May 17, 2026
ac3fd35
test: 仮想HCI接続proxyを追加
RarkHopper May 17, 2026
bbe9996
test: BlueZのpairing helperを追加
RarkHopper May 17, 2026
7fcc7ff
test: hidraw入力を作るCUSE helperを追加
RarkHopper May 17, 2026
b3ee4f1
test: VagrantのBLE HID検証VMを追加
RarkHopper May 17, 2026
6b5a618
test: BLE HID E2Eをmakeから実行可能にする
RarkHopper May 17, 2026
85302f8
chore: Docker ComposeのE2E定義を削除
RarkHopper May 17, 2026
9f18907
docs: 仮想BLE HID検証手順を追加
RarkHopper May 17, 2026
11341ad
chore: internal docsのignore方針を固定
RarkHopper May 17, 2026
f12826c
ci: Go以外の検査もCIで実行する
RarkHopper May 17, 2026
083977c
fix: HID report処理の異常系を明示する
RarkHopper May 17, 2026
569a12c
fix: E2E補助処理の停止と送信を安定させる
RarkHopper May 17, 2026
4dbe592
chore: Go lint規則を強める
RarkHopper May 17, 2026
3c18afe
fix: Linux HIDraw読み取りのlint違反を直す
RarkHopper May 17, 2026
3fb7784
build: Python toolsをuv管理と型検査に移す
RarkHopper May 17, 2026
c50ee20
docs: 開発に必要なDBus依存を明記する
RarkHopper May 17, 2026
00c587e
fix: E2Eスクリプトのshellcheck違反を直す
RarkHopper May 17, 2026
350d230
build: PyGObjectのビルド依存を明示する
RarkHopper May 17, 2026
0733b32
chore: Pythonキャッシュ無視をtoolsへ寄せる
RarkHopper May 17, 2026
4d2d0bb
build: Python toolsの型検査を実体化する
RarkHopper May 17, 2026
cbc8c21
docs: toolsの開発手順を分けて書く
RarkHopper May 17, 2026
cda8f71
build: E2E用UTM providerをsubmoduleで固定する
RarkHopper May 17, 2026
c53b3be
fix: E2EのBlueZ起動待ちを安定させる
RarkHopper May 17, 2026
2879834
fix: E2E初回起動のHCI待ちを安定させる
RarkHopper May 17, 2026
3762e69
build: PackerでE2E用boxを定義する
RarkHopper May 17, 2026
4d3e3b4
build: Packer UTM pluginの導入手順を追加する
RarkHopper May 17, 2026
bf65caf
ci: Packer設定を検証する
RarkHopper May 17, 2026
98d3103
fix: macOSでCUSE確認を実行しない
RarkHopper May 17, 2026
0c04975
build: E2E用boxをVagrantへ登録する
RarkHopper May 17, 2026
743d2d5
refactor: VagrantfileをE2E用box前提にする
RarkHopper May 17, 2026
edcea81
refactor: HID E2Eの起動手順を分ける
RarkHopper May 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .dockerignore

This file was deleted.

29 changes: 28 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
check:
name: Check
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- name: Checkout
Expand All @@ -24,5 +25,31 @@ jobs:
go.mod
go.sum

- name: Setup uv
uses: astral-sh/setup-uv@v8.1.0
with:
version: "0.9.22"
enable-cache: true

- name: Setup Packer
uses: hashicorp/setup-packer@v3.1.0
with:
version: "1.15.3"

- name: Install check dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential \
gobject-introspection \
libcairo2-dev \
libdbus-1-dev \
libfuse3-dev \
libgirepository1.0-dev \
libgirepository-2.0-dev \
pkg-config \
ruby \
shellcheck

- name: Check
run: make check
run: make ci
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/bin/
/dist/
/tmp/
/packer_cache/

*.out
*.test
Expand All @@ -9,3 +10,4 @@ coverage.out
.DS_Store
.idea/
.vscode/
.vagrant/
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "third_party/vagrant_utm"]
path = third_party/vagrant_utm
url = https://github.com/RarkHopper/vagrant_utm.git
branch = fix/remove-applescript-continuation-chars
97 changes: 97 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,104 @@ version: "2"

linters:
default: standard
enable:
# Input hygiene: catch confusing Unicode control bytes, stale loop copies,
# suspicious durations, unsafe type assertions, and wasted assignments.
- bidichk
- copyloopvar
- durationcheck
- forcetypeassert
- intrange
- mirror
- wastedassign

# Error handling: prefer wrapped errors, Go 1.13 error checks, static
# sentinel errors, and safer JSON error handling.
- err113
- errchkjson
- errname
- errorlint
- nilerr
- nilnil
- wrapcheck

# Security and resource handling: catch unchecked response bodies and
# common security mistakes in production code.
- bodyclose
- gosec

# Static bug checks: keep the standard analyzer set plus extra vet checks.
- govet
- ineffassign
- staticcheck
- unused

# Code quality: remove redundant conversions, catch misspellings, enforce
# useful nolint comments, and find simple allocation and stdlib cleanups.
- exptostd
- gocritic
- makezero
- misspell
- nolintlint
- prealloc
- predeclared
- revive
- unconvert
- unparam
- usestdlibvars

# Coverage of domain-like branches: useful for enum-style switches even in
# a small command line application.
- exhaustive

# Complexity: keep very complex functions visible without forcing a large
# refactor of existing command dispatch in this PR.
- cyclop
- gocognit

settings:
cyclop:
max-complexity: 30
package-average: 10
gocognit:
min-complexity: 45
govet:
enable:
- nilness
- shadow
misspell:
locale: US
nolintlint:
allow-unused: false
require-explanation: true
require-specific: true
revive:
enable-default-rules: true
rules:
# The repository already has a compact internal package style. Requiring
# comments for every exported test helper and DBus method would add
# noise without catching behavior bugs.
- name: exported
disabled: true
- name: package-comments
disabled: true
- name: unused-parameter
- name: unused-receiver

exclusions:
generated: strict
presets:
- comments
- common-false-positives
- std-error-handling
rules:
# Test fixtures intentionally use broad file permissions and temporary
# paths; production files still go through gosec.
- path: _test\.go
linters:
- gosec

formatters:
enable:
# Keep the existing formatter gate stricter than gofmt.
- gofumpt
104 changes: 102 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
.PHONY: build fmt lint lint-config test check
.PHONY: all clean build fmt fmt-check lint lint-config vet test race-test check mod-check script-check python-fmt python-check python-runtime-check packer-check vagrant-check packer-utm-plugin vagrant-utm-plugin e2e-box cuse-check ci e2e

GOLANGCI_LINT := go tool golangci-lint
PACKER ?= packer
UTM_APP ?= /Applications/UTM.app
QEMU_IMG ?= $(shell find -L "$(UTM_APP)" -path '*/qemu-img.framework/Versions/*/qemu-img' -type f 2>/dev/null | head -n 1)
VAGRANT ?= vagrant
LOCAL_GOOS ?= $(shell go env GOOS)
LOCAL_GOARCH ?= $(shell go env GOARCH)
RPI_GOOS ?= linux
RPI_GOARCH ?= arm64
SHELLCHECK ?= shellcheck
UV ?= uv
TOOLS_PYTHON ?= 3.12
TOOLS_DIR := tools
TOOLS_UV := $(UV) --project $(TOOLS_DIR) --directory $(TOOLS_DIR)
SHELL_SCRIPTS := scripts/hid-e2e.sh scripts/install-packer-utm-plugin.sh scripts/install-vagrant-utm-plugin.sh scripts/provision-e2e-vm.sh
PYTHON_TOOLS := hci-proxy.py bluez-agent.py bluez-pair.py
PYTHON_SOURCES := $(PYTHON_TOOLS) lib stubs
CUSE_TOOL := tools/hidraw-cuse.c
E2E_BOX_NAME ?= rpi-keyboard-switcher/e2e-ubuntu-24.04-arm64
E2E_BOX_FILE ?= dist/boxes/rpi-keyboard-switcher-e2e-utm.box
E2E_BOX_STAMP ?= dist/boxes/.rpi-keyboard-switcher-e2e-utm.added
E2E_BOX_INPUTS := packer/e2e-utm.pkr.hcl packer/cloud-init/meta-data packer/cloud-init/network-config packer/cloud-init/user-data scripts/provision-e2e-vm.sh tools/pyproject.toml tools/uv.lock
PACKER_UTM_PLUGIN_STAMP ?= dist/packer/.packer-utm-plugin-v4.0.0.installed

all: build

clean:
rm -rf dist tools/.mypy_cache tools/.ruff_cache tools/.venv tools/__pycache__ tools/lib/__pycache__

build:
mkdir -p dist
Expand All @@ -14,14 +37,91 @@ build:

fmt:
$(GOLANGCI_LINT) fmt
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) ruff format $(PYTHON_SOURCES)

fmt-check:
$(GOLANGCI_LINT) fmt --diff
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) ruff format --check $(PYTHON_SOURCES)

lint:
$(GOLANGCI_LINT) run ./...

lint-config:
$(GOLANGCI_LINT) config verify

vet:
go vet ./...

test:
go test ./...

check: lint-config lint test
race-test:
go test -race ./...

check: lint-config fmt-check lint vet test python-check

mod-check:
go mod tidy
git diff --exit-code -- go.mod go.sum

script-check:
bash -n $(SHELL_SCRIPTS)
$(SHELLCHECK) $(SHELL_SCRIPTS)

python-fmt:
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) ruff format $(PYTHON_SOURCES)

python-check:
$(TOOLS_UV) lock --check --python $(TOOLS_PYTHON) --managed-python
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) ruff check $(PYTHON_SOURCES)
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) mypy $(PYTHON_SOURCES)
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) pyright
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) python -m compileall -q $(PYTHON_SOURCES)

python-runtime-check:
$(TOOLS_UV) run --locked --managed-python --python $(TOOLS_PYTHON) --extra runtime --no-dev python -c 'import dbus; import gi; from gi.repository import GLib; print(GLib.MainLoop)'

packer-check:
$(PACKER) fmt -check packer
$(PACKER) init packer
$(PACKER) validate packer

vagrant-check:
ruby -c Vagrantfile

$(PACKER_UTM_PLUGIN_STAMP): scripts/install-packer-utm-plugin.sh
PACKER=$(PACKER) scripts/install-packer-utm-plugin.sh
mkdir -p $(dir $@)
touch $@

packer-utm-plugin: $(PACKER_UTM_PLUGIN_STAMP)

vagrant-utm-plugin:
VAGRANT=$(VAGRANT) scripts/install-vagrant-utm-plugin.sh

$(E2E_BOX_FILE): $(E2E_BOX_INPUTS)
mkdir -p $(dir $@)
$(PACKER) init packer
PACKER=$(PACKER) scripts/install-packer-utm-plugin.sh
PATH="$(dir $(QEMU_IMG)):$$PATH" $(PACKER) build -force packer/e2e-utm.pkr.hcl

$(E2E_BOX_STAMP): $(E2E_BOX_FILE)
$(VAGRANT) box add --force --name $(E2E_BOX_NAME) $(E2E_BOX_FILE)
mkdir -p $(dir $@)
touch $@

e2e-box: $(E2E_BOX_STAMP)

ifeq ($(LOCAL_GOOS),linux)
cuse-check:
pkg-config --exists fuse3
cc -Wall -Wextra -fsyntax-only $$(pkg-config --cflags fuse3) $(CUSE_TOOL)
else
cuse-check:
@echo "skip cuse-check: fuse3 CUSE check requires Linux ($(LOCAL_GOOS))"
endif

ci: check race-test build mod-check script-check python-runtime-check packer-check vagrant-check cuse-check

e2e: vagrant-utm-plugin e2e-box
VAGRANT=$(VAGRANT) scripts/hid-e2e.sh
Loading
Loading