Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 28 additions & 0 deletions reboot/cli/commands/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pathlib import Path
from reboot.aio.backoff import Backoff
from reboot.cli.commands.dev import (
DEFAULT_LOCAL_ENVOY_PORT,
_dashboard_reachable,
_open_on_restart,
_viewers,
Expand All @@ -29,6 +30,7 @@
DEFAULT_DASHBOARD_PORT,
ENVVAR_RBT_API_DIRECTORY,
ENVVAR_RBT_APPLICATION,
ENVVAR_RBT_APPLICATION_URL,
ENVVAR_RBT_GENERATED_DIRECTORY,
)
from reboot.settings import (
Expand Down Expand Up @@ -121,6 +123,25 @@ def _application(parser: ArgumentParser) -> Optional[str]:
return None


def _application_url(parser: ArgumentParser) -> str:
"""Returns where the developer's application serves, which is the
port they tell `rbt dev run` to serve on, and `rbt dev run`'s
default port when they tell it none.

Read rather than asked for again, for the same reason as the
application. Only a plain `dev run --port=` line counts: a line
written for a config, `dev run:hmr --port=`, applies only when
that config is asked for, which nothing here knows.
"""
port = DEFAULT_LOCAL_ENVOY_PORT
for argument in parser.dot_rc_arguments('dev run'):
name, separator, value = argument.partition('=')
if name == '--port' and separator == '=':
port = int(value)

return f'http://localhost:{port}'


def _generated_directory(parser: ArgumentParser) -> Optional[str]:
"""Returns the directory `rbt generate` writes Python code into,
which is where its `--python=` flag points, and `None` when it
Expand All @@ -145,6 +166,7 @@ def _dashboard_env(
port: int,
api_directory: str,
application: Optional[str],
application_url: str,
generated_directory: Optional[str],
) -> dict[str, str]:
"""The environment for the dashboard application.
Expand Down Expand Up @@ -204,6 +226,11 @@ def _dashboard_env(
if application is not None:
composed[ENVVAR_RBT_APPLICATION] = application

# Where the developer's application serves, for the page to read
# its states and tasks from. Always set: the application has a
# port whether or not it is running.
composed[ENVVAR_RBT_APPLICATION_URL] = application_url

# Where the developer's generated Python is, spelled the same way
# and for the same reason. Left out when the developer named no
# `--python` directory, which is what tells the dashboard there is
Expand Down Expand Up @@ -366,6 +393,7 @@ async def dashboard(
port=port,
api_directory=_api_directory(parser),
application=_application(parser),
application_url=_application_url(parser),
generated_directory=_generated_directory(parser),
)

Expand Down
12 changes: 12 additions & 0 deletions reboot/dashboard/backend/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
# logs, and outside the Linux ephemeral range.
DEFAULT_DASHBOARD_PORT = 9871

# Where the dashboard application tells its page the developer's
# application is, as a JSON object with the URL under `url`. The page
# runs in the browser and cannot read the environment, so the URL the
# CLI puts there has to be served to it.
APPLICATION_PATH = '/application'

# The `Dashboard` state holding everything the dashboard shows, as
# the dashboard application last read it.
DASHBOARD_ID = 'dashboard'
Expand All @@ -47,6 +53,12 @@
# which case no implementation is looked for.
ENVVAR_RBT_APPLICATION = 'RBT_APPLICATION'

# Where the developer's application serves, `http://localhost:9991`,
# from the port the `.rbtrc` gives `rbt dev run`. The page reads the
# application's states and tasks from there; nothing else in the
# dashboard reaches the application.
ENVVAR_RBT_APPLICATION_URL = 'RBT_APPLICATION_URL'

# The directory `rbt generate` writes Python code into, as the
# `.rbtrc` spells it with `--python=`. The generated code is where
# the state types are defined, which is what typing the developer's
Expand Down
11 changes: 10 additions & 1 deletion reboot/dashboard/backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
being developed.
"""
import asyncio
import os
from pathlib import Path
from rbt.dashboard.v1.dashboard_rbt import Dashboard, Preferences
from rbt.std.collections.ordered_map.v1.ordered_map_rbt import OrderedMap
Expand All @@ -17,9 +18,11 @@
from reboot.aio.external import InitializeContext
from reboot.bdd import recordings
from reboot.dashboard.backend.constants import (
APPLICATION_PATH,
CHANGELOG_ID,
DASHBOARD_ID,
DASHBOARD_PATH,
ENVVAR_RBT_APPLICATION_URL,
PREFERENCES_ID,
PRESENCE_ID,
)
Expand All @@ -32,7 +35,7 @@
)
from reboot.std.presence.v1 import presence
from starlette.exceptions import HTTPException
from starlette.responses import FileResponse
from starlette.responses import FileResponse, JSONResponse
from starlette.staticfiles import StaticFiles

# The built page, beside this module, which is the same arrangement
Expand Down Expand Up @@ -103,6 +106,12 @@ async def recording(relative: str) -> FileResponse:
feature file under the working directory."""
return FileResponse(_recording(Path.cwd(), relative))

@application.http.get(APPLICATION_PATH)
async def application_url() -> JSONResponse:
"""Where the developer's application serves, for the page to
read its states and tasks from."""
return JSONResponse({'url': os.environ[ENVVAR_RBT_APPLICATION_URL]})

application.http.mount(
DASHBOARD_PATH,
app=StaticFiles(
Expand Down
7 changes: 7 additions & 0 deletions reboot/dashboard/web/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ ts_config(
ts_project(
name = "dashboard_ts",
srcs = [
"src/application.ts",
"src/callgraph.ts",
"src/changelog.ts",
"src/constants.ts",
"src/feature_files.ts",
"src/features.ts",
"src/frontend_window.tsx",
"src/graph.tsx",
"src/json_tree.tsx",
"src/link_properties_to_data_types.ts",
"src/main.tsx",
"src/picker.tsx",
"src/states.tsx",
],
declaration = True,
tsconfig = ":tsconfig",
# The contract test imports `link_properties_to_data_types.ts`.
visibility = ["//tests/reboot/dashboard:__pkg__"],
deps = [
"//:node_modules/@bufbuild/protobuf",
"//:node_modules/@reboot-dev/reboot-api",
"//:node_modules/@reboot-dev/reboot-react",
"//:node_modules/@reboot-dev/reboot-std",
"//:node_modules/@reboot-dev/reboot-std-api",
Expand All @@ -42,6 +48,7 @@ ts_project(
"//rbt/v1alpha1/api:schema_js_proto",
"//rbt/v1alpha1/bdd:feature_js_proto",
"//rbt/v1alpha1/bdd:grammar_js_proto",
"//rbt/v1alpha1/inspect:inspect_js_proto",
],
)

Expand Down
Loading
Loading