[MM-67954] Browser agent ltbrowserapi fails on startup: missing config/config.json when deploying from GitHub release#980
Conversation
…ode modules correctly
…e logging from config.json
…le logging and set console log level to debug
…ests - Introduced a new `setupAgentType` function to streamline the setup of agent types in tests. - Updated `TestIsBrowserAgentInstance` and `TestBrowserAgentConfigValidation` to utilize the new setup function. - Enhanced the `createLoadAgentHandler` to validate the `browsercontroller.json` configuration before creating browser agents. - Added logic in the Terraform agent configuration to upload the `browsercontroller.json` to browser agent instances, ensuring valid configurations are used during load tests.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAPI and Terraform now read and validate a dedicated BrowserController config ( Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant API as "API Server\n(api/agent.go)"
participant BC as "BrowserController\n(loadtest/control/browsercontroller)"
participant Defaults as "defaults.Validate"
participant Terraform as "Terraform\n(deployment/terraform/agent.go)"
Client->>API: POST /loadagent/create (browser agent)
API->>BC: ReadConfig("./config/browsercontroller.json")
BC-->>API: config or error
API->>Defaults: Validate(config)
Defaults-->>API: valid or validation error
alt config valid
API-->>Client: 201 Created (agent)
Note right of Terraform: Deployment flow
Terraform->>BC: Read & marshal browsercontroller.json
Terraform-->>Agent: Upload browsercontroller.json to agent path
else read/validation failed
API-->>Client: 400 Bad Request { "error": "..." }
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.11.3)Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
api/agent.go (1)
144-151:⚠️ Potential issue | 🔴 CriticalMissing
returnafterNewControllerWrappererror.When
NewControllerWrapperfails (line 145), the handler writes an error response but does not return early. Execution continues to line 153, which callsloadtest.Newwith anilcontroller, likely causing a panic or unexpected behaviour.🐛 Proposed fix
newC, err := NewControllerWrapper(<Config, ucConfig, 0, agentId, a.metrics, isBAInstance) if err != nil { writeAgentResponse(w, http.StatusBadRequest, &client.AgentResponse{ Id: agentId, Message: "load-test agent creation failed", Error: fmt.Sprintf("could not create agent: %s", err), }) + return }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/agent.go` around lines 144 - 151, The error handler after calling NewControllerWrapper(<Config, ucConfig, 0, agentId, a.metrics, isBAInstance) writes an AgentResponse but fails to return, allowing execution to continue with a nil controller; update the handler so that after writeAgentResponse(...) it immediately returns from the enclosing function (thus preventing subsequent calls like loadtest.New(...) from running with newC == nil), referencing NewControllerWrapper, writeAgentResponse, and the newC variable to locate and fix the flow control.
🧹 Nitpick comments (2)
docs/config/browsercontroller.md (1)
40-89: Consider adding default values for LogSettings fields.The Go struct in
browsercontroller/config.godefines default values for these fields (e.g.,EnableConsole: true,ConsoleLevel: "debug",FileLocation: "browseragent.log"), but they're not documented here. Adding Default: annotations would improve consistency with the other documented fields and help users understand the out-of-the-box behaviour.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/config/browsercontroller.md` around lines 40 - 89, The docs for LogSettings are missing the default values present in the Go struct; update the LogSettings section to add "Default:" annotations for each field to match the defaults defined in the browsercontroller config (refer to the LogSettings struct and fields in browsercontroller/config.go): set EnableConsole default to true, ConsoleLevel default to "debug", EnableFile default to false (or whatever the struct uses), FileLevel default to "debug" (or the struct value), and FileLocation default to "browseragent.log"; ensure each field paragraph adds a short "Default: <value>" line consistent with other docs.browser/src/config/accessors.ts (1)
6-10: Tighten the docblock wording and typos for maintainability.The comment has minor spelling/grammar issues (
URl,its created) that make intent harder to scan.Suggested wording update
/** - * Server URl is always passed as a parameter to the browser controller while - * its created. So we don't need to read it from the config.json. But we need - * hardcoded value for tests and smoke simulations. + * Server URL is always passed as a parameter when the browser controller is + * created, so we don't read it from config.json. We keep a hardcoded fallback + * for tests and smoke simulations. */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@browser/src/config/accessors.ts` around lines 6 - 10, Edit the docblock comment at the top of browser/src/config/accessors.ts to fix typos and tighten wording: change "URl" to "URL", "its created" to "when it's created", and rephrase the whole comment to a concise sentence like "The server URL is passed to the browser controller when it's created, so we don't read it from config.json; a hardcoded value is retained for tests and smoke simulations." Ensure the updated comment replaces the existing block above the accessor definitions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@api/agent_test.go`:
- Around line 400-418: The subtest "succeeds with valid browsercontroller.json"
depends on changing dirs and a repo-local config; instead create a temporary
config directory and a valid browsercontroller.json file inside it before
calling the POST("/create") path: make a temp dir (or use t.TempDir()), mkdir
"config" inside it, write a minimal valid JSON for browsercontroller.json, set
the test's current working dir to that temp dir (or ensure ReadConfig is pointed
there) and register t.Cleanup to remove the temp files and restore the original
working dir; remove the os.Chdir("..") reliance and keep the rest of the test
flow that uses requestData and the POST("/create") call unchanged so the test
becomes self-contained.
In `@deployment/terraform/agent.go`:
- Around line 230-237: The current upload branch only runs when agentType ==
deployment.AgentTypeBrowser, so browsercontroller.json isn't copied to hosts
where ltbrowserapi.service is present but agentType differs; change the
condition around creating the uploadInfo (the block that appends with srcData:
browserControllerConfig and dstPath via t.ExpandWithUser) to target any host
that will run ltbrowserapi.service instead of only deployment.AgentTypeBrowser —
e.g., detect presence of ltbrowserapi (a helper like
agentHasService("ltbrowserapi.service") or include other relevant AgentType
values) and append the uploadInfo accordingly so the file exists wherever the
code later restarts ltbrowserapi.service.
- Around line 112-115: The code currently hard-fails when
browsercontroller.ReadConfig("./config/browsercontroller.json") returns an
error; update the block guarded by t.output.HasBrowserAgents() so that if
reading "./config/browsercontroller.json" yields ENOENT (or can’t be found) you
fall back to reading a sample file (e.g.
"./config/browsercontroller.sample.json") and, if that also fails, fall back to
a built-in/default config (or browsercontroller.DefaultConfig()) instead of
returning an error; adjust the error handling around
browsercontroller.ReadConfig and the variable bccfg, log a warning when falling
back, and only return an error if no config can be established after the
fallbacks.
In `@docs/config/browsercontroller.md`:
- Line 55: Update the phrasing in the sentence "Possible values (in order of
decreasing verbosity, these are case sensitive):" and the other identical
occurrence to use the hyphenated compound adjective "case-sensitive" instead of
"case sensitive" so it reads "Possible values (in order of decreasing verbosity,
these are case-sensitive):".
---
Outside diff comments:
In `@api/agent.go`:
- Around line 144-151: The error handler after calling
NewControllerWrapper(<Config, ucConfig, 0, agentId, a.metrics, isBAInstance)
writes an AgentResponse but fails to return, allowing execution to continue with
a nil controller; update the handler so that after writeAgentResponse(...) it
immediately returns from the enclosing function (thus preventing subsequent
calls like loadtest.New(...) from running with newC == nil), referencing
NewControllerWrapper, writeAgentResponse, and the newC variable to locate and
fix the flow control.
---
Nitpick comments:
In `@browser/src/config/accessors.ts`:
- Around line 6-10: Edit the docblock comment at the top of
browser/src/config/accessors.ts to fix typos and tighten wording: change "URl"
to "URL", "its created" to "when it's created", and rephrase the whole comment
to a concise sentence like "The server URL is passed to the browser controller
when it's created, so we don't read it from config.json; a hardcoded value is
retained for tests and smoke simulations." Ensure the updated comment replaces
the existing block above the accessor definitions.
In `@docs/config/browsercontroller.md`:
- Around line 40-89: The docs for LogSettings are missing the default values
present in the Go struct; update the LogSettings section to add "Default:"
annotations for each field to match the defaults defined in the
browsercontroller config (refer to the LogSettings struct and fields in
browsercontroller/config.go): set EnableConsole default to true, ConsoleLevel
default to "debug", EnableFile default to false (or whatever the struct uses),
FileLevel default to "debug" (or the struct value), and FileLocation default to
"browseragent.log"; ensure each field paragraph adds a short "Default: <value>"
line consistent with other docs.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1ed82073-e855-452f-b440-0bdca7d3c0f7
📒 Files selected for processing (24)
api/agent.goapi/agent_test.gobrowser/src/app.tsbrowser/src/config/accessors.tsbrowser/src/config/loader.tsbrowser/src/e2e/post_and_scroll_scenario.spec.tsbrowser/src/logger/index.test.tsbrowser/src/logger/index.tsbrowser/src/routes/browser.test.tsbrowser/src/routes/browser.tsbrowser/src/services/browser_manager.tsbrowser/src/smoke_simulations/index.tsconfig/browsercontroller.sample.jsonconfig/config.sample.jsonconfig/config.sample.tomldeployment/terraform/agent.godocs/config/browsercontroller.mddocs/config/config.mdexamples/config/perfcomp/json/config.jsonexamples/config/release/json/config.jsonloadtest/config.goloadtest/control/browsercontroller/config.goloadtest/loadtest_test.goloadtest/user/userentity/helper_test.go
💤 Files with no reviewable changes (7)
- config/config.sample.toml
- examples/config/perfcomp/json/config.json
- loadtest/loadtest_test.go
- examples/config/release/json/config.json
- config/config.sample.json
- docs/config/config.md
- loadtest/config.go
agarciamontoro
left a comment
There was a problem hiding this comment.
Looking good! This makes sense, sending the file to the agent machine on creation seems robust to me. I added a couple of comments, and I'll take the liberty to fix the failing CI test so that we can try and merge this today.
| // Read and validate the browsercontroller.json that was uploaded by | ||
| // Terraform to confirm it landed correctly and contains valid values | ||
| // before proceeding with browser agent creation if it's a browser agent instance. | ||
| if isBAInstance { | ||
| bccfg, err := browsercontroller.ReadConfig("./config/browsercontroller.json") | ||
| if err != nil { | ||
| writeAgentResponse(w, http.StatusBadRequest, &client.AgentResponse{ | ||
| Error: fmt.Sprintf("could not read browser controller config: %s", err), | ||
| }) | ||
| return | ||
| } | ||
| if err := defaults.Validate(bccfg); err != nil { | ||
| writeAgentResponse(w, http.StatusBadRequest, &client.AgentResponse{ | ||
| Error: fmt.Sprintf("could not validate browser controller config: %s", err), | ||
| }) | ||
| return | ||
| } | ||
| } |
There was a problem hiding this comment.
Just to confirm for my own understanding: this is only to prevent malformed or missing config files, right? The ltbrowserapi process is the one that will read this later.
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
api/agent_test.go (1)
35-47: Consider usingt.Setenvfor cleaner environment variable handling.Go 1.17+ provides
t.Setenvwhich automatically restores the original value at test cleanup and marks the test as incompatible witht.Parallel(). This would simplify the helper and make the non-parallel requirement explicit.♻️ Suggested refactor
func setupAgentType(t *testing.T, agentType string) { t.Helper() - originalHome := os.Getenv("HOME") tempDir, err := os.MkdirTemp("", "test_home_"+agentType) require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(tempDir) }) + agentTypeFile := filepath.Join(tempDir, deployment.AgentTypeFileName) require.NoError(t, os.WriteFile(agentTypeFile, []byte(agentType), 0644)) - os.Setenv("HOME", tempDir) - t.Cleanup(func() { - os.Setenv("HOME", originalHome) - os.RemoveAll(tempDir) - }) + t.Setenv("HOME", tempDir) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/agent_test.go` around lines 35 - 47, The setupAgentType helper should use t.Setenv to set HOME and let the testing framework restore it automatically: create the tempDir and agentType file as before, call t.Setenv("HOME", tempDir) instead of os.Setenv and remove the manual originalHome capture and os.Setenv restore; keep a t.Cleanup to os.RemoveAll(tempDir) to delete the temp directory; update the function setupAgentType to use t.Setenv and remove the manual environment restore logic so tests are marked as incompatible with t.Parallel().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@api/agent_test.go`:
- Around line 35-47: The setupAgentType helper should use t.Setenv to set HOME
and let the testing framework restore it automatically: create the tempDir and
agentType file as before, call t.Setenv("HOME", tempDir) instead of os.Setenv
and remove the manual originalHome capture and os.Setenv restore; keep a
t.Cleanup to os.RemoveAll(tempDir) to delete the temp directory; update the
function setupAgentType to use t.Setenv and remove the manual environment
restore logic so tests are marked as incompatible with t.Parallel().
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b024b2c0-3cec-4b8b-aa96-919cd2e29b4c
📒 Files selected for processing (3)
api/agent_test.gobrowser/src/config/accessors.tsdocs/config/browsercontroller.md
✅ Files skipped from review due to trivial changes (1)
- docs/config/browsercontroller.md
🚧 Files skipped from review as they are similar to previous changes (1)
- browser/src/config/accessors.ts
Ah, this is nice! |
This takes care of cleanup automatically and marks the test as not suitable for test parallelism.
|
@coderabbitai configuration |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
api/agent_test.go (1)
380-387: Make the “missing config” subtest fully self-contained.This case still depends on the process working directory not containing
./config/browsercontroller.json. Consider forcing an empty temp working dir in this subtest too, so it can’t pass/fail based on ambient files.Suggested patch
t.Run("fails when browsercontroller.json is missing", func(t *testing.T) { setupAgentType(t, deployment.AgentTypeBrowser) + tempDir := t.TempDir() + t.Chdir(tempDir) rd := requestData{LoadTestConfig: ltConfig} e.POST("/create").WithQuery("id", "ltb0").WithJSON(rd). Expect().Status(http.StatusBadRequest). JSON().Object().ContainsKey("error") })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/agent_test.go` around lines 380 - 387, The subtest started with t.Run("fails when browsercontroller.json is missing", ...) is not fully self-contained because it relies on the process working directory not containing ./config/browsercontroller.json; wrap the test body so it creates an isolated working directory via tmp := t.TempDir(), save the current working dir (cwd, err := os.Getwd()), chdir into tmp (os.Chdir(tmp)) and defer restoring the original cwd (defer func(){ _ = os.Chdir(cwd) }()), then call setupAgentType(t, deployment.AgentTypeBrowser) and run the existing requestData/ e.POST("/create") assertions; this guarantees the missing browsercontroller.json condition regardless of ambient files.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@api/agent_test.go`:
- Around line 380-387: The subtest started with t.Run("fails when
browsercontroller.json is missing", ...) is not fully self-contained because it
relies on the process working directory not containing
./config/browsercontroller.json; wrap the test body so it creates an isolated
working directory via tmp := t.TempDir(), save the current working dir (cwd, err
:= os.Getwd()), chdir into tmp (os.Chdir(tmp)) and defer restoring the original
cwd (defer func(){ _ = os.Chdir(cwd) }()), then call setupAgentType(t,
deployment.AgentTypeBrowser) and run the existing requestData/ e.POST("/create")
assertions; this guarantees the missing browsercontroller.json condition
regardless of ambient files.
|
Configuration used: Organization UI CodeRabbit configurationlanguage: en-CA
tone_instructions: ''
early_access: false
enable_free_tier: true
inheritance: false
reviews:
profile: chill
request_changes_workflow: true
high_level_summary: true
high_level_summary_instructions: ''
high_level_summary_placeholder: '@coderabbitai summary'
high_level_summary_in_walkthrough: false
auto_title_placeholder: '@coderabbitai'
auto_title_instructions: ''
review_status: false
review_details: false
commit_status: true
fail_commit_status: false
collapse_walkthrough: true
changed_files_summary: true
sequence_diagrams: true
estimate_code_review_effort: true
assess_linked_issues: true
related_issues: true
related_prs: true
suggested_labels: true
labeling_instructions: []
auto_apply_labels: false
suggested_reviewers: false
auto_assign_reviewers: false
in_progress_fortune: false
poem: false
enable_prompt_for_ai_agents: true
path_filters: []
path_instructions: []
abort_on_close: true
disable_cache: false
auto_review:
enabled: true
description_keyword: ''
auto_incremental_review: true
auto_pause_after_reviewed_commits: 5
ignore_title_keywords: []
labels: []
drafts: false
base_branches: []
ignore_usernames: []
finishing_touches:
docstrings:
enabled: true
unit_tests:
enabled: true
simplify:
enabled: false
custom: []
pre_merge_checks:
override_requested_reviewers_only: false
docstrings:
mode: warning
threshold: 80
title:
mode: warning
requirements: ''
description:
mode: warning
issue_assessment:
mode: warning
custom_checks: []
tools:
ast-grep:
rule_dirs: []
util_dirs: []
essential_rules: true
packages: []
shellcheck:
enabled: true
ruff:
enabled: true
markdownlint:
enabled: true
github-checks:
enabled: true
timeout_ms: 90000
languagetool:
enabled: true
enabled_rules: []
disabled_rules: []
enabled_categories: []
disabled_categories: []
enabled_only: false
level: default
biome:
enabled: true
hadolint:
enabled: true
swiftlint:
enabled: true
phpstan:
enabled: true
level: default
phpmd:
enabled: true
phpcs:
enabled: true
golangci-lint:
enabled: true
yamllint:
enabled: true
gitleaks:
enabled: true
trufflehog:
enabled: true
checkov:
enabled: true
tflint:
enabled: true
detekt:
enabled: true
eslint:
enabled: true
flake8:
enabled: true
fortitudeLint:
enabled: true
rubocop:
enabled: true
buf:
enabled: true
regal:
enabled: true
actionlint:
enabled: true
pmd:
enabled: true
clang:
enabled: true
cppcheck:
enabled: true
opengrep:
enabled: true
semgrep:
enabled: true
circleci:
enabled: true
clippy:
enabled: true
sqlfluff:
enabled: true
trivy:
enabled: true
prismaLint:
enabled: true
pylint:
enabled: true
oxc:
enabled: true
shopifyThemeCheck:
enabled: true
luacheck:
enabled: true
brakeman:
enabled: true
dotenvLint:
enabled: true
htmlhint:
enabled: true
stylelint:
enabled: true
checkmake:
enabled: true
osvScanner:
enabled: true
blinter:
enabled: true
smartyLint:
enabled: true
emberTemplateLint:
enabled: true
psscriptanalyzer:
enabled: true
chat:
art: false
allow_non_org_members: true
auto_reply: true
integrations:
jira:
usage: auto
linear:
usage: auto
knowledge_base:
opt_out: false
web_search:
enabled: true
code_guidelines:
enabled: true
filePatterns: []
learnings:
scope: auto
issues:
scope: auto
jira:
usage: auto
project_keys: []
linear:
usage: auto
team_keys: []
pull_requests:
scope: auto
mcp:
usage: auto
disabled_servers: []
linked_repositories: []
code_generation:
docstrings:
language: en-US
path_instructions: []
unit_tests:
path_instructions: []
issue_enrichment:
auto_enrich:
enabled: false
planning:
enabled: true
auto_planning:
enabled: true
labels: []
labeling:
labeling_instructions: []
auto_apply_labels: false
|
The testing version takes care of cleanup automatically.
|
Removing @fmartingr following the new 1 human reviewer rule :) I'll merge this as soon as I test it. |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai resolve |
✅ Actions performedComments resolved and changes approved. |
|
Ok, that was difficult. |
…g/config.json when deploying from GitHub release (#980) * Moved configuration accessors to a new file structure under `config/` * Refactor logger tests to use updated config accessors path and mock node modules correctly * Moved LogSettings in browsercontroller.json to manage console and file logging from config.json * Update default logging settings in BrowserLogSettings to enable console logging and set console log level to debug * Add browser controller configuration validation and setup for agent tests - Introduced a new `setupAgentType` function to streamline the setup of agent types in tests. - Updated `TestIsBrowserAgentInstance` and `TestBrowserAgentConfigValidation` to utilize the new setup function. - Enhanced the `createLoadAgentHandler` to validate the `browsercontroller.json` configuration before creating browser agents. - Added logic in the Terraform agent configuration to upload the `browsercontroller.json` to browser agent instances, ensuring valid configurations are used during load tests. * fix test * Fix test with valid config file * Fix typo in comment * Fix typo in docs * Use t.Chdir and t.Setenv instead of os's This takes care of cleanup automatically and marks the test as not suitable for test parallelism. * Use t.TempDir instead of os.MkdirTemp The testing version takes care of cleanup automatically. --------- Co-authored-by: Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
/cherry-pick release-1.33 |
|
Cherry pick is scheduled. |
|
Error trying doing the automated Cherry picking. Please do this manually |
…g/config.json when deploying from GitHub release (#980) (#981) * Moved configuration accessors to a new file structure under `config/` * Refactor logger tests to use updated config accessors path and mock node modules correctly * Moved LogSettings in browsercontroller.json to manage console and file logging from config.json * Update default logging settings in BrowserLogSettings to enable console logging and set console log level to debug * Add browser controller configuration validation and setup for agent tests - Introduced a new `setupAgentType` function to streamline the setup of agent types in tests. - Updated `TestIsBrowserAgentInstance` and `TestBrowserAgentConfigValidation` to utilize the new setup function. - Enhanced the `createLoadAgentHandler` to validate the `browsercontroller.json` configuration before creating browser agents. - Added logic in the Terraform agent configuration to upload the `browsercontroller.json` to browser agent instances, ensuring valid configurations are used during load tests. * fix test * Fix test with valid config file * Fix typo in comment * Fix typo in docs * Use t.Chdir and t.Setenv instead of os's This takes care of cleanup automatically and marks the test as not suitable for test parallelism. * Use t.TempDir instead of os.MkdirTemp The testing version takes care of cleanup automatically. --------- Co-authored-by: M-ZubairAhmed <m-zubairahmed@protonmail.com>
Summary
When deploying browser agents from the GitHub release tarball, ltbrowserapi fails with ENOENT: no such file or directory, open 'config/config.json' and enters a restart loop. This happens because:
This PR fixes the issue by:
Ticket Link
Fixes https://mattermost.atlassian.net/browse/MM-67954
Summary by CodeRabbit
New Features
Documentation
Configuration
Tests