sotashimozono_obsidian-remo.../plugin/package.json
Souta da3a2e9ffd feat(test): docker sshd integration test environment (Tier B-1+B-3, 0.4.0)
All existing tests mock ssh2, so the actual auth + SFTP channel
code has been entirely untested up to now. Three real-world bugs
in PRs #49 (ssh_config) and #50 (jump host) — neither caught by
mocks — confirmed it was time to wire up real-network tests.

This PR adds a reproducible docker sshd container, a vitest
integration suite that talks to it via the actual SftpClient, and
a CI job that brings the container up, runs the suite, and tears
it down.

## Components

- `docker/test-sshd/Dockerfile` — Ubuntu 22.04 + openssh-server.
  Pre-creates a `tester` user (UID 1000) with `vault/` in their
  home, pubkey-only auth, `StrictModes no` so a bind-mounted
  authorized_keys works regardless of host UID.
- `docker-compose.yml` (repo root) — single `sshd` service on
  127.0.0.1:2222, bind-mounts the public key + a host-side
  `docker/test-vault/` directory, healthcheck on port 22.
- `docker/test-vault/` — bind-mounted vault root the test writes
  into. Contents are gitignored aside from a README.
- `docker/keys/` — gitignored; populated on first run.
- `scripts/start-test-sshd.mjs` — generates an ed25519 keypair on
  first run (otherwise reuses), `docker compose up -d --build`,
  polls `Health.Status` until healthy. Idempotent.
- `scripts/stop-test-sshd.mjs` — `docker compose down -v`.
- `vitest.integration.config.ts` — separate config that includes
  `tests/integration/**` and serialises files (no fileParallelism)
  so they don't fight over the single sshd. Default
  `vitest.config.ts` excludes the integration dir so `npm test`
  stays fast.
- `tests/integration/ssh.integration.test.ts` — opens a real SSH
  session with the generated keypair and exercises list / read /
  write (small text + 64KB binary) / stat / exists / remove
  through the actual SftpClient. Each run uses a unique subdir
  under `/home/tester/vault` so leftovers don't collide.
- `package.json` scripts: `sshd:start`, `sshd:stop`,
  `test:integration`. `npm test` is unchanged.
- `.github/workflows/integration.yml` — separate from `ci.yml` so
  the integration run doesn't gate other PR signals. Brings the
  container up before the test step, tears it down in a
  finally-style step, uploads `docker logs` as an artefact on
  failure.

## Local usage

```
cd plugin
npm run sshd:start
npm run test:integration
npm run sshd:stop
```

Requires Docker (Desktop or daemon) on PATH. Unit tests
(`npm test`) work without Docker.

## Out of scope (B-2 / B-4)

- ProxyJump / two-container bastion → target topology
- Daemon (obsidian-remote-server) auto-deploy + RPC handshake
  end-to-end against the container
Both queued for a follow-up PR once this base lands.

## Version

0.3.2 → 0.4.0 (new feature surface, minor bump).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:05:55 +09:00

40 lines
1.4 KiB
JSON

{
"name": "obsidian-remote-ssh",
"version": "0.4.0",
"description": "VS Code Remote SSH-like experience for Obsidian",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "node esbuild.config.mjs production",
"dev:install": "node scripts/dev-install.mjs",
"build:install": "node esbuild.config.mjs production && node scripts/dev-install.mjs",
"build:server": "node scripts/build-server.mjs",
"build:full": "node scripts/build-server.mjs && node esbuild.config.mjs production && node scripts/dev-install.mjs",
"cdp:tail": "node scripts/cdp-tail.mjs",
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"test:integration": "vitest run --config vitest.integration.config.ts",
"sshd:start": "node scripts/start-test-sshd.mjs",
"sshd:stop": "node scripts/stop-test-sshd.mjs",
"lint": "eslint src --ext .ts",
"version": "node scripts/bump-version.mjs && git add manifest.json versions.json"
},
"keywords": ["obsidian", "ssh", "sftp", "remote"],
"author": "",
"license": "MIT",
"dependencies": {
"ssh2": "^1.17.0"
},
"devDependencies": {
"@types/node": "^25.6.0",
"@types/ssh2": "^1.11.19",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"esbuild": "^0.28.0",
"eslint": "^10.2.1",
"obsidian": "latest",
"typescript": "^6.0.3",
"vitest": "^4.1.5",
"@vitest/coverage-v8": "^4.1.5"
}
}