Skip to content

[Repo Assist] Add --root option to fsdocs watch for remote/proxy hosting#1089

Open
github-actions[bot] wants to merge 7 commits intomainfrom
repo-assist/fix-issue-924-watch-root-override-c4e35a7b2fb520aa
Open

[Repo Assist] Add --root option to fsdocs watch for remote/proxy hosting#1089
github-actions[bot] wants to merge 7 commits intomainfrom
repo-assist/fix-issue-924-watch-root-override-c4e35a7b2fb520aa

Conversation

@github-actions
Copy link
Contributor

🤖 This is an automated PR from Repo Assist.

Closes #924

Problem

fsdocs watch always forced root = (localhost/redacted) ignoring any --parameters rootthe user supplied. This makes generated pages broken when served in GitHub Codespaces (port-forwarding replaceslocalhost` with a cloud URL), behind a reverse proxy, or in any other non-localhost environment.

Fix

Added a --root option to fsdocs watch that overrides the watch-mode localhost default:

# Codespaces / reverse proxy — root-relative URLs work everywhere
fsdocs watch --root /

# Fully qualified remote URL
fsdocs watch --root (myforwardedhost.example.com/redacted)

When --root is not supplied, behaviour is unchanged: root defaults to `(localhost/redacted)

Changes

  • src/fsdocs-tool/BuildCommand.fs:
    • Added abstract root_override_option: string option (default None) to CoreBuildOptions
    • Added --root CLI option to WatchCommand, overriding root_override_option
    • Modified watch-mode root logic at line 1560 to use root_override_option when provided
  • RELEASE_NOTES.md: changelog entry under [Unreleased]

Test Status

  • dotnet build FSharp.Formatting.sln --configuration Release — succeeded (1 pre-existing FS0760 warning, unrelated)
  • dotnet test FSharp.Formatting.sln --configuration Release --no-build — all 499 tests pass (0 failures)
  • dotnet fantomas src/fsdocs-tool/BuildCommand.fs --check — no issues

Generated by Repo Assist for issue #924 ·

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

Closes #924

Previously fsdocs watch always forced root = http://localhost:<port>/,
ignoring any user-supplied root parameter. This makes the generated pages
unusable when served via GitHub Codespaces port-forwarding, a reverse proxy,
or any other non-localhost environment.

This PR adds:
- A --root option to WatchCommand exposing a user-specified root URL override
- An abstract root_override_option on CoreBuildOptions (default None)
- Modified watch-mode root logic: uses the --root value when provided,
  otherwise falls back to http://localhost:<port>/ as before

Usage:
  fsdocs watch --root /                       # root-relative URLs
  fsdocs watch --root https://example.com/docs/   # absolute remote URL

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nojaf
Copy link
Collaborator

nojaf commented Mar 12, 2026

/repo-assist sprintf "http://localhost:%d/" this.port_option might not be what the url wants. Something people need 127.0.0.1 or 0.0.0.0? What do we do with this localhost string?

… hardcoded localhost

The injected WebSocket URI was hardcoded as ws://localhost:<port>/websocket,
which breaks in GitHub Codespaces, behind reverse proxies, and over HTTPS.
Now uses window.location.host (which includes the correct hostname and port)
with the appropriate ws:/wss: protocol to match the page's scheme.

Removes the now-unused port parameter from generateWatchScript.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

Commit pushed: a9ad07a

Generated by Repo Assist

@github-actions
Copy link
Contributor Author

🤖 Repo Assist here.

Great catch, @nojaf! There are actually three distinct localhost strings in play — let me clarify each:

1. userRoot — the root URL baked into generated HTML links

sprintf "(localhost/redacted) this.port_option

This is the one the --root option already overrides. The localhost default is fine for local development; users who need a different URL (Codespaces, proxy) pass --root / or --root https://…. ✅

2. WebSocket hot-reload URL — injected into every page

var wsUri = "ws://localhost:\{\{PORT}}/websocket";

This was the real problem. In Codespaces or behind a proxy, the browser loads the page from a non-localhost origin and cannot connect back to ws://localhost:… — hot reload silently breaks. I've just pushed a fix: it now uses window.location.host (which includes the correct hostname + port) and picks ws: or wss: to match the page's protocol:

var wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
var wsUri = wsProtocol + "//" + window.location.host + "/websocket";

This works correctly for local dev, Codespaces, and any proxied setup. ✅

3. Server bind address
The Suave server binds to 127.0.0.1 (Suave's default). In GitHub Codespaces this is fine — Codespaces tunnels traffic to 127.0.0.1 within the container. In Docker with published ports you'd need 0.0.0.0, but that's a separate concern and a bigger security trade-off. I've left it as-is for now; we can add a --host option if that need is confirmed.

Summary: the --root option handles doc links; the WebSocket fix (just pushed) handles hot-reload; the server bind address is fine for the common cases.

Generated by Repo Assist for issue #1089 ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

@dsyme dsyme marked this pull request as ready for review March 13, 2026 23:49
@nojaf
Copy link
Collaborator

nojaf commented Mar 16, 2026

/repo-assist When can this ever be https? var wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:"; we don't serve any content in watch mode with any ssl certs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable watch server from arbitrary host

2 participants