Closed cmoulliard closed 6 months ago
cc @tumido
@tumido Have you been able to have a look ? Can I help you ?
Yes, this is currently not possible. I'm not sure if we want to evolve and enhance the current dynamic frontend system while there's parallel work ongoing in the upstream.
I'm not sure if we want to evolve and enhance the current dynamic frontend system while there's parallel work ongoing in the upstream.
I don't think it makes sense to add more features in the current dynamic frontend system which will risk making it more difficult to converge with the parallel upstream work. If it doesn't prevent the core feature of the Quarkus plugin to work, then let's postpone the scaffolder field extension for later.
@christophe-f what do you think ?
@cmoulliard ^^
2. how many of those quarkus extensions would be listed and are they always installation dependent?
Until now we have developed 3 fields and soon we will have 4. They are needed when a user scaffold a project using a template including them
2. I.e. could the interim solution be a static dropdown that's populated in the template?
This is doable but as the list of the quarkus versions change when new quarkus are out (like also the extensions liust), then it will be needed to find a way to populate the list using values passed as app-config.yaml field/parameter (aka similar to what users do with their git servers, etc)
There is something that I dont understand. Even if this is not well documented, backstage-next offers a way to configure some additional fields as you can see here: https://github.com/backstage/backstage/blob/master/packages/app-next/app-config.yaml#L149-L156
- scaffolder.page:
config:
groups:
- title: Recommended
filter:
entity.metadata.tags: recommended
- scaffolder.page/fields: '@backstage/plugin-scaffolder#LowerCaseValuePickerFieldExtension'
- scaffolder.page/layout: '@backstage/plugin-scaffolder#TwoColumnLayout'
Question: Does it work or not ? Is it something that we could use with backstage-showcase
?
Surely, that's the plan, but this backstage-next
things were not available when the dynamic frontend plugins were introduced into the Janus showcase, which explains why we had to start with something Janus-specific which covered the main needs on the Janus side.
The plan is now to:
That's precisely why we want to avoid, as much as possible, investing more in the Janus-specific implementation.
- dynamic frontend plugin system
Is there a great example well documented explaining how to create a new front plugin, build it and configure it ?
Is there a great example well documented explaining how to create a new front plugin, build it and configure it ?
It's currently in progress.
This is definitely something that we need to provide. Platform engineers will need to add custom FieldExtension.
I started to experiment/play with new frontend using app-next
package of backstage = 1.25 where I included the scaffolderPlugin
within the App.tsx
file
const app = createApp({
features: [
graphiqlPlugin,
pagesPlugin,
techRadarPlugin,
techdocsPlugin,
userSettingsPlugin,
homePlugin,
appVisualizerPlugin,
scaffolderPlugin,
...
and declared (based on existing example) such a field declaration within the app-config.yaml
file but that fails
- scaffolder.page/fields: '@backstage/plugin-scaffolder#LowerCaseValuePickerFieldExtension'
Error reported "Invalid extension configuration at app.extensions[19][scaffolder.page/fields], value must be a boolean or object"
Raised by this code:
// backstage/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts)
if (typeof value !== 'object' || Array.isArray(value)) {
// We don't mention null here - we don't want people to explicitly enter
// - entity.card.about: null
throw new Error(errorMsg('value must be a boolean or object', id));
}
I digged into the code and found how backstage is able to discover the custom template fields ;-)
Such a mechanism is taking place here within the scaffolderpage
/**
* The Router and main entrypoint to the Scaffolder plugin.
*
* @public
*/
export const ScaffolderPage = scaffolderPlugin.provide(
createRoutableExtension({
name: 'ScaffolderPage',
component: () => import('./components/Router').then(m => m.Router),
mountPoint: rootRouteRef,
}),
);
which creates a routableExtension using the Router.tsx component. The router.tsx contains a const instantiated from a function useCustomFieldExtensions() using either the react router dom => outlet()
or props.children
.
// https://github.com/backstage/backstage/blob/master/plugins/scaffolder/src/components/Router/Router.tsx#L110-L112
...
const outlet = useOutlet() || props.children;
const customFieldExtensions =
useCustomFieldExtensions<FieldExtensionOptions>(outlet);
...
and
// https://github.com/backstage/backstage/blob/master/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts#L32-L39
import { useElementFilter } from '@backstage/core-plugin-api';
import { FieldExtensionOptions } from '../extensions';
import {
FIELD_EXTENSION_KEY,
FIELD_EXTENSION_WRAPPER_KEY,
} from '../extensions/keys';
/**
* Hook that returns all custom field extensions from the current outlet.
* @public
*/
export const useCustomFieldExtensions = <
TComponentDataType = FieldExtensionOptions,
>(
outlet: React.ReactNode,
) => {
return useElementFilter(outlet, elements =>
elements
.selectByComponentData({
key: FIELD_EXTENSION_WRAPPER_KEY,
})
.findComponentData<TComponentDataType>({
key: FIELD_EXTENSION_KEY,
}),
);
}
Do you think that we could pass the props.children
(or register the componentData within the outlet. How ? IDK) to the router using a new parameter created within the janus-idp front-end yaml file and containing ?
@gashcrumb @tumido
Support to register scaffolderPlugin.provide
It is not possible today to register using the dynamic configuration, a plugin packaging
ScaffolderFieldExtension
. Such fields which are React field components are used part of a backstage template and are registered as such