Skip to content

Commit aede372

Browse files
authored
fix: Normalize TMPDIR paths in wrapper (#6)
1 parent 06b2333 commit aede372

4 files changed

Lines changed: 144 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: oven-sh/setup-bun@v2
17+
with:
18+
bun-version: 1.3.11
19+
20+
- name: Install dependencies
21+
run: bun install
22+
23+
- name: Run tests
24+
run: bun test

bin/opencode-memory

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ AUTODREAM_STALE_LOCK_SECS=$((60 * 60))
177177

178178
WORKING_DIR="${OPENCODE_MEMORY_DIR:-$(pwd)}"
179179

180+
TMP_BASE_DIR="${TMPDIR:-/tmp}"
181+
while [ "$TMP_BASE_DIR" != "/" ] && [ "${TMP_BASE_DIR%/}" != "$TMP_BASE_DIR" ]; do
182+
TMP_BASE_DIR="${TMP_BASE_DIR%/}"
183+
done
184+
if [ -z "$TMP_BASE_DIR" ]; then
185+
TMP_BASE_DIR="/"
186+
fi
187+
180188
# Scope lock files at project root granularity (not per-subdirectory).
181189
PROJECT_SCOPE_DIR="$WORKING_DIR"
182190
if git -C "$WORKING_DIR" rev-parse --show-toplevel >/dev/null 2>&1; then
@@ -186,7 +194,7 @@ fi
186194
PROJECT_KEY="$(printf '%s' "$PROJECT_SCOPE_DIR" | cksum | awk '{print $1}')"
187195

188196
# Lock files (prevent concurrent work on the same project)
189-
LOCK_DIR="${TMPDIR:-/tmp}/opencode-memory-locks"
197+
LOCK_DIR="$TMP_BASE_DIR/opencode-memory-locks"
190198
mkdir -p "$LOCK_DIR"
191199
EXTRACT_LOCK_FILE="$LOCK_DIR/${PROJECT_KEY}.extract.lock"
192200

@@ -195,7 +203,7 @@ mkdir -p "$STATE_DIR"
195203
CONSOLIDATION_LOCK_FILE="$STATE_DIR/${PROJECT_KEY}.consolidate-lock"
196204

197205
# Logs
198-
LOG_DIR="${TMPDIR:-/tmp}/opencode-memory-logs"
206+
LOG_DIR="$TMP_BASE_DIR/opencode-memory-logs"
199207
mkdir -p "$LOG_DIR"
200208
TASK_LOG_PREFIX="$(date +%Y%m%d-%H%M%S)-${PROJECT_KEY}"
201209
EXTRACT_LOG_FILE="$LOG_DIR/extract-${TASK_LOG_PREFIX}.log"

test/github-actions-ci.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { describe, expect, test } from "bun:test"
2+
import { existsSync, readFileSync } from "fs"
3+
import { join } from "path"
4+
5+
const workflowPath = join(process.cwd(), ".github", "workflows", "ci.yml")
6+
7+
describe("GitHub Actions CI workflow", () => {
8+
test("defines pull request validation that installs dependencies and runs bun test", () => {
9+
expect(existsSync(workflowPath)).toBe(true)
10+
11+
const workflow = readFileSync(workflowPath, "utf-8")
12+
13+
expect(workflow).toContain("on:")
14+
expect(workflow).toContain("pull_request:")
15+
expect(workflow).toContain("push:")
16+
expect(workflow).toContain("branches: [main]")
17+
expect(workflow).toContain("oven-sh/setup-bun")
18+
expect(workflow).toContain("bun install")
19+
expect(workflow).toContain("bun test")
20+
})
21+
})

test/opencode-memory.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { afterEach, describe, expect, test } from "bun:test"
2+
import { chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs"
3+
import { tmpdir } from "os"
4+
import { join } from "path"
5+
import { spawnSync } from "child_process"
6+
7+
const tempRoots: string[] = []
8+
const scriptPath = join(process.cwd(), "bin", "opencode-memory")
9+
10+
function makeTempRoot(): string {
11+
const root = mkdtempSync(join(tmpdir(), "opencode-memory-test-"))
12+
tempRoots.push(root)
13+
return root
14+
}
15+
16+
function writeExecutable(filePath: string, content: string): void {
17+
writeFileSync(filePath, content, "utf-8")
18+
chmodSync(filePath, 0o755)
19+
}
20+
21+
afterEach(() => {
22+
while (tempRoots.length > 0) {
23+
const root = tempRoots.pop()
24+
if (root) {
25+
rmSync(root, { recursive: true, force: true })
26+
}
27+
}
28+
})
29+
30+
describe("opencode-memory wrapper", () => {
31+
test("normalizes TMPDIR before composing extraction log paths", () => {
32+
const root = makeTempRoot()
33+
const fakeBin = join(root, "bin")
34+
const homeDir = join(root, "home")
35+
const tmpDir = `${join(root, "tmp")}/`
36+
const claudeDir = join(root, "claude")
37+
38+
mkdirSync(fakeBin, { recursive: true })
39+
mkdirSync(homeDir, { recursive: true })
40+
mkdirSync(tmpDir, { recursive: true })
41+
mkdirSync(claudeDir, { recursive: true })
42+
43+
writeExecutable(
44+
join(fakeBin, "opencode"),
45+
`#!/usr/bin/env bash
46+
set -euo pipefail
47+
if [ "\${1:-}" = "session" ] && [ "\${2:-}" = "list" ]; then
48+
echo '[{"id":"ses_test_123","time":{"updated":1,"created":1}}]'
49+
exit 0
50+
fi
51+
if [ "\${1:-}" = "run" ]; then
52+
echo "extraction ok"
53+
exit 0
54+
fi
55+
if [ "\${1:-}" = "--help" ]; then
56+
echo "fake help"
57+
exit 0
58+
fi
59+
exit 0
60+
`,
61+
)
62+
63+
const result = spawnSync("bash", [scriptPath, "--help"], {
64+
cwd: root,
65+
encoding: "utf-8",
66+
env: {
67+
...process.env,
68+
PATH: `${fakeBin}:${process.env.PATH ?? ""}`,
69+
HOME: homeDir,
70+
TMPDIR: tmpDir,
71+
CLAUDE_CONFIG_DIR: claudeDir,
72+
OPENCODE_MEMORY_FOREGROUND: "1",
73+
OPENCODE_MEMORY_AUTODREAM: "0",
74+
},
75+
})
76+
77+
expect(result.status).toBe(0)
78+
expect(result.stderr).toContain("Extraction log: ")
79+
expect(result.stderr).not.toContain("//opencode-memory-logs")
80+
81+
const logPathMatch = result.stderr.match(/Extraction log: (.+)\n/)
82+
expect(logPathMatch).not.toBeNull()
83+
84+
const logPath = logPathMatch?.[1].trim() ?? ""
85+
expect(logPath.startsWith(join(root, "tmp", "opencode-memory-logs", "extract-"))).toBe(true)
86+
expect(existsSync(logPath)).toBe(true)
87+
expect(readFileSync(logPath, "utf-8")).toContain("extraction ok")
88+
})
89+
})

0 commit comments

Comments
 (0)