pass custom container to mount mfe app#218
Conversation
📝 WalkthroughWalkthroughAdds an exported MfeContainer type, rewrites portal rendering to use ShadowRoot, scopes theme stylesheet and Emotion style tag handling to a container-specific root, updates lifecycle hooks to set/reset that root, and makes FnAppProvider create/use a container-scoped Emotion cache. ChangesContainer-Scoped Theme Management
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@public/app/fn-app/create-mfe.ts`:
- Around line 105-116: The static theme root can be left unset or stale causing
getThemeStyleRoot() to throw or reuse a previous instance; update
setThemeStyleRoot(container) so when container is falsy it resets or defaults
createMfe.themeStyleRoot to a safe value (e.g., document) and/or ensure
mountFnApp() and updateFnApp() call loadFnTheme() with a reinitialized style
root; specifically, modify setThemeStyleRoot to set createMfe.themeStyleRoot =
container || document (or null-clearing before load) and ensure
getThemeStyleRoot() no longer throws by relying on that default, touching the
setThemeStyleRoot, getThemeStyleRoot, mountFnApp, updateFnApp, and loadFnTheme
references.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 8ac32184-e883-4f46-8c3a-34282347845c
📒 Files selected for processing (2)
public/app/fn-app/create-mfe.tspublic/app/fn-app/types.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-test
🧰 Additional context used
📓 Path-based instructions (1)
**/*.ts
⚙️ CodeRabbit configuration file
**/*.ts: - Do not allow use ofeslint-disable,@ts-expect-error, or@ts-ignoreunless there's a clear, inline comment explaining why it's necessary.
- Suggest early returns in place of nested
if,elseor loops with complex branching.- Flag function-wide scopes created by
try/catchor top-levelif/else. Recommend moving the inner logic to its own function.- Flag use of
try/catchfor control flow. Recommend using.catch()with appropriate error handling.- Flag
try/catchthat introduces aletwhere.catch()withconstcould be used instead.- Flag
catchblocks that narrow the caughterrortoError. Suggest typing thecatchparameter asunknown.- Flag cases where types are narrowed manually before passing a value to the logger. Suggest passing the value directly without narrowing.
- Flag logging expressions that extract
error.messageor convert the error to a string. Suggest logging the full error value instead.- Flag variables created from
error.messageorString(error)that are then logged. Suggest logging the originalerrorvalue directly.- When
letis used to accumulate a value through conditions, suggest replacing it with a function that returns the final value directly.- Flag
letfollowed by a single conditional reassignment. Suggest aconstwith a ternary or a helper that returns the final value.- Flag Map get-or-create patterns that assign to a
let(e.g.let x = map.get(k); if (!x) { x = new ...; map.set(k, x) }). Suggest agetOrCreate*helper that returns the value and keeps the variableconst.- Flag nested conditions that can be combined into a single guard. Suggest simplifying with an early return.
- When encountering side effects such as mutation in
forEach, suggest replacing withmap,filterorreduce.- Recommend introducing intermediate variables when string interpolation contains non-trivial logic.
- Ban all
astype assertions everywhere, including chains like ...
Files:
public/app/fn-app/types.tspublic/app/fn-app/create-mfe.ts
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@public/app/fn-app/fn-app-provider.tsx`:
- Around line 30-48: The code currently mutates the process-wide emotionCssCache
and moves its tags inside the useMemo callback for the FnAppProvider, which
breaks multi-dashboard rendering; keep the per-container createCache call inside
useMemo (createCache with key 'grafana-mf' and container) but remove any
reassignment of emotionCssCache.sheet.container and DOM appendChild calls from
the memo callback, and instead perform any required global-sheet relocation in a
useEffect (or avoid relocating shared `@emotion/css` entirely) so side effects run
only after mount; reference emotionCssCache, useMemo, createCache, FnAppProvider
and DashboardPortal when making the change.
In `@public/microfrontends/fn_dashboard/index.html`:
- Line 10: The inline <script> tag currently has an empty nonce attribute
(nonce="") which nullifies CSP protection; either remove the nonce attribute
entirely if you are not using CSP, or populate it with a server-generated
cryptographically secure nonce value and inject that same value into the
server's Content-Security-Policy header (matching 'nonce-{value}'); locate the
inline script tag with nonce="" in the HTML (the <script nonce=""> element) and
implement server-side generation/injection of the nonce or remove the attribute
accordingly so the CSP remains effective.
- Around line 20-22: The two script tags referencing
runtime~fn_dashboard.a5d060ef4f8cb38ef003.js and
fn_dashboard.61924fc7a748b4f2ecc3.js currently have empty nonce attributes and
no SRI/CORS attributes; fix by removing empty nonce="" or (preferably) replacing
with a server-generated cryptographically-random nonce value that matches the
page CSP, and restore Subresource Integrity by computing and adding
integrity="sha384-..." (or sha512) for each script file and add
crossorigin="anonymous" so SRI can function; locate the tags in
public/microfrontends/fn_dashboard/index.html and update the script elements
referencing those two filenames accordingly.
- Around line 20-22: In public/microfrontends/fn_dashboard/index.html the script
tags reference non-existent hashed bundles
runtime~fn_dashboard.a5d060ef4f8cb38ef003.js and
fn_dashboard.61924fc7a748b4f2ecc3.js; either update those src attributes to
point to the actual built filenames/paths produced by your bundler (replace the
two referenced filenames with the real outputs) or ensure your build/pipeline
emits those specific files into the public/build location so the paths resolve
at runtime (adjust your build config or deployment static asset step to
produce/serve the expected bundles).
- Around line 13-14: The template references hashed assets under public/build
(e.g. the strings 'public/build/grafana.light.<hash>.css',
'public/build/grafana.dark.<hash>.css' and runtime~fn_dashboard.<hash>.js /
fn_dashboard.<hash>.js) which are missing; either update the asset URLs in the
index.html to the actual deployed locations (e.g. remove the leading "public/"
so they resolve to /build/...) or make the build/deploy process copy/generate
those hashed files into public/build; locate the asset declarations in the
fn_dashboard index.html (the base href and the light/dark CSS and JS script
references) and change them to point to the correct runtime paths or to template
placeholders that your bundler will replace during build.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: b145b256-f5d3-4952-89cc-906c013ee4ac
📒 Files selected for processing (5)
public/app/fn-app/create-mfe.tspublic/app/fn-app/fn-app-provider.tsxpublic/app/fn-app/fn-dashboard-page/fn-dashboard.tsxpublic/app/fn-app/utils.tsxpublic/microfrontends/fn_dashboard/index.html
🚧 Files skipped from review as they are similar to previous changes (1)
- public/app/fn-app/create-mfe.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build_and_deploy
- GitHub Check: build-and-test
🔇 Additional comments (4)
public/microfrontends/fn_dashboard/index.html (2)
1-7: LGTM!
8-9: LGTM!public/app/fn-app/utils.tsx (1)
8-22: LGTM!public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx (1)
74-87: ⚡ Quick winVerify
containerprop type compatibility.Type is compatible:
FNDashboardProps['container']isMfeContainer | null(MfeContainer = Document | DocumentFragment | HTMLElement), andRenderPortal’s render-prop callback parameter is typed asMfeContainerwhile it passesshadowRootfromattachShadow(DOMShadowRootextendsDocumentFragment).
| const emotionCache = useMemo( | ||
| () => { | ||
| const container = | ||
| props.container instanceof Document ? props.container.head : props.container || document.head; | ||
|
|
||
| emotionCssCache.sheet.container = container; | ||
| emotionCssCache.sheet.tags.forEach((tag) => { | ||
| if (tag.parentNode !== container) { | ||
| container.appendChild(tag); | ||
| } | ||
| }); | ||
|
|
||
| return createCache({ | ||
| key: 'grafana-mf', | ||
| container, | ||
| }); | ||
| }, | ||
| [props.container] | ||
| ); |
There was a problem hiding this comment.
Mutating the shared global Emotion cache inside useMemo breaks multi-dashboard rendering.
emotionCssCache is the process-wide singleton from @emotion/css shared by the host app and every dashboard. DashboardPortal renders one FnAppProvider per dashboard, each with its own shadow-root container. Two problems:
- Each instance reassigns
emotionCssCache.sheet.containerandappendChild's all existing@emotion/csstags into its own shadow root. With more than one dashboard the last render wins, relocating those style tags out of the host (and out of every other dashboard's root), so other consumers lose their styles. - These are side effects (global mutation + DOM moves) executed inside
useMemo, which must be pure. Under concurrent rendering React may invoke or discard the memo callback speculatively, making the relocation unreliable.
Keep createCache in useMemo for the per-container scoping, but move the global-sheet relocation into an effect, and reconsider whether the shared @emotion/css cache should be re-parented at all when multiple shadow roots are active.
♻️ Suggested direction
- const emotionCache = useMemo(
- () => {
- const container =
- props.container instanceof Document ? props.container.head : props.container || document.head;
-
- emotionCssCache.sheet.container = container;
- emotionCssCache.sheet.tags.forEach((tag) => {
- if (tag.parentNode !== container) {
- container.appendChild(tag);
- }
- });
-
- return createCache({
- key: 'grafana-mf',
- container,
- });
- },
- [props.container]
- );
+ const container = useMemo(
+ () => (props.container instanceof Document ? props.container.head : props.container || document.head),
+ [props.container]
+ );
+ const emotionCache = useMemo(() => createCache({ key: 'grafana-mf', container }), [container]);
+
+ useEffect(() => {
+ // Re-parent existing `@emotion/css` tags into the scoped container.
+ // NOTE: this still touches a shared global cache; verify it is safe when
+ // multiple dashboards (shadow roots) are mounted simultaneously.
+ emotionCssCache.sheet.container = container;
+ emotionCssCache.sheet.tags.forEach((tag) => {
+ if (tag.parentNode !== container) {
+ container.appendChild(tag);
+ }
+ });
+ }, [container]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const emotionCache = useMemo( | |
| () => { | |
| const container = | |
| props.container instanceof Document ? props.container.head : props.container || document.head; | |
| emotionCssCache.sheet.container = container; | |
| emotionCssCache.sheet.tags.forEach((tag) => { | |
| if (tag.parentNode !== container) { | |
| container.appendChild(tag); | |
| } | |
| }); | |
| return createCache({ | |
| key: 'grafana-mf', | |
| container, | |
| }); | |
| }, | |
| [props.container] | |
| ); | |
| const container = useMemo( | |
| () => (props.container instanceof Document ? props.container.head : props.container || document.head), | |
| [props.container] | |
| ); | |
| const emotionCache = useMemo(() => createCache({ key: 'grafana-mf', container }), [container]); | |
| useEffect(() => { | |
| // Re-parent existing `@emotion/css` tags into the scoped container. | |
| // NOTE: this still touches a shared global cache; verify it is safe when | |
| // multiple dashboards (shadow roots) are mounted simultaneously. | |
| emotionCssCache.sheet.container = container; | |
| emotionCssCache.sheet.tags.forEach((tag) => { | |
| if (tag.parentNode !== container) { | |
| container.appendChild(tag); | |
| } | |
| }); | |
| }, [container]); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/app/fn-app/fn-app-provider.tsx` around lines 30 - 48, The code
currently mutates the process-wide emotionCssCache and moves its tags inside the
useMemo callback for the FnAppProvider, which breaks multi-dashboard rendering;
keep the per-container createCache call inside useMemo (createCache with key
'grafana-mf' and container) but remove any reassignment of
emotionCssCache.sheet.container and DOM appendChild calls from the memo
callback, and instead perform any required global-sheet relocation in a
useEffect (or avoid relocating shared `@emotion/css` entirely) so side effects run
only after mount; reference emotionCssCache, useMemo, createCache, FnAppProvider
and DashboardPortal when making the change.
|
|
||
| <body class="theme-light app-grafana"> | ||
| <div id="grafanaRoot"></div> | ||
| <script nonce=""> |
There was a problem hiding this comment.
Critical: Empty nonce attribute defeats CSP protection.
The nonce="" attribute on this inline script tag has an empty value, which defeats Content Security Policy (CSP) protection. If CSP is enabled with script-src 'nonce-{value}', an empty nonce effectively allows any inline script to execute, creating a security vulnerability.
Either populate the nonce with a cryptographically random value generated server-side, or remove the attribute if CSP is not being used.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/microfrontends/fn_dashboard/index.html` at line 10, The inline
<script> tag currently has an empty nonce attribute (nonce="") which nullifies
CSP protection; either remove the nonce attribute entirely if you are not using
CSP, or populate it with a server-generated cryptographically secure nonce value
and inject that same value into the server's Content-Security-Policy header
(matching 'nonce-{value}'); locate the inline script tag with nonce="" in the
HTML (the <script nonce=""> element) and implement server-side
generation/injection of the nonce or remove the attribute accordingly so the CSP
remains effective.
| light: '../../../public/build/grafana.light.65904cef23d9f7f76c4a.css', | ||
| dark: '../../../public/build/grafana.dark.7c4d93ecbdd92098eb9a.css', |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if the hashed CSS files referenced in the HTML exist
# Expected CSS files based on the HTML
LIGHT_CSS="public/build/grafana.light.65904cef23d9f7f76c4a.css"
DARK_CSS="public/build/grafana.dark.7c4d93ecbdd92098eb9a.css"
echo "Checking for CSS files..."
if [ -f "$LIGHT_CSS" ]; then
echo "✓ Found: $LIGHT_CSS"
else
echo "✗ Missing: $LIGHT_CSS"
fi
if [ -f "$DARK_CSS" ]; then
echo "✓ Found: $DARK_CSS"
else
echo "✗ Missing: $DARK_CSS"
fi
# Also search for any grafana theme CSS files to see what actually exists
echo -e "\nAll Grafana theme CSS files in public/build/:"
fd -e css 'grafana\.(light|dark)\.' public/build/ --exec echo "{}"Repository: coderabbitai/grafana
Length of output: 381
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Inspect index.html base + themePaths snippet =="
nl -ba public/microfrontends/fn_dashboard/index.html | sed -n '1,80p'
echo
echo "== Locate referenced hashed CSS files anywhere in repo =="
LIGHT_REF="grafana.light.65904cef23d9f7f76c4a.css"
DARK_REF="grafana.dark.7c4d93ecbdd92098eb9a.css"
echo "Searching for: $LIGHT_REF"
rg -n --hidden --no-ignore -S "$LIGHT_REF" . || true
echo "Searching for: $DARK_REF"
rg -n --hidden --no-ignore -S "$DARK_REF" . || true
echo
echo "== List any grafana.light.* and grafana.dark.* CSS files in repo =="
fd -e css "grafana\.(light|dark)\..*" . || true
echo
echo "== Check for common build output dirs (existence only) =="
for d in public/build build public/dist public/assets dist assets; do
if [ -d "$d" ]; then echo "Found dir: $d"; else echo "Missing dir: $d"; fi
doneRepository: coderabbitai/grafana
Length of output: 176
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Inspect index.html base + themePaths snippet =="
awk '{printf "%5d %s\n", NR, $0}' public/microfrontends/fn_dashboard/index.html | sed -n '1,120p'
echo
echo "== Locate referenced hashed CSS files anywhere in repo =="
LIGHT_REF="grafana.light.65904cef23d9f7f76c4a.css"
DARK_REF="grafana.dark.7c4d93ecbdd92098eb9a.css"
echo "Searching for: $LIGHT_REF"
rg -n --hidden --no-ignore -S "$LIGHT_REF" . || true
echo "Searching for: $DARK_REF"
rg -n --hidden --no-ignore -S "$DARK_REF" . || true
echo
echo "== List any grafana.light.* and grafana.dark.* CSS files in repo =="
fd -e css "grafana\.(light|dark)\..*" . || true
echo
echo "== Check for common build output dirs (existence only) =="
for d in public/build public/dist public/assets build dist assets; do
if [ -d "$d" ]; then echo "Found dir: $d"; else echo "Missing dir: $d"; fi
doneRepository: coderabbitai/grafana
Length of output: 1680
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Check whether referenced build JS files exist =="
RUNTIME="public/build/runtime~fn_dashboard.a5d060ef4f8cb38ef003.js"
BUNDLE="public/build/fn_dashboard.61924fc7a748b4f2ecc3.js"
for f in "$RUNTIME" "$BUNDLE"; do
if [ -f "$f" ]; then
echo "✓ Found: $f"
else
echo "✗ Missing: $f"
fi
doneRepository: coderabbitai/grafana
Length of output: 246
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n --hidden --no-ignore -S "runtime~fn_dashboard\.a5d060ef4f8cb38ef003\.js" . || true
rg -n --hidden --no-ignore -S "fn_dashboard\.61924fc7a748b4f2ecc3\.js" . || true
rg -n --hidden --no-ignore -S "grafana\.(light|dark)\." public/microfrontends/fn_dashboard/index.html || true
ls -la public || true
ls -la public/microfrontends/fn_dashboard || trueRepository: coderabbitai/grafana
Length of output: 2017
Fix asset URLs: referenced hashed CSS/JS under public/build/ are missing in this repo snapshot
public/microfrontends/fn_dashboard/index.html resolves (with <base href="/" />) to /public/build/grafana.{light|dark}.<hash>.css and also loads /public/build/runtime~fn_dashboard.<hash>.js + /public/build/fn_dashboard.<hash>.js, but public/build/ (and those hashed files) aren’t present here—these requests will 404 unless your build/deploy step generates/copies them into public/build (or the template should be updated to the real asset locations).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/microfrontends/fn_dashboard/index.html` around lines 13 - 14, The
template references hashed assets under public/build (e.g. the strings
'public/build/grafana.light.<hash>.css', 'public/build/grafana.dark.<hash>.css'
and runtime~fn_dashboard.<hash>.js / fn_dashboard.<hash>.js) which are missing;
either update the asset URLs in the index.html to the actual deployed locations
(e.g. remove the leading "public/" so they resolve to /build/...) or make the
build/deploy process copy/generate those hashed files into public/build; locate
the asset declarations in the fn_dashboard index.html (the base href and the
light/dark CSS and JS script references) and change them to point to the correct
runtime paths or to template placeholders that your bundler will replace during
build.
| <script nonce="" src="../../../public/build/runtime~fn_dashboard.a5d060ef4f8cb38ef003.js" type="text/javascript"></script> | ||
|
|
||
| <script nonce="" src="../../../public/build/fn_dashboard.61924fc7a748b4f2ecc3.js" type="text/javascript"></script> |
There was a problem hiding this comment.
Critical: Empty nonce attributes and missing integrity protection.
These script tags have two security issues:
-
Empty nonce attributes (
nonce=""): Same CSP bypass vulnerability as noted earlier. Each script with an empty nonce defeats Content Security Policy protection. -
Missing Subresource Integrity (SRI): The AI summary confirms that
integrityandcrossoriginattributes were removed. This is a security regression that eliminates protection against script tampering. SRI ensures that loaded scripts haven't been modified on the CDN or during transit.
Recommended fixes:
- Populate nonce attributes with server-generated cryptographically random values, or remove if CSP is not used
- Restore
integrityattributes with SHA-384/SHA-512 hashes of the script files - Add
crossorigin="anonymous"to enable SRI with CORS
🔒 Example with SRI attributes
- <script nonce="" src="../../../public/build/runtime~fn_dashboard.a5d060ef4f8cb38ef003.js" type="text/javascript"></script>
+ <script nonce="{SERVER_GENERATED_NONCE}" src="../../../public/build/runtime~fn_dashboard.a5d060ef4f8cb38ef003.js" type="text/javascript" integrity="sha384-{HASH}" crossorigin="anonymous"></script>
- <script nonce="" src="../../../public/build/fn_dashboard.61924fc7a748b4f2ecc3.js" type="text/javascript"></script>
+ <script nonce="{SERVER_GENERATED_NONCE}" src="../../../public/build/fn_dashboard.61924fc7a748b4f2ecc3.js" type="text/javascript" integrity="sha384-{HASH}" crossorigin="anonymous"></script>Note: Generate integrity hashes using: openssl dgst -sha384 -binary <file> | openssl base64 -A
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/microfrontends/fn_dashboard/index.html` around lines 20 - 22, The two
script tags referencing runtime~fn_dashboard.a5d060ef4f8cb38ef003.js and
fn_dashboard.61924fc7a748b4f2ecc3.js currently have empty nonce attributes and
no SRI/CORS attributes; fix by removing empty nonce="" or (preferably) replacing
with a server-generated cryptographically-random nonce value that matches the
page CSP, and restore Subresource Integrity by computing and adding
integrity="sha384-..." (or sha512) for each script file and add
crossorigin="anonymous" so SRI can function; locate the tags in
public/microfrontends/fn_dashboard/index.html and update the script elements
referencing those two filenames accordingly.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if the hashed JS bundles referenced in the HTML exist
# Expected JS files based on the HTML
RUNTIME_JS="public/build/runtime~fn_dashboard.a5d060ef4f8cb38ef003.js"
MAIN_JS="public/build/fn_dashboard.61924fc7a748b4f2ecc3.js"
echo "Checking for JS bundles..."
if [ -f "$RUNTIME_JS" ]; then
echo "✓ Found: $RUNTIME_JS"
else
echo "✗ Missing: $RUNTIME_JS"
fi
if [ -f "$MAIN_JS" ]; then
echo "✓ Found: $MAIN_JS"
else
echo "✗ Missing: $MAIN_JS"
fi
# Also search for any fn_dashboard JS files to see what actually exists
echo -e "\nAll fn_dashboard JS files in public/build/:"
fd -e js 'fn_dashboard' public/build/ --exec echo "{}"Repository: coderabbitai/grafana
Length of output: 385
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Locate the expected hashed bundle filenames anywhere in the repo
echo "Searching for exact hashed bundle filenames..."
rg -n --hidden --no-ignore-vcs -S "runtime~fn_dashboard\.a5d060ef4f8cb38ef003\.js|fn_dashboard\.61924fc7a748b4f2ecc3\.js" . || true
echo
echo "Finding files by name (may take a moment)..."
find . -type f \( -name 'runtime~fn_dashboard.a5d060ef4f8cb38ef003.js' -o -name 'fn_dashboard.61924fc7a748b4f2ecc3.js' \) -print || true
echo
# 2) Check whether a public/build directory exists anywhere under repo
echo "Checking for build output directories..."
find . -type d -path "*/public/build" -print || true
find . -type d -name build -maxdepth 4 -print || true
echo
# 3) Show the relevant section of the HTML for base href and script tags
echo "---- public/microfrontends/fn_dashboard/index.html (relevant section) ----"
nl -ba public/microfrontends/fn_dashboard/index.html | sed -n '1,120p'Repository: coderabbitai/grafana
Length of output: 713
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) Does any fn_dashboard JS exist anywhere?"
find . -type f \( -name '*fn_dashboard*js' -o -name '*runtime~fn_dashboard*js' \) -print || true
echo
echo "2) What JS files exist under pkg/build and scripts/build (limited by fn_dashboard keywords)?"
for d in ./pkg/build ./scripts/build; do
if [ -d "$d" ]; then
echo "-- $d --"
find "$d" -type f -name '*fn_dashboard*js' -print || true
find "$d" -type f -name '*runtime*fn_dashboard*js' -print || true
fi
done
echo
echo "3) Reprint public/microfrontends/fn_dashboard/index.html lines 1-60 (no nl)."
sed -n '1,80p' public/microfrontends/fn_dashboard/index.htmlRepository: coderabbitai/grafana
Length of output: 1027
Fix: referenced hashed fn_dashboard JS bundles aren’t present at /public/build
- In public/microfrontends/fn_dashboard/index.html (lines 20-22), the page loads:
- ../../../public/build/runtime~fn_dashboard.a5d060ef4f8cb38ef003.js
- ../../../public/build/fn_dashboard.61924fc7a748b4f2ecc3.js
- The repo checkout has no public/build directory and these exact hashed JS files don’t exist anywhere in the repository, so the script tags will fail (404) unless your build/deploy pipeline generates/serves them at /public/build.
- Update the hashes/paths to match the actual build outputs or ensure the bundles are produced and available at the expected location at runtime.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/microfrontends/fn_dashboard/index.html` around lines 20 - 22, In
public/microfrontends/fn_dashboard/index.html the script tags reference
non-existent hashed bundles runtime~fn_dashboard.a5d060ef4f8cb38ef003.js and
fn_dashboard.61924fc7a748b4f2ecc3.js; either update those src attributes to
point to the actual built filenames/paths produced by your bundler (replace the
two referenced filenames with the real outputs) or ensure your build/pipeline
emits those specific files into the public/build location so the paths resolve
at runtime (adjust your build config or deployment static asset step to
produce/serve the expected bundles).
Summary by CodeRabbit
New Features
Refactor
Other