Skip to content

Update plugin system and implement aleternative home for LS3 (Insee) …#1078

Open
garronej wants to merge 2 commits into
mainfrom
plugin-system-update
Open

Update plugin system and implement aleternative home for LS3 (Insee) …#1078
garronej wants to merge 2 commits into
mainfrom
plugin-system-update

Conversation

@garronej

@garronej garronej commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

…as an example usecase

Summary by CodeRabbit

  • New Features

    • Added LS3 environment home screen with service launcher cards (RStudio, Jupyter, VSCode)
    • Integrated GitLab repository selection flow for service launches
    • Enhanced plugin system with dynamic component mounting capabilities
  • Documentation

    • Added GitLab token setup reference guide
  • Refactor

    • Streamlined plugin initialization and event handling

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a plugin mounting system that allows external code to dynamically load and render React components in the main application, implements a shared IDE launcher component with Git configuration support, demonstrates the system with a concrete example plugin, and wires the infrastructure into the app via React portals.

Changes

Plugin mounting system and HomeLS3 IDE launcher

Layer / File(s) Summary
Plugin import allowlist
web/src/pluginSystem/onyxia_import.ts
Defines a hardcoded allowlist of modules available to plugins via onyxia.import, with type-to-import mappings for React, Tss, UI components, and Material-UI exports; enforces exhaustiveness via a switch statement that throws on unsupported module names.
Plugin mounting event and API extension
web/src/pluginSystem/pluginSystem.ts, web/src/pluginSystem/index.ts
Extends the Onyxia global type with mountComponent method and import field; introduces evtPluginComponent event to broadcast mount requests; implements the mounting mechanism to write component/container pairs into event state; re-exports from pluginSystem entry point.
App portal rendering
web/src/ui/App/App.tsx, web/src/ui/App/Main.tsx
Subscribes the App component to evtPluginComponent state changes; conditionally renders mounted components via React createPortal into the specified container; reformats Main JSX structure for readability.
Shared HomeLS3 IDE launcher
web/src/ui/shared/HomeLS3/HomeLS3.tsx, HomeLS3GitDialog.tsx, HomeLS3Hero.tsx, HomeLS3ServiceCard.tsx, index.ts
Implements a component system for IDE selection (RStudio/Jupyter/VSCode) with Git configuration via persisted state; two-step dialog validates and persists GitLab token and repository URL; hero section greets the authenticated user; service cards render with dynamic cover images; barrel export surfaces the main component.
Example plugin with DOM tracking
web/public/custom-resources-example/ls3/registerPageContainerListener.js, HomeLS3.js, main.js, ../main.js, jsconfig.json, ls3/how-to-get-my-gitlab-token.md
Demonstrates the plugin system: uses MutationObserver to track DOM element creation by route; dynamically imports HomeLS3 via the plugin allowlist; creates and mounts the component into the route container; includes JavaScript type-checking configuration and GitLab token setup documentation.
Legacy plugin cleanup
web/public/custom-resources/.gitignore, my-plugin.js
Removes the TypeScript plugin example; simplifies the JavaScript plugin to log only the Onyxia ready state; updates .gitignore to include only my-plugin.js.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A system so clever, plugins now load,
React components flow down a well-ordered road,
IDE launchers bloom with a Git-flavored dance,
The app opens portals—give mounting a chance! 🚀

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title references updating the plugin system and implementing an alternative home for LS3, which align with the main changes, but contains a typo ('aleternative' instead of 'alternative') and uses ellipsis suggesting incompleteness. Correct the typo ('aleternative' to 'alternative') and complete the title by removing the ellipsis or finishing the intended description.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch plugin-system-update

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
web/src/pluginSystem/pluginSystem.ts (1)

92-94: ⚡ Quick win

Validate container before mounting.

The container parameter is accepted without validation. If a plugin passes an invalid or detached DOM element, createPortal in App.tsx will fail silently or throw at render time.

🛡️ Proposed validation
 mountComponent: ({ Component, container }) => {
+    if (!(container instanceof HTMLElement)) {
+        throw new TypeError("container must be an HTMLElement");
+    }
+    if (!container.isConnected) {
+        console.warn("Mounting to a detached container; portal may not render.");
+    }
     evtPluginComponent.state = { Component, 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 `@web/src/pluginSystem/pluginSystem.ts` around lines 92 - 94, Validate the
plugin mount target before assigning evtPluginComponent.state in mountComponent:
ensure the passed container is a DOM Element (container instanceof Element) and
is attached to the document (document.contains(container)); if the check fails,
do not set evtPluginComponent.state and instead surface an error (e.g.,
console.error or existing logger) or throw so the failure is explicit (this
affects mountComponent, evtPluginComponent.state, Component and the createPortal
usage in App.tsx).
web/public/custom-resources-example/ls3/HomeLS3.js (1)

21-28: ⚡ Quick win

Pass children as third argument to React.createElement.

Per React conventions, children should be passed as the third argument to React.createElement(type, props, ...children) rather than inside the props object. While both approaches work, the idiomatic pattern is clearer and matches React's API design.

♻️ Proposed refactor
         return React.createElement(
             Text,
             {
                 typo: "object heading",
-                className: classes.root,
-                children: "My Alternative Home With Onyxia-ui Text"
+                className: classes.root
             },
+            "My Alternative Home With Onyxia-ui Text"
         );
🤖 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 `@web/public/custom-resources-example/ls3/HomeLS3.js` around lines 21 - 28, The
return in HomeLS3.js creates a Text element with children placed inside the
props object; update the React.createElement call to follow the idiomatic
signature by removing the children property from the props object and passing
"My Alternative Home With Onyxia-ui Text" as the third argument to
React.createElement(Text, { typo: "object heading", className: classes.root },
"My Alternative Home With Onyxia-ui Text").
web/public/custom-resources-example/ls3/main.js (1)

1-1: ⚡ Quick win

Remove unused import and commented code.

The createHomeLS3 import (line 1) is unused, and the commented-out alternative implementation (line 10) should be removed. This example demonstrates the plugin system using onyxia.import("ui/shared/HomeLS3"), so keeping the commented alternative implementation adds confusion rather than clarity.

♻️ Proposed cleanup
-import { createHomeLS3 } from "./HomeLS3.js";
 import { registerPageContainerListener } from "./registerPageContainerListener.js";

 /** `@typedef` {import("../../../src/pluginSystem").Onyxia} Onyxia */

 /** `@param` {Onyxia} onyxia */
 export async function main(onyxia) {

     const { HomeLS3 } = await onyxia.import("ui/shared/HomeLS3");
-    //const { HomeLS3 } = await createHomeLS3(onyxia);

     console.log("===>", import.meta.url);

Also applies to: 10-10

🤖 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 `@web/public/custom-resources-example/ls3/main.js` at line 1, Remove the unused
import createHomeLS3 and the commented-out alternative implementation to avoid
confusion; specifically delete the import statement referencing createHomeLS3
and remove the commented code that shows an alternative implementation (the
block that suggests using createHomeLS3 instead of
onyxia.import("ui/shared/HomeLS3")), leaving only the example that demonstrates
onyxia.import("ui/shared/HomeLS3") so the plugin usage is clear.
🤖 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 `@web/public/custom-resources-example/ls3/registerPageContainerListener.js`:
- Around line 6-34: The registerPageContainerListener function creates a
MutationObserver and never disconnects it; modify registerPageContainerListener
to return a cleanup function that disconnects the observer and clears
element_cache so observers don't accumulate. Locate
registerPageContainerListener, the local variables element_cache and observer,
and the update() closure; after observer.observe(...) add a returned function
like () => { observer.disconnect(); element_cache = undefined; } and ensure
callers invoke that cleanup on unload or when replacing listeners.

In `@web/src/ui/shared/HomeLS3.tsx`:
- Line 61: Update the French text string "Pour integrer GIT, lire ça:" in
HomeLS3.tsx to use the correct accent: change "integrer" to "intégrer" so it
reads "Pour intégrer GIT, lire ça:"; locate the literal string in the HomeLS3
component (the JSX/return text) and replace it accordingly.
- Line 43: The greeting string in the Text component in HomeLS3 (Text with prop
typo="page heading") uses the misspelled "Bienvenu"; change it to the correct
French "Bienvenue" so the rendered greeting reads "Bienvenue {user.firstName}".
Ensure you only update the string literal inside the Text component (leave the
Text component, typo prop, and user.firstName interpolation unchanged).
- Around line 95-103: The helmValuesPatch is incorrectly using a hardcoded URL
instead of the user's input: replace the hardcoded string
"https://github.com/InseeFrLab/onyxia" with the gitRepositoryUrl variable so the
patch value uses the user-provided repository; keep the existing ternary that
sets helmValuesPatch to undefined when gitRepositoryUrl is undefined and ensure
the patch entry still targets path ["git","repository"] (i.e., value:
gitRepositoryUrl).

---

Nitpick comments:
In `@web/public/custom-resources-example/ls3/HomeLS3.js`:
- Around line 21-28: The return in HomeLS3.js creates a Text element with
children placed inside the props object; update the React.createElement call to
follow the idiomatic signature by removing the children property from the props
object and passing "My Alternative Home With Onyxia-ui Text" as the third
argument to React.createElement(Text, { typo: "object heading", className:
classes.root }, "My Alternative Home With Onyxia-ui Text").

In `@web/public/custom-resources-example/ls3/main.js`:
- Line 1: Remove the unused import createHomeLS3 and the commented-out
alternative implementation to avoid confusion; specifically delete the import
statement referencing createHomeLS3 and remove the commented code that shows an
alternative implementation (the block that suggests using createHomeLS3 instead
of onyxia.import("ui/shared/HomeLS3")), leaving only the example that
demonstrates onyxia.import("ui/shared/HomeLS3") so the plugin usage is clear.

In `@web/src/pluginSystem/pluginSystem.ts`:
- Around line 92-94: Validate the plugin mount target before assigning
evtPluginComponent.state in mountComponent: ensure the passed container is a DOM
Element (container instanceof Element) and is attached to the document
(document.contains(container)); if the check fails, do not set
evtPluginComponent.state and instead surface an error (e.g., console.error or
existing logger) or throw so the failure is explicit (this affects
mountComponent, evtPluginComponent.state, Component and the createPortal usage
in App.tsx).
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5b2f9679-3226-4a00-9de9-6c37397f6f74

📥 Commits

Reviewing files that changed from the base of the PR and between 5f1e818 and 56eabe6.

📒 Files selected for processing (15)
  • web/public/custom-resources-example/jsconfig.json
  • web/public/custom-resources-example/ls3/HomeLS3.js
  • web/public/custom-resources-example/ls3/git-tutorial.md
  • web/public/custom-resources-example/ls3/main.js
  • web/public/custom-resources-example/ls3/registerPageContainerListener.js
  • web/public/custom-resources-example/main.js
  • web/public/custom-resources/.gitignore
  • web/public/custom-resources/my-plugin.js
  • web/public/custom-resources/my-plugin.ts
  • web/src/pluginSystem/index.ts
  • web/src/pluginSystem/onyxia_import.ts
  • web/src/pluginSystem/pluginSystem.ts
  • web/src/ui/App/App.tsx
  • web/src/ui/App/Main.tsx
  • web/src/ui/shared/HomeLS3.tsx
💤 Files with no reviewable changes (2)
  • web/public/custom-resources/my-plugin.ts
  • web/public/custom-resources/my-plugin.js

Comment on lines +6 to +34
export function registerPageContainerListener(routeName, listener) {

/** @type {HTMLElement | undefined} */
let element_cache = undefined;

const update = () => {
const element = document.getElementById(`page-container-${routeName}`);
if (element === null) {
return;
}
if (element === element_cache) {
return;
}
element_cache = element;
listener(element);
};

update();

const observer = new MutationObserver(() => {
update();
});

observer.observe(document.documentElement, {
childList: true,
subtree: true
});

}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Memory leak: MutationObserver never disconnected.

The MutationObserver is created and starts observing but is never disconnected. If registerPageContainerListener is called multiple times (e.g., during plugin reloads or if multiple listeners are registered), observers will accumulate in memory and continue running indefinitely, leaking memory and CPU cycles.

🔧 Proposed fix to return cleanup function
 /**
  * `@param` {string} routeName
  * `@param` {(element: HTMLElement) => void} listener
+ * `@returns` {() => void} Cleanup function to disconnect the observer
  */
 export function registerPageContainerListener(routeName, listener) {

     /** `@type` {HTMLElement | undefined} */
     let element_cache = undefined;

     const update = () => {
         const element = document.getElementById(`page-container-${routeName}`);
         if (element === null) {
             return;
         }
         if (element === element_cache) {
             return;
         }
         element_cache = element;
         listener(element);
     };

     update();

     const observer = new MutationObserver(() => {
         update();
     });

     observer.observe(document.documentElement, {
         childList: true,
         subtree: true
     });
+
+    // Return cleanup function
+    return () => {
+        observer.disconnect();
+    };

 }

Callers should store and invoke the returned cleanup function when appropriate (e.g., on plugin unload or route change).

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 9-9: It's not necessary to initialize 'element_cache' to undefined.

See more on https://sonarcloud.io/project/issues?id=InseeFrLab_onyxia&issues=AZ63IdGKGiqAEoYQuJZu&open=AZ63IdGKGiqAEoYQuJZu&pullRequest=1078

🤖 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 `@web/public/custom-resources-example/ls3/registerPageContainerListener.js`
around lines 6 - 34, The registerPageContainerListener function creates a
MutationObserver and never disconnects it; modify registerPageContainerListener
to return a cleanup function that disconnects the observer and clears
element_cache so observers don't accumulate. Locate
registerPageContainerListener, the local variables element_cache and observer,
and the update() closure; after observer.observe(...) add a returned function
like () => { observer.disconnect(); element_cache = undefined; } and ensure
callers invoke that cleanup on unload or when replacing listeners.

Comment thread web/src/ui/shared/HomeLS3.tsx Outdated
return (
<div className={classes.root}>
{user !== undefined && (
<Text typo="page heading">Bienvenu {user.firstName}</Text>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

French spelling error in greeting.

"Bienvenu" should be "Bienvenue" (with final 'e') for proper French grammar in a general welcoming context.

📝 Proposed fix
-                <Text typo="page heading">Bienvenu {user.firstName}</Text>
+                <Text typo="page heading">Bienvenue {user.firstName}</Text>
📝 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.

Suggested change
<Text typo="page heading">Bienvenu {user.firstName}</Text>
<Text typo="page heading">Bienvenue {user.firstName}</Text>
🤖 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 `@web/src/ui/shared/HomeLS3.tsx` at line 43, The greeting string in the Text
component in HomeLS3 (Text with prop typo="page heading") uses the misspelled
"Bienvenu"; change it to the correct French "Bienvenue" so the rendered greeting
reads "Bienvenue {user.firstName}". Ensure you only update the string literal
inside the Text component (leave the Text component, typo prop, and
user.firstName interpolation unchanged).

Comment thread web/src/ui/shared/HomeLS3.tsx Outdated
Comment thread web/src/ui/shared/HomeLS3.tsx Outdated
Comment on lines +95 to +103
helmValuesPatch:
gitRepositoryUrl === undefined
? undefined
: [
{
path: ["git", "repository"],
value: "https://github.com/InseeFrLab/onyxia"
}
],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical bug: Hardcoded repository URL ignores user input.

The helmValuesPatch uses a hardcoded repository URL "https://github.com/InseeFrLab/onyxia" instead of the gitRepositoryUrl state variable that the user configures via the TextField above. This means the user's Git repository input is collected but completely ignored during service launch.

🐛 Proposed fix
                     helmValuesPatch:
                         gitRepositoryUrl === undefined
                             ? undefined
                             : [
                                   {
                                       path: ["git", "repository"],
-                                      value: "https://github.com/InseeFrLab/onyxia"
+                                      value: gitRepositoryUrl
                                   }
                               ],
📝 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.

Suggested change
helmValuesPatch:
gitRepositoryUrl === undefined
? undefined
: [
{
path: ["git", "repository"],
value: "https://github.com/InseeFrLab/onyxia"
}
],
helmValuesPatch:
gitRepositoryUrl === undefined
? undefined
: [
{
path: ["git", "repository"],
value: gitRepositoryUrl
}
],
🤖 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 `@web/src/ui/shared/HomeLS3.tsx` around lines 95 - 103, The helmValuesPatch is
incorrectly using a hardcoded URL instead of the user's input: replace the
hardcoded string "https://github.com/InseeFrLab/onyxia" with the
gitRepositoryUrl variable so the patch value uses the user-provided repository;
keep the existing ternary that sets helmValuesPatch to undefined when
gitRepositoryUrl is undefined and ensure the patch entry still targets path
["git","repository"] (i.e., value: gitRepositoryUrl).

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
28.7% Duplication on New Code (required ≤ 5%)

See analysis details on SonarQube Cloud

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (2)
web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx (1)

24-26: 💤 Low value

Consider removing or populating empty style object.

The root style object is empty and serves no purpose. Either remove it if no styles are needed, or populate it with actual styling rules.

♻️ Proposed options

Option 1: Remove if unused

-const useStyles = tss.withName({ HomeLS3ServiceCard }).create(() => ({
-    root: {}
-}));

Option 2: Add actual styles if needed

 const useStyles = tss.withName({ HomeLS3ServiceCard }).create(() => ({
-    root: {}
+    root: {
+        // Add styles as needed
+    }
 }));
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx` around lines 24 - 26, The
styles object created by useStyles (tss.withName({ HomeLS3ServiceCard }).create)
contains an unused empty "root" entry; either remove the "root" property and any
references to it in the HomeLS3ServiceCard component, or populate "root" with
the needed CSS rules (e.g., layout/padding/typography) and keep useStyles as-is
— locate the useStyles declaration and the HomeLS3ServiceCard component to apply
the chosen change.
web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx (1)

182-208: 💤 Low value

Remove redundant React fragment.

The fragment wrapping the GitLab repo URL TextField (lines 182-208) contains only a single child and is redundant.

♻️ Proposed fix
             ) : (
-                <>
                     <TextField
                         label="URL du dépot GitLab"
                         helperText={<>URL du repo gitlab a cloner dans le service</>}
                         doOnlyShowErrorAfterFirstFocusLost={false}
                         defaultValue={gitlabRepoUrl ?? ""}
                         evtAction={evtTextFieldAction}
                         getIsValidValue={token => {
                             if (token !== "" && !GITLAB_REPO_REGEXP.test(token)) {
                                 return {
                                     isValidValue: false,
                                     message: <>Pas un url GitLab valide</>
                                 };
                             }
 
                             return {
                                 isValidValue: true
                             };
                         }}
                         onValueBeingTypedChange={params => {
                             setIsValidateTokenDisabled(!params.isValidValue);
                             if (params.isValidValue) {
                                 setGitlabRepoUrl(params.value);
                             }
                         }}
                     />
-                </>
             )}
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx` around lines 182 - 208, The
JSX contains a redundant React fragment wrapping a single TextField in the
HomeLS3GitDialog component; remove the surrounding fragment so the TextField is
returned directly (keep all TextField props and handlers like label, helperText,
defaultValue, evtAction, getIsValidValue, onValueBeingTypedChange and state
setters such as setGitlabRepoUrl/setIsValidateTokenDisabled unchanged) so the
component JSX remains valid without the unnecessary <>...</>.
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3.tsx`:
- Around line 62-70: The helmValuesPatch currently hardcodes the git.repository
to "https://github.com/InseeFrLab/onyxia" instead of using the user-provided
gitlabRepoUrl; update the helmValuesPatch construction (the object keyed by
helmValuesPatch in HomeLS3.tsx) so that when gitlabRepoUrl is defined you set
the patch entry's value to gitlabRepoUrl (not the hardcoded URL), preserving the
same path ["git","repository"] shape and keeping the undefined branch when
gitlabRepoUrl is undefined; make sure you reference the gitlabRepoUrl variable
in the value field so the user's input is applied.

In `@web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx`:
- Line 101: The code is storing a GitLab Personal Access Token under the
misleading key githubPersonalAccessToken; rename this key and all usages to
gitlabPersonalAccessToken to avoid cross-service credential collisions. Update
the destructuring from useCoreState (const { githubPersonalAccessToken } =
useCoreState(...)) to use gitlabPersonalAccessToken, and update every occurrence
inside HomeLS3GitDialog (including the handlers and JSX references around the
referenced lines ~114, ~120, and ~145-147) so the state read, write, validation,
and any prop names consistently use gitlabPersonalAccessToken; ensure any
set/update calls and persisted storage keys are changed to match.
- Around line 156-158: The validation error message in HomeLS3GitDialog's JSX
currently shows the incorrect GitLab token prefix "gplat-xxx"; update that
string to "glpat-xxx" so the message correctly reflects the GitLab token format.
Locate the token validation/label text inside the HomeLS3GitDialog component
(the JSX fragment showing "Un Token GitLab doit être de la forme gplat-xxx") and
replace the literal with "glpat-xxx" to fix the typo.

In `@web/src/ui/shared/HomeLS3/HomeLS3Hero.tsx`:
- Line 17: The img in HomeLS3Hero.tsx (<img
src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`} />) is
missing an alt attribute; add an appropriate alt string (e.g., "LS3 logo" or a
more descriptive phrase relevant to the site) to the <img> element in the
HomeLS3Hero component so screen readers can describe the image.
- Around line 19-23: Update the user-facing French copy in the HomeLS3Hero
component: change the heading Text (Text typo="object heading") from "Bienvenu
{userDisplayName}" to "Bienvenue {userDisplayName}" and update the subtitle Text
(Text typo="subtitle") to "Démarre ton service en quelques clics et profite de
la puissance de calcul de nos serveurs." to fix spelling, accents, plural
agreement, and noun form.

In `@web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx`:
- Line 19: Update the button label in the HomeLS3ServiceCard component to fix
the French spelling: replace the current text "Demarer un {serviceName}" in the
Button JSX (the Button with onClick={onClick}) with the correct "Démarrer un
{serviceName}" so the accent and spelling are correct while keeping the
serviceName interpolation and onClick handler unchanged.
- Line 18: The <img> in the HomeLS3ServiceCard component is missing an alt
attribute; update the img element in HomeLS3ServiceCard.tsx (the element using
coverImageUrl) to include a descriptive alt (preferably from an existing prop
like service title or a coverImageAlt prop) and fall back to an empty alt="" if
the image is purely decorative so screen readers are handled properly.

---

Nitpick comments:
In `@web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx`:
- Around line 182-208: The JSX contains a redundant React fragment wrapping a
single TextField in the HomeLS3GitDialog component; remove the surrounding
fragment so the TextField is returned directly (keep all TextField props and
handlers like label, helperText, defaultValue, evtAction, getIsValidValue,
onValueBeingTypedChange and state setters such as
setGitlabRepoUrl/setIsValidateTokenDisabled unchanged) so the component JSX
remains valid without the unnecessary <>...</>.

In `@web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx`:
- Around line 24-26: The styles object created by useStyles (tss.withName({
HomeLS3ServiceCard }).create) contains an unused empty "root" entry; either
remove the "root" property and any references to it in the HomeLS3ServiceCard
component, or populate "root" with the needed CSS rules (e.g.,
layout/padding/typography) and keep useStyles as-is — locate the useStyles
declaration and the HomeLS3ServiceCard component to apply the chosen change.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: dee1105c-ec7b-4fca-98d4-4e8a85aede5d

📥 Commits

Reviewing files that changed from the base of the PR and between 56eabe6 and 5e20b9b.

⛔ Files ignored due to path filters (3)
  • web/public/custom-resources-example/ls3/assets/Jupyter.png is excluded by !**/*.png
  • web/public/custom-resources-example/ls3/assets/RStudio.jpg is excluded by !**/*.jpg
  • web/public/custom-resources-example/ls3/assets/ls3-logo.png is excluded by !**/*.png
📒 Files selected for processing (8)
  • web/public/custom-resources-example/ls3/assets/VSCode.webp
  • web/public/custom-resources-example/ls3/how-to-get-my-gitlab-token.md
  • web/src/pluginSystem/onyxia_import.ts
  • web/src/ui/shared/HomeLS3/HomeLS3.tsx
  • web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx
  • web/src/ui/shared/HomeLS3/HomeLS3Hero.tsx
  • web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx
  • web/src/ui/shared/HomeLS3/index.ts
💤 Files with no reviewable changes (1)
  • web/public/custom-resources-example/ls3/how-to-get-my-gitlab-token.md
✅ Files skipped from review due to trivial changes (1)
  • web/src/ui/shared/HomeLS3/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/pluginSystem/onyxia_import.ts

Comment on lines +62 to +70
helmValuesPatch:
gitlabRepoUrl === undefined
? undefined
: [
{
path: ["git", "repository"],
value: "https://github.com/InseeFrLab/onyxia"
}
],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical bug: User-provided GitLab repository URL is ignored.

The helmValuesPatch sets git.repository to a hardcoded GitHub URL ("https://github.com/InseeFrLab/onyxia") instead of using the gitlabRepoUrl value collected from the user via the dialog. This completely defeats the purpose of the GitLab integration flow where users provide their own repository URL.

🐛 Proposed fix
                 helmValuesPatch:
                     gitlabRepoUrl === undefined
                         ? undefined
                         : [
                               {
                                   path: ["git", "repository"],
-                                  value: "https://github.com/InseeFrLab/onyxia"
+                                  value: gitlabRepoUrl
                               }
                           ],
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3.tsx` around lines 62 - 70, The
helmValuesPatch currently hardcodes the git.repository to
"https://github.com/InseeFrLab/onyxia" instead of using the user-provided
gitlabRepoUrl; update the helmValuesPatch construction (the object keyed by
helmValuesPatch in HomeLS3.tsx) so that when gitlabRepoUrl is defined you set
the patch entry's value to gitlabRepoUrl (not the hardcoded URL), preserving the
same path ["git","repository"] shape and keeping the undefined branch when
gitlabRepoUrl is undefined; make sure you reference the gitlabRepoUrl variable
in the value field so the user's input is applied.

}) {
const { serviceName, onProceed } = props;

const { githubPersonalAccessToken } = useCoreState("userConfigs", "userConfigs");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Major data integrity issue: GitLab token stored with GitHub key name.

The code uses the key "githubPersonalAccessToken" to store and retrieve what is actually a GitLab Personal Access Token. This naming inconsistency creates serious confusion and could lead to security issues where GitHub and GitLab credentials are mixed up or overwrite each other.

The key should be renamed to accurately reflect that it stores a GitLab token, not a GitHub token.

♻️ Proposed fix

Update the key name throughout the codebase:

-    const { githubPersonalAccessToken } = useCoreState("userConfigs", "userConfigs");
+    const { gitlabPersonalAccessToken } = useCoreState("userConfigs", "userConfigs");
                         onSubmit={token => {
                             userConfigs.changeValue({
-                                key: "githubPersonalAccessToken",
+                                key: "gitlabPersonalAccessToken",
                                 value: token
                             });
                         }}

And update line 114:

-    const doInjectGitUrl = !!githubPersonalAccessToken && !!gitlabRepoUrl;
+    const doInjectGitUrl = !!gitlabPersonalAccessToken && !!gitlabRepoUrl;

And line 120:

-            {!githubPersonalAccessToken ? (
+            {!gitlabPersonalAccessToken ? (

Also applies to: 145-147

🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx` at line 101, The code is
storing a GitLab Personal Access Token under the misleading key
githubPersonalAccessToken; rename this key and all usages to
gitlabPersonalAccessToken to avoid cross-service credential collisions. Update
the destructuring from useCoreState (const { githubPersonalAccessToken } =
useCoreState(...)) to use gitlabPersonalAccessToken, and update every occurrence
inside HomeLS3GitDialog (including the handlers and JSX references around the
referenced lines ~114, ~120, and ~145-147) so the state read, write, validation,
and any prop names consistently use gitlabPersonalAccessToken; ensure any
set/update calls and persisted storage keys are changed to match.

Comment on lines +156 to +158
Un Token GitLab doit être de la forme
gplat-xxx
</>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Typo in validation error message.

The error message contains "gplat-xxx" but the correct GitLab token prefix is "glpat-xxx" (with 'l' before 'p').

📝 Proposed fix
                                             Un Token GitLab doit être de la forme
-                                            gplat-xxx
+                                            glpat-xxx
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3GitDialog.tsx` around lines 156 - 158, The
validation error message in HomeLS3GitDialog's JSX currently shows the incorrect
GitLab token prefix "gplat-xxx"; update that string to "glpat-xxx" so the
message correctly reflects the GitLab token format. Locate the token
validation/label text inside the HomeLS3GitDialog component (the JSX fragment
showing "Un Token GitLab doit être de la forme gplat-xxx") and replace the
literal with "glpat-xxx" to fix the typo.


return (
<div className={cx(classes.root, className)}>
<img src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`} />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing alt attribute on image.

The <img> element lacks an alt attribute, which is required for accessibility. Screen readers need this to describe the image to visually impaired users.

♿ Proposed fix
-            <img src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`} />
+            <img 
+                src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`}
+                alt="Logo LS3"
+            />
📝 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.

Suggested change
<img src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`} />
<img
src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`}
alt="Logo LS3"
/>
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 17-17: img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.

See more on https://sonarcloud.io/project/issues?id=InseeFrLab_onyxia&issues=AZ64yJfnmunmQ4nJa-FH&open=AZ64yJfnmunmQ4nJa-FH&pullRequest=1078

🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3Hero.tsx` at line 17, The img in
HomeLS3Hero.tsx (<img
src={`${PUBLIC_URL}custom-resources-example/ls3/assets/ls3-logo.png`} />) is
missing an alt attribute; add an appropriate alt string (e.g., "LS3 logo" or a
more descriptive phrase relevant to the site) to the <img> element in the
HomeLS3Hero component so screen readers can describe the image.

Comment on lines +19 to +23
<Text typo="object heading">Bienvenu {userDisplayName}</Text>
<Text typo="subtitle">
Demare ton service en quelque clicks et profite de la puissance de
calcule de nos serveurs.
</Text>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

French grammar and spelling errors in user-facing text.

The text contains several French language errors:

  • Line 19: "Bienvenu" → should be "Bienvenue" (feminine/neutral form)
  • Line 21: "Demare" → should be "Démarre" (correct spelling with accent)
  • Line 21: "quelque clicks" → should be "quelques clics" (plural agreement and French word)
  • Line 22: "calcule" → should be "calcul" (noun form)
📝 Proposed fix
-                <Text typo="object heading">Bienvenu {userDisplayName}</Text>
+                <Text typo="object heading">Bienvenue {userDisplayName}</Text>
                 <Text typo="subtitle">
-                    Demare ton service en quelque clicks et profite de la puissance de
-                    calcule de nos serveurs.
+                    Démarre ton service en quelques clics et profite de la puissance de
+                    calcul de nos serveurs.
                 </Text>
📝 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.

Suggested change
<Text typo="object heading">Bienvenu {userDisplayName}</Text>
<Text typo="subtitle">
Demare ton service en quelque clicks et profite de la puissance de
calcule de nos serveurs.
</Text>
<Text typo="object heading">Bienvenue {userDisplayName}</Text>
<Text typo="subtitle">
Démarre ton service en quelques clics et profite de la puissance de
calcul de nos serveurs.
</Text>
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3Hero.tsx` around lines 19 - 23, Update the
user-facing French copy in the HomeLS3Hero component: change the heading Text
(Text typo="object heading") from "Bienvenu {userDisplayName}" to "Bienvenue
{userDisplayName}" and update the subtitle Text (Text typo="subtitle") to
"Démarre ton service en quelques clics et profite de la puissance de calcul de
nos serveurs." to fix spelling, accents, plural agreement, and noun form.


return (
<div className={cx(classes.root, className)}>
<img src={coverImageUrl} />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing alt attribute on image.

The <img> element lacks an alt attribute, which is required for accessibility. Screen readers need this to describe the service image to visually impaired users.

♿ Proposed fix
-            <img src={coverImageUrl} />
+            <img src={coverImageUrl} alt={`${serviceName} service`} />
📝 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.

Suggested change
<img src={coverImageUrl} />
<img src={coverImageUrl} alt={`${serviceName} service`} />
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 18-18: img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.

See more on https://sonarcloud.io/project/issues?id=InseeFrLab_onyxia&issues=AZ64yJimmunmQ4nJa-FJ&open=AZ64yJimmunmQ4nJa-FJ&pullRequest=1078

🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx` at line 18, The <img> in
the HomeLS3ServiceCard component is missing an alt attribute; update the img
element in HomeLS3ServiceCard.tsx (the element using coverImageUrl) to include a
descriptive alt (preferably from an existing prop like service title or a
coverImageAlt prop) and fall back to an empty alt="" if the image is purely
decorative so screen readers are handled properly.

return (
<div className={cx(classes.root, className)}>
<img src={coverImageUrl} />
<Button onClick={onClick}>Demarer un {serviceName}</Button>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

French spelling error in button text.

"Demarer" should be "Démarrer" (with accent on the first 'e' and double 'r').

📝 Proposed fix
-            <Button onClick={onClick}>Demarer un {serviceName}</Button>
+            <Button onClick={onClick}>Démarrer un {serviceName}</Button>
📝 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.

Suggested change
<Button onClick={onClick}>Demarer un {serviceName}</Button>
<Button onClick={onClick}>Démarrer un {serviceName}</Button>
🤖 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 `@web/src/ui/shared/HomeLS3/HomeLS3ServiceCard.tsx` at line 19, Update the
button label in the HomeLS3ServiceCard component to fix the French spelling:
replace the current text "Demarer un {serviceName}" in the Button JSX (the
Button with onClick={onClick}) with the correct "Démarrer un {serviceName}" so
the accent and spelling are correct while keeping the serviceName interpolation
and onClick handler unchanged.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant