Conversation
There was a problem hiding this comment.
Pull request overview
This PR changes how opencode-server.sh chooses where to persist server state, preferring a repo-local .opencode-server/ directory when run inside a git repository (and auto-ignoring it), while keeping ~/.config/ as the fallback outside git repos. It also makes authentication messaging/provider handling more generic, and expands the devcontainer test suite to validate the new storage behavior.
Changes:
- Add git-repo detection to store PID/logs/certs/password/Caddyfile under
<repo>/.opencode-server/and append it to.git/info/exclude. - Make authentication checks and messages provider-agnostic and validate auth via “file exists + non-empty”.
- Expand
tests/test-devcontainer.shwith a set of git-repo-specific data-directory tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
opencode-server.sh |
Introduces repo-local data directory logic and provider-agnostic authentication prompts/checks. |
tests/test-devcontainer.sh |
Adds coverage for repo-local data storage and git ignore behavior. |
README.md |
Documents the new data storage behavior and updates authentication wording. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Locally ignore the data directory so it's never committed | ||
| EXCLUDE_FILE="$GIT_ROOT/.git/info/exclude" | ||
| mkdir -p "$(dirname "$EXCLUDE_FILE")" | ||
| if ! grep -qxF '.opencode-server' "$EXCLUDE_FILE" 2>/dev/null; then | ||
| echo '.opencode-server' >> "$EXCLUDE_FILE" | ||
| fi |
There was a problem hiding this comment.
Using "$GIT_ROOT/.git/info/exclude" assumes ".git" is a directory, but in git worktrees/submodules it can be a file pointing elsewhere; in that case "mkdir -p $GIT_ROOT/.git/info" will fail and the ignore entry won’t be applied. Prefer resolving the exclude path via git itself (e.g., git -C "$GIT_ROOT" rev-parse --git-path info/exclude) and then append/check that file.
| # Check if authenticated (skip if --skip-auth or --stop) | ||
| if [ "$SKIP_AUTH" = "false" ] && [ "$1" != "--stop" ]; then | ||
| AUTH_FILE="$HOME/.local/share/opencode/auth.json" |
There was a problem hiding this comment.
The auth gate is skipped only when --stop is the first argument ($1). If --stop is provided after other flags, the script may incorrectly prompt for auth and the stop handler won’t run. Consider parsing --stop the same way as --skip-auth (scan all args) so stop works regardless of argument order.
| echo "=== Test 16: .git/info/exclude contains .opencode-server ===" | ||
| EXCLUDE_CONTENT=$(docker exec "$CONTAINER_NAME" bash -c 'cat /tmp/test-repo/.git/info/exclude' 2>/dev/null) | ||
| if echo "$EXCLUDE_CONTENT" | grep -qxF '.opencode-server'; then | ||
| pass ".opencode-server is in .git/info/exclude" | ||
| else | ||
| fail ".opencode-server not found in .git/info/exclude" | ||
| echo "Exclude file contents: $EXCLUDE_CONTENT" | ||
| fi |
There was a problem hiding this comment.
Because this test script runs with set -e, capturing exclude contents via EXCLUDE_CONTENT=$(docker exec ... cat ...) will abort the entire suite if cat fails (e.g., if the exclude file wasn’t created). To ensure the test reports a clean failure instead of exiting early, guard the command substitution (e.g., ... || true) and then assert on the result/file existence explicitly.
| echo "=== Test 17: Password file is inside .opencode-server/ ===" | ||
| GIT_PASSWORD=$(docker exec "$CONTAINER_NAME" bash -c 'cat /tmp/test-repo/.opencode-server/opencode-server-local' 2>/dev/null) | ||
| if [ -n "$GIT_PASSWORD" ]; then | ||
| pass "Password file found in .opencode-server/: ${GIT_PASSWORD:0:8}..." | ||
| else | ||
| fail "Password file not found in .opencode-server/" | ||
| fi |
There was a problem hiding this comment.
Same set -e issue here: GIT_PASSWORD=$(docker exec ... cat ...) will cause the whole test run to exit if the password file is missing/unreadable, instead of recording a failed assertion. Consider guarding the substitution (|| true) or checking file existence first, then reading it.
| if git rev-parse --show-toplevel &>/dev/null; then | ||
| GIT_ROOT="$(git rev-parse --show-toplevel)" | ||
| DATA_DIR="$GIT_ROOT/.opencode-server" | ||
| mkdir -p "$DATA_DIR" | ||
|
|
There was a problem hiding this comment.
When running inside a git repo, the script unconditionally switches to "$GIT_ROOT/.opencode-server" without checking whether the repo root is writable. If the workspace/repo is mounted read-only (common in some containers/CI), subsequent writes (PID/logs/certs/password) will fail and the server start/stop flow will break. Consider falling back to "$HOME/.config" when creating/writing "$DATA_DIR" fails (e.g., check mkdir exit status and/or a simple write test).
This pull request updates the way OpenCode server stores its data files, introducing a new behavior where, if the server is run inside a git repository, all persistent data is stored in a
.opencode-server/directory at the repo root (which is automatically git-ignored). Otherwise, it defaults to the user's config directory as before. The documentation and authentication messages have been updated for clarity and provider-agnostic language. Tests have been added to verify the new data storage logic.The most important changes are:
Data storage location improvements:
opencode-server.shscript now detects if it is running inside a git repository and, if so, stores all persistent data (password, PID file, certificates, logs, Caddyfile) in a.opencode-server/directory at the repo root. This directory is automatically added to.git/info/excludeto prevent accidental commits. If not in a git repo, data is stored in~/.config/as before.README.mdhas been updated to document the new data storage behavior, including the use of<data-dir>and a new "Data Storage" section explaining the logic. [1] [2]Authentication flow updates:
Testing enhancements:
test-devcontainer.sh) has been expanded with a series of tests to verify the new data directory logic, including checks for file locations, git ignore behavior, data persistence, and correct operation both inside and outside git repositories.