From 37ab71200193ab9ea08dcea6918cec18583dd3e8 Mon Sep 17 00:00:00 2001
From: Juan Pablo Garcia Ripa
Date: Sat, 11 Jan 2025 12:00:19 +0100
Subject: [PATCH 01/37] fix: add validation for the `each` values
Signed-off-by: Juan Pablo Garcia Ripa
---
.changeset/fair-rocks-dream.md | 5 +++++
.../tasks/NunjucksWorkflowRunner.test.ts | 21 +++++++++++++++++++
.../tasks/NunjucksWorkflowRunner.ts | 20 ++++++++++++------
3 files changed, 40 insertions(+), 6 deletions(-)
create mode 100644 .changeset/fair-rocks-dream.md
diff --git a/.changeset/fair-rocks-dream.md b/.changeset/fair-rocks-dream.md
new file mode 100644
index 0000000000..4d33a60bcd
--- /dev/null
+++ b/.changeset/fair-rocks-dream.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+add validation for `each` values
diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts
index 7e204d35df..31ba7195b2 100644
--- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts
@@ -988,6 +988,27 @@ describe('NunjucksWorkflowRunner', () => {
);
expect(fakeActionHandler).not.toHaveBeenCalled();
});
+
+ it('should validate each parameter renders to a valid value', async () => {
+ const task = createMockTaskWithSpec({
+ apiVersion: 'scaffolder.backstage.io/v1beta3',
+ steps: [
+ {
+ id: 'test',
+ name: 'name',
+ each: '${{parameters.data}}',
+ action: 'jest-validated-action',
+ input: { foo: '${{each.value}}' },
+ },
+ ],
+ output: {},
+ parameters: {},
+ });
+ await expect(runner.execute(task)).rejects.toThrow(
+ 'Invalid each value passed to action jest-validated-action, "${{parameters.data}}" cannot be resolved to a value',
+ );
+ expect(fakeActionHandler).not.toHaveBeenCalled();
+ });
});
describe('secrets', () => {
diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts
index ad9d85cb2d..9865f4db87 100644
--- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts
@@ -304,13 +304,21 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
return;
}
}
+
+ const resolvedEach =
+ step.each && this.render(step.each, context, renderTemplate);
+
+ if (step.each && !resolvedEach) {
+ throw new InputError(
+ `Invalid each value passed to action ${action.id}, "${step.each}" cannot be resolved to a value`,
+ );
+ }
+
const iterations = (
- step.each
- ? Object.entries(this.render(step.each, context, renderTemplate)).map(
- ([key, value]) => ({
- each: { key, value },
- }),
- )
+ resolvedEach
+ ? Object.entries(resolvedEach).map(([key, value]) => ({
+ each: { key, value },
+ }))
: [{}]
).map(i => ({
...i,
From 9fc6ffc33e40d89c19d83a5dff4bc2ba52dd6708 Mon Sep 17 00:00:00 2001
From: Juan Pablo Garcia Ripa
Date: Wed, 15 Jan 2025 13:56:35 +0100
Subject: [PATCH 02/37] update changes message
Co-authored-by: Vincenzo Scamporlino
Signed-off-by: Juan Pablo Garcia Ripa
---
.changeset/fair-rocks-dream.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.changeset/fair-rocks-dream.md b/.changeset/fair-rocks-dream.md
index 4d33a60bcd..d1f7f3f0f7 100644
--- a/.changeset/fair-rocks-dream.md
+++ b/.changeset/fair-rocks-dream.md
@@ -2,4 +2,4 @@
'@backstage/plugin-scaffolder-backend': patch
---
-add validation for `each` values
+Fixed an issue where invalid expressions or non-object values in `step.each` caused an error.
From dd2edbc6dfe686a3bc6e6f90eda638064b05d20f Mon Sep 17 00:00:00 2001
From: Alisson Fabiano
Date: Tue, 21 Jan 2025 15:16:36 -0300
Subject: [PATCH 03/37] fix log stream component to take up remaining space
Signed-off-by: Alisson Fabiano
---
.../src/components/OngoingTask/OngoingTask.tsx | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx
index ffcc377995..97047d00c9 100644
--- a/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx
+++ b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx
@@ -20,7 +20,6 @@ import Box from '@material-ui/core/Box';
import Button from '@material-ui/core/Button';
import Paper from '@material-ui/core/Paper';
import { makeStyles } from '@material-ui/core/styles';
-import { ResizableBox } from 'react-resizable';
import {
ScaffolderTaskOutput,
scaffolderApiRef,
@@ -119,6 +118,7 @@ export const OngoingTask = (props: {
useEffect(() => {
if (taskStream.completed && !taskStream.error) {
+ setLogVisibleState(true);
setButtonBarVisibleState(false);
}
}, [taskStream.error, taskStream.completed]);
@@ -292,13 +292,11 @@ export const OngoingTask = (props: {
) : null}
{logsVisible ? (
-
-
-
-
-
-
-
+
+
+
+
+
) : null}
From b11d5cc5da562211d7fc0329dadf1457fd49c7ce Mon Sep 17 00:00:00 2001
From: Alisson Fabiano
Date: Tue, 21 Jan 2025 15:16:46 -0300
Subject: [PATCH 04/37] add feature to move scroll to the end of lines
Signed-off-by: Alisson Fabiano
---
.../components/LogViewer/RealLogViewer.tsx | 29 ++++++++++++++-----
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx
index cbeb249815..37768ad80b 100644
--- a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx
+++ b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx
@@ -18,12 +18,12 @@ import Box from '@material-ui/core/Box';
import IconButton from '@material-ui/core/IconButton';
import CopyIcon from '@material-ui/icons/FileCopy';
import classnames from 'classnames';
-import React, { useEffect, useMemo, useRef } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom';
import AutoSizer from 'react-virtualized-auto-sizer';
import { FixedSizeList } from 'react-window';
-import { AnsiProcessor } from './AnsiProcessor';
+import { AnsiLine, AnsiProcessor } from './AnsiProcessor';
import { LogLine } from './LogLine';
import { LogViewerControls } from './LogViewerControls';
import { HEADER_SIZE, useStyles } from './styles';
@@ -37,7 +37,9 @@ export interface RealLogViewerProps {
export function RealLogViewer(props: RealLogViewerProps) {
const classes = useStyles({ classes: props.classes });
- const listRef = useRef(null);
+ const [fixedListInstance, setFixedListInstance] = useState | null>(null);
// The processor keeps state that optimizes appending to the text
const processor = useMemo(() => new AnsiProcessor(), []);
@@ -48,10 +50,21 @@ export function RealLogViewer(props: RealLogViewerProps) {
const location = useLocation();
useEffect(() => {
- if (search.resultLine !== undefined && listRef.current) {
- listRef.current.scrollToItem(search.resultLine - 1, 'center');
+ if (fixedListInstance) {
+ fixedListInstance.scrollToItem(lines.length - 1, 'end');
}
- }, [search.resultLine]);
+ }, [fixedListInstance, lines]);
+
+ useEffect(() => {
+ if (!fixedListInstance) {
+ return;
+ }
+ if (search.resultLine) {
+ fixedListInstance.scrollToItem(search.resultLine - 1, 'center');
+ } else {
+ fixedListInstance.scrollToItem(lines.length - 1, 'end');
+ }
+ }, [fixedListInstance, search.resultLine, lines]);
useEffect(() => {
if (location.hash) {
@@ -76,7 +89,9 @@ export function RealLogViewer(props: RealLogViewerProps) {
) => {
+ setFixedListInstance(instance);
+ }}
className={classes.log}
height={(height || 480) - HEADER_SIZE}
width={width || 640}
From 17088d22bc11f7a21f35dee39d2c59032f3d4e1f Mon Sep 17 00:00:00 2001
From: Alisson Fabiano
Date: Tue, 21 Jan 2025 15:16:57 -0300
Subject: [PATCH 05/37] add changeset
Signed-off-by: Alisson Fabiano
---
.changeset/loud-baboons-relate.md | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 .changeset/loud-baboons-relate.md
diff --git a/.changeset/loud-baboons-relate.md b/.changeset/loud-baboons-relate.md
new file mode 100644
index 0000000000..408188abd0
--- /dev/null
+++ b/.changeset/loud-baboons-relate.md
@@ -0,0 +1,7 @@
+---
+'@backstage/core-components': minor
+'@backstage/plugin-scaffolder': minor
+---
+
+Changes the TaskLogStream to take up all remaining space
+Changes the RealLogViewer to always display the last line by default
From 524f0afb309c6c1708092a2b0a73bf8275792fc5 Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Wed, 22 Jan 2025 12:01:48 +0100
Subject: [PATCH 06/37] techdocs: add missing alpha entity content route ref
Signed-off-by: Patrik Oldsberg
---
.changeset/fifty-turtles-count.md | 5 +++++
plugins/techdocs/src/alpha.tsx | 1 +
2 files changed, 6 insertions(+)
create mode 100644 .changeset/fifty-turtles-count.md
diff --git a/.changeset/fifty-turtles-count.md b/.changeset/fifty-turtles-count.md
new file mode 100644
index 0000000000..76bea0dcaa
--- /dev/null
+++ b/.changeset/fifty-turtles-count.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Add missing route ref to the `/alpha` entity content extension.
diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx
index e0e1c1761e..a9ac353753 100644
--- a/plugins/techdocs/src/alpha.tsx
+++ b/plugins/techdocs/src/alpha.tsx
@@ -170,6 +170,7 @@ const techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({
{
defaultPath: 'docs',
defaultTitle: 'TechDocs',
+ routeRef: convertLegacyRouteRef(rootCatalogDocsRouteRef),
loader: () =>
import('./Router').then(({ EmbeddedDocsRouter }) =>
compatWrapper(
From d3246272521de2c9091de72a8cfa2392d131acca Mon Sep 17 00:00:00 2001
From: Charles de Dreuille
Date: Wed, 22 Jan 2025 22:26:47 +0000
Subject: [PATCH 07/37] Update docs + css variables
Signed-off-by: Charles de Dreuille
---
.../src/app/(docs)/components/button/page.mdx | 8 +-
.../app/(docs)/components/heading/page.mdx | 4 +-
.../src/app/(docs)/components/table/page.mdx | 2 +-
.../src/app/(docs)/components/text/page.mdx | 4 +-
.../src/app/(docs)/theme/theming/page.mdx | 555 ++++++++++++++----
canon-docs/src/app/globals.css | 2 +-
canon-docs/src/app/page.module.css | 2 +-
.../components/CodeBlock/styles.module.css | 2 +-
.../components/CustomTheme/styles.module.css | 2 +-
.../HeadlessBanners/styles.module.css | 4 +-
.../src/components/Sidebar/Sidebar.module.css | 8 +-
.../src/components/Table/styles.module.css | 2 +-
canon-docs/src/components/Tabs/parts.tsx | 4 +-
.../src/components/Tabs/styles.module.css | 2 +-
.../src/components/Toolbar/nav.module.css | 12 +-
.../src/components/Toolbar/theme.module.css | 10 +-
canon-docs/src/mdx-components.tsx | 7 +-
canon-docs/src/snippets/_snippets.ts | 31 +
canon-docs/src/snippets/button.tsx | 7 +-
canon-docs/src/snippets/heading.tsx | 3 +-
canon-docs/src/snippets/text.tsx | 5 +-
.../canon/.storybook/themes/backstage.css | 8 +-
.../canon/src/components/Box/Box.stories.tsx | 2 +-
packages/canon/src/components/Box/styles.css | 2 +-
.../canon/src/components/Button/styles.css | 8 +-
.../canon/src/components/Checkbox/styles.css | 2 +-
.../src/components/Field/Field.styles.css | 6 +-
.../canon/src/components/Heading/styles.css | 2 +-
.../src/components/Input/Input.styles.css | 4 +-
packages/canon/src/components/Text/styles.css | 2 +-
packages/canon/src/css/core.css | 23 +-
31 files changed, 553 insertions(+), 182 deletions(-)
diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx
index c35c4888f3..e0b0a89f31 100644
--- a/canon-docs/src/app/(docs)/components/button/page.mdx
+++ b/canon-docs/src/app/(docs)/components/button/page.mdx
@@ -167,9 +167,7 @@ Here's a view when buttons are responsive.
py={4}
open
preview={ }
- code={`
- Button
- `}
+ code={`
+ Responsive Button
+ `}
/>
diff --git a/canon-docs/src/app/(docs)/components/heading/page.mdx b/canon-docs/src/app/(docs)/components/heading/page.mdx
index 4e3b0aa46c..e843e131ce 100644
--- a/canon-docs/src/app/(docs)/components/heading/page.mdx
+++ b/canon-docs/src/app/(docs)/components/heading/page.mdx
@@ -93,5 +93,7 @@ on the screen size.
py={4}
open
preview={ }
- code={`Responsive `}
+ code={`
+ Responsive heading
+ `}
/>
diff --git a/canon-docs/src/app/(docs)/components/table/page.mdx b/canon-docs/src/app/(docs)/components/table/page.mdx
index f91505acf6..f169bcd7f9 100644
--- a/canon-docs/src/app/(docs)/components/table/page.mdx
+++ b/canon-docs/src/app/(docs)/components/table/page.mdx
@@ -1 +1 @@
-# Table
+# Table (Coming soon)
diff --git a/canon-docs/src/app/(docs)/components/text/page.mdx b/canon-docs/src/app/(docs)/components/text/page.mdx
index 79f9f96a6b..6d96fc5da3 100644
--- a/canon-docs/src/app/(docs)/components/text/page.mdx
+++ b/canon-docs/src/app/(docs)/components/text/page.mdx
@@ -137,5 +137,7 @@ on the screen size.
}
- code={`Responsive `}
+ code={`
+ Responsive text
+ `}
/>
diff --git a/canon-docs/src/app/(docs)/theme/theming/page.mdx b/canon-docs/src/app/(docs)/theme/theming/page.mdx
index 3a16b533e9..14cd06cb8f 100644
--- a/canon-docs/src/app/(docs)/theme/theming/page.mdx
+++ b/canon-docs/src/app/(docs)/theme/theming/page.mdx
@@ -1,67 +1,70 @@
import { CodeBlock } from '@/components/CodeBlock';
import * as Table from '@/components/Table';
import { Chip } from '@/components/Chip';
+import { customTheme } from '@/snippets/_snippets';
# Theming
-Backstage ships with a default theme with a light and dark mode variant. The
-themes are provided as a part of the `@backstage/canon` package, which also
-includes utilities for customizing the default theme, or creating completely
-new themes.
+Canon's theming is built entirely on CSS, without relying on any CSS-in-JS libraries.
+At its core, it provides a solid default theme that is easily customizable using a
+comprehensive set of CSS variables. Additionally, it enables anyone to adapt the design
+to their specific needs. Each component comes with fixed class names, making customization
+even more straightforward.
## Light & Dark modes
-By default we are supporting both light and dark modes. Each user can opt to
-choose what theme they want to use or to use their system decide what theme to
-use. If you want to create your own theme, you will have to set both light and
-dark themes following the instructions below. If you only set one of them, the
-other mode will fallback to the default theme.
+By default, Canon supports both light and dark modes using the `data-theme` attribute.
+The light theme is applied by default if no `data-theme` attribute is specified. To create
+a custom theme, you'll need to define both light and dark modes as outlined below. If
+only one mode is defined, the other will fall back to the default theme.
## How to create your own theme
-To create your own theme, you will have to define the variables below. To do
-that, create a theme.css file and import it in your application. Here's an
-example below on how to set your light and dark mode.
+In our [started guide](/), we ask you to import two css files. The `core.css` file includes
+the default set of variables. We recommend to keep this file in place and add your own theme
+on top of it. `core.css` also include an opinionated reset. If you decided to remove `core.css`
+you will have to provide your own reset css.
-
+Here's an example of how your theme.css file should look like:
-## Colors
+
-We provide a set of generic colours tokens that we use across Canon. By
-changing these colours you can easily change the look and feel of your
-application to match your brand.
+## Available CSS variables
+
+### Core background colors
+
+These colors are used for the background of your application. We are mostly using for now a
+single elevated background for panels. `--canon-bg` should mostly use as the main background
+color of your app.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-bg
+
+ The background color of your Backstage instance.
+
+
+
+ --canon-bg-elevated
+
+ Use for any panels or elevated surfaces.
+
+
+
+
+### Component background colors
+
+These colors are meants for interactive components like buttons, callout avatar, chips, ...
+We have two main level of background you can customise. The accent one is mostly used as a primary option
+for interactive components. The tint one is used for secondary components like callouts, avatars, ...
@@ -75,54 +78,254 @@ application to match your brand.
--canon-bg-accent
- The accent color for the theme.
+ Used mostly for primary interactive components.
- --canon-bg
+ --canon-bg-accent-hover
+
+
+ Used for interactive components when they are hovered.
- The background color for the theme.
- --canon-bg-elevated
+ --canon-bg-accent-focus
+
+
+ Used for interactive components when they are in focus.
- The first surface color for the theme.
- --canon-bg
+ --canon-bg-accent-disabled
+
+
+ Used for interactive components when they are disabled.
- The second surface color for the theme.
- --canon-outline
+ --canon-bg-tint
- The outline color for the theme.
+ Used for secondary interactive components.
- --canon-outline-focus
+ --canon-bg-tint-hover
+
+
+ Used for interactive components when they are hovered.
- The outline focus color for the theme.
- --canon-text-primary
+ --canon-bg-tint-focus
+
+
+ Used for interactive components when they are active.
- The primary text color for the theme.
- --canon-text-secondary
+ --canon-bg-tint-disabled
+
+
+ Used for interactive components when they are disabled.
- The secondary text color for the theme.
-## Typography
+### Status background colors
+
+These backgrounds are intended for non-interactive elements to visually convey a specific state.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-bg-danger
+
+ Used to show errors informations.
+
+
+
+ --canon-bg-warning
+
+ Used to show warnings informations.
+
+
+
+ --canon-bg-success
+
+ Used to show success informations.
+
+
+
+
+### Foreground colors
+
+Foreground colours are meant to work in pair with a background colours. Typeically this would work
+for icons, texts, shapes, ... Use a matching name to know what foreground color to use. These colors
+are prefixed with `fg` to make it easier to identify.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-fg-primary
+
+
+ It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
+
+
+
+
+ --canon-fg-secondary
+
+
+ It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
+
+
+
+
+ --canon-fg-link
+
+
+ It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
+
+
+
+
+ --canon-fg-link-hover
+
+
+ It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
+
+
+
+
+ --canon-fg-accent
+
+ It should be used on top of `--canon-bg-accent`.
+
+
+
+ --canon-fg-tint
+
+ It should be used on top of `--canon-bg-tint`.
+
+
+
+ --canon-fg-danger
+
+ It should be used on top of `--canon-bg-danger`.
+
+
+
+ --canon-fg-warning
+
+ It should be used on top of `--canon-bg-warning`.
+
+
+
+ --canon-fg-success
+
+ It should be used on top of `--canon-bg-success`.
+
+
+
+
+### Border colors
+
+These border colors are mostly meant to be used as borders on top of any components with
+low contrast to help as a separator with the different background colors.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-border
+
+
+ It should be used on top of `--canon-bg-elevated`.
+
+
+
+
+ --canon-border-hover
+
+
+ Used when the component is interactive and hovered.
+
+
+
+
+ --canon-border-focus
+
+
+ Used when the component is interactive and focused.
+
+
+
+
+ --canon-border-tint
+
+ It should be used on top of `--canon-bg-tint`.
+
+
+
+ --canon-border-tint-hover
+
+ Used when the component is hovered.
+
+
+
+ --canon-border-tint-focus
+
+ Used when the component is in focus.
+
+
+
+ --canon-border-danger
+
+ It should be used on top of `--canon-bg-danger`.
+
+
+
+ --canon-border-warning
+
+ It should be used on top of `--canon-bg-warning`.
+
+
+
+ --canon-border-success
+
+ It should be used on top of `--canon-bg-success`.
+
+
+
+
+## Font families
We have two fonts that we use across Canon. The first one is the sans-serif
font that we use for the body of the application. The second one is the
@@ -151,12 +354,9 @@ monospace font that we use for code blocks and tables.
-## Spacing
+## Font weights
-Our default spacing system is made to work in most scenarios. We have 7 scale
-values from `xxs` to `xxl`. We use the values on padding and margin in our
-layout components mostly. If you prefer to use a different spacing system, you
-can do that by changing the values below.
+We have two font weights that we use across Canon. Regular or Bold
@@ -168,53 +368,184 @@ can do that by changing the values below.
- --canon-space-unit
-
-
- The base unit for the spacing system. Default value is `1em`
+ --canon-font-weight-regular
+ The regular font weight for the theme.
- --canon-space-xxs
+ --canon-font-weight-bold
- Default value is `0.25 x space unit`
-
-
-
- --canon-space-xs
-
- Default value is `0.5 x space unit`
-
-
-
- --canon-space-sm
-
- Default value is `0.75 x space unit`
-
-
-
- --canon-space-md
-
- Default value is `1.25 x space unit`
-
-
-
- --canon-space-lg
-
- Default value is `2 x space unit`
-
-
-
- --canon-space-xl
-
- Default value is `3.25 x space unit`
-
-
-
- --canon-space-xxl
-
- Default value is `5.25 x space unit`
+ The bold font weight for the theme.
+
+
+
+
+## Spacing
+
+We built a spacing system based on a single value `--canon-space`. This value is
+used to calculate the spacing for all the components. By default if you would like to
+increase or decrease the spacing between your components you can do it simply by updating
+`--canon-space` and it will apply to all spacing values.
+
+`--canon-space` is not used directly in any components but serve as an easy way to
+calculate the other values.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-space
+
+
+ The base unit for the spacing system. Default value is `0.25rem`.
+
+
+
+
+
+Below is the list of all spacing values you can use in your application. We use these
+tokens for pretty much each spacing properties like padding, margin, gaps, ...
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-space-0_5
+
+ Base unit (`--canon-space`) times 0.5.
+
+
+
+ --canon-space-1
+
+ Base unit (`--canon-space`).
+
+
+
+ --canon-space-1_5
+
+ Base unit (`--canon-space`) times 1.5.
+
+
+
+ --canon-space-2
+
+ Base unit (`--canon-space`) times 2.
+
+
+
+ --canon-space-3
+
+ Base unit (`--canon-space`) times 3.
+
+
+
+ --canon-space-4
+
+ Base unit (`--canon-space`) times 4.
+
+
+
+ --canon-space-5
+
+ Base unit (`--canon-space`) times 5.
+
+
+
+ --canon-space-6
+
+ Base unit (`--canon-space`) times 6.
+
+
+
+ --canon-space-7
+
+ Base unit (`--canon-space`) times 7.
+
+
+
+ --canon-space-8
+
+ Base unit (`--canon-space`) times 8.
+
+
+
+ --canon-space-9
+
+ Base unit (`--canon-space`) times 9.
+
+
+
+ --canon-space-10
+
+ Base unit (`--canon-space`) times 10.
+
+
+
+ --canon-space-11
+
+ Base unit (`--canon-space`) times 11.
+
+
+
+ --canon-space-12
+
+ Base unit (`--canon-space`) times 12.
+
+
+
+ --canon-space-13
+
+ Base unit (`--canon-space`) times 13.
+
+
+
+ --canon-space-14
+
+ Base unit (`--canon-space`) times 14.
+
+
+
+
+### Radius (Work in progress)
+
+Our radius system is a little bit different from spacing as we use a factor to calculate the radius values.
+Under the hood different components uses different radius values. For example, button can be set to have full radius
+while a checkbox will have to remain a square.
+
+Here are the different radius factor we recommend to use
+
+- None: `0`
+- Small: `0.75`
+- Medium: `1`
+- Large: `1.5`
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-radius-factor
+
+ By default the value is set to medium `1`.
diff --git a/canon-docs/src/app/globals.css b/canon-docs/src/app/globals.css
index 71f7b8be9c..6f3702c950 100644
--- a/canon-docs/src/app/globals.css
+++ b/canon-docs/src/app/globals.css
@@ -2,7 +2,7 @@ body {
display: flex;
flex-direction: row;
background-color: var(--canon-bg);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
transition: background-color 0.2s ease-in-out;
--docs-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
diff --git a/canon-docs/src/app/page.module.css b/canon-docs/src/app/page.module.css
index b0fbed71c1..3d22802a3c 100644
--- a/canon-docs/src/app/page.module.css
+++ b/canon-docs/src/app/page.module.css
@@ -17,7 +17,7 @@
}
.page p {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
font-size: 1rem;
line-height: 1.5rem;
margin-top: 0;
diff --git a/canon-docs/src/components/CodeBlock/styles.module.css b/canon-docs/src/components/CodeBlock/styles.module.css
index b5f005f962..fcd5309f14 100644
--- a/canon-docs/src/components/CodeBlock/styles.module.css
+++ b/canon-docs/src/components/CodeBlock/styles.module.css
@@ -18,7 +18,7 @@
border-bottom: 1px solid var(--canon-border);
padding: 12px 20px;
font-size: 0.875rem;
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
}
.code {
diff --git a/canon-docs/src/components/CustomTheme/styles.module.css b/canon-docs/src/components/CustomTheme/styles.module.css
index fdb2d00fba..8f72b15d02 100644
--- a/canon-docs/src/components/CustomTheme/styles.module.css
+++ b/canon-docs/src/components/CustomTheme/styles.module.css
@@ -66,7 +66,7 @@
padding: 0 8px;
color: #fff;
background-color: var(--canon-bg);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
transition: background-color 0.2s ease-in-out;
border-radius: 0.25rem;
cursor: pointer;
diff --git a/canon-docs/src/components/HeadlessBanners/styles.module.css b/canon-docs/src/components/HeadlessBanners/styles.module.css
index 1353f150bb..6cbb107aa7 100644
--- a/canon-docs/src/components/HeadlessBanners/styles.module.css
+++ b/canon-docs/src/components/HeadlessBanners/styles.module.css
@@ -10,7 +10,7 @@
}
.icon path {
- fill: var(--canon-text-primary);
+ fill: var(--canon-fg-primary);
}
.content {
@@ -37,6 +37,6 @@
border-radius: 100px;
margin-top: var(--canon-space-3);
font-size: var(--canon-font-size-3);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
gap: var(--canon-space-2);
}
diff --git a/canon-docs/src/components/Sidebar/Sidebar.module.css b/canon-docs/src/components/Sidebar/Sidebar.module.css
index 43f1681812..d87be799d0 100644
--- a/canon-docs/src/components/Sidebar/Sidebar.module.css
+++ b/canon-docs/src/components/Sidebar/Sidebar.module.css
@@ -10,7 +10,7 @@
left: 0;
width: 300px;
height: 100vh;
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
background-color: var(--canon-bg-elevated);
border-right: 1px solid var(--canon-border);
padding-left: 20px;
@@ -26,7 +26,7 @@
}
.logo path {
- fill: var(--canon-text-primary);
+ fill: var(--canon-fg-primary);
}
.menu {
@@ -75,11 +75,11 @@
font-family: var(--docs-font);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
.lineStatus {
font-family: var(--docs-font);
font-size: var(--canon-font-size-3);
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
}
diff --git a/canon-docs/src/components/Table/styles.module.css b/canon-docs/src/components/Table/styles.module.css
index 7ac48709eb..9b67b25025 100644
--- a/canon-docs/src/components/Table/styles.module.css
+++ b/canon-docs/src/components/Table/styles.module.css
@@ -38,7 +38,7 @@
transition: background-color 0.2s ease-in-out;
& p {
- margin: 0;
+ margin: 0 !important;
}
}
diff --git a/canon-docs/src/components/Tabs/parts.tsx b/canon-docs/src/components/Tabs/parts.tsx
index e0ae296136..0139d3be1a 100644
--- a/canon-docs/src/components/Tabs/parts.tsx
+++ b/canon-docs/src/components/Tabs/parts.tsx
@@ -34,8 +34,8 @@ export const Tab = (props: React.ComponentProps) => (
{...rest}
style={{
color: state.selected
- ? 'var(--canon-text-primary)'
- : 'var(--canon-text-secondary)',
+ ? 'var(--canon-fg-primary)'
+ : 'var(--canon-fg-secondary)',
}}
>
{children}
diff --git a/canon-docs/src/components/Tabs/styles.module.css b/canon-docs/src/components/Tabs/styles.module.css
index 8d898fd727..2ce4d81064 100644
--- a/canon-docs/src/components/Tabs/styles.module.css
+++ b/canon-docs/src/components/Tabs/styles.module.css
@@ -22,6 +22,6 @@
left: var(--active-tab-left);
width: var(--active-tab-width);
height: 1px;
- background-color: var(--canon-text-primary);
+ background-color: var(--canon-fg-primary);
transition: all 0.2s ease-in-out;
}
diff --git a/canon-docs/src/components/Toolbar/nav.module.css b/canon-docs/src/components/Toolbar/nav.module.css
index 90730b1403..123817c323 100644
--- a/canon-docs/src/components/Toolbar/nav.module.css
+++ b/canon-docs/src/components/Toolbar/nav.module.css
@@ -27,21 +27,21 @@
all: unset;
height: 60px;
font-family: var(--docs-font);
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-bold);
cursor: pointer;
transition: color 0.2s ease-in-out;
&:hover {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
&[data-selected] {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
& p {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
}
@@ -60,7 +60,7 @@
}
.tab p {
- color: var(--canon-text-secondary) !important;
+ color: var(--canon-fg-secondary) !important;
}
.indicator {
@@ -72,7 +72,7 @@
width: var(--active-tab-width);
height: 1px;
border-radius: 0.25rem;
- background-color: var(--canon-text-primary);
+ background-color: var(--canon-fg-primary);
transition-property: translate, width, background-color;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
diff --git a/canon-docs/src/components/Toolbar/theme.module.css b/canon-docs/src/components/Toolbar/theme.module.css
index 564f5be4ca..4da56e31f3 100644
--- a/canon-docs/src/components/Toolbar/theme.module.css
+++ b/canon-docs/src/components/Toolbar/theme.module.css
@@ -29,23 +29,23 @@
outline: 0;
background: none;
appearance: none;
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
user-select: none;
height: 2rem;
flex: 1;
cursor: pointer;
&[data-selected] {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
& p {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
}
@media (hover: hover) {
&:hover {
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
}
@@ -64,7 +64,7 @@
}
.tab p {
- color: var(--canon-text-secondary) !important;
+ color: var(--canon-fg-secondary) !important;
}
.indicator {
diff --git a/canon-docs/src/mdx-components.tsx b/canon-docs/src/mdx-components.tsx
index 85df3315c4..6d94175619 100644
--- a/canon-docs/src/mdx-components.tsx
+++ b/canon-docs/src/mdx-components.tsx
@@ -62,10 +62,13 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
),
a: ({ children, href }) => (
-
+
{children as ReactNode}
),
+ li: ({ children }) => (
+ {children as ReactNode}
+ ),
pre: ({ children }) => {
const codeContent = React.isValidElement(children)
? (children.props as { children: string }).children
@@ -80,7 +83,7 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
backgroundColor: 'var(--canon-bg-elevated)',
padding: '0.2rem 0.375rem',
borderRadius: '0.25rem',
- color: 'var(--canon-text-secondary)',
+ color: 'var(--canon-fg-secondary)',
border: '1px solid var(--canon-border)',
fontSize: '0.875rem',
}}
diff --git a/canon-docs/src/snippets/_snippets.ts b/canon-docs/src/snippets/_snippets.ts
index 417ff853b5..eb16cbb66c 100644
--- a/canon-docs/src/snippets/_snippets.ts
+++ b/canon-docs/src/snippets/_snippets.ts
@@ -1,5 +1,36 @@
// Sometimes codes are not formatted correctly in the docs, so we need to use snippets
+export const customTheme = `:root {
+ --canon-font-regular: system-ui;
+ --canon-font-weight-regular: 400;
+ --canon-font-weight-bold: 600;
+ --canon-bg: #f8f8f8;
+ --canon-bg-elevated: #fff;
+ /* ... other CSS variables */
+
+ /* Add your custom components styles here */
+ .canon-Button {
+ background-color: #000;
+ color: #fff;
+ }
+}
+
+[data-theme='dark'] {
+ --canon-font-regular: system-ui;
+ --canon-font-weight-regular: 400;
+ --canon-font-weight-bold: 600;
+ --canon-bg: #f8f8f8;
+ --canon-bg-elevated: #fff;
+ /* ... other CSS variables */
+
+ /* Add your custom components styles here */
+ .canon-Button {
+ background-color: #000;
+ color: #fff;
+ }
+}
+`;
+
export const grid = `import { Grid } from '@backstage/canon';
diff --git a/canon-docs/src/snippets/button.tsx b/canon-docs/src/snippets/button.tsx
index 59e6bbd486..30ed666a6a 100644
--- a/canon-docs/src/snippets/button.tsx
+++ b/canon-docs/src/snippets/button.tsx
@@ -62,8 +62,11 @@ export const ButtonDisabled = () => {
};
export const ButtonResponsive = () => {
- // TODO: Add responsive button
- return null;
+ return (
+
+ Responsive Button
+
+ );
};
export const ButtonPlayground = () => {
diff --git a/canon-docs/src/snippets/heading.tsx b/canon-docs/src/snippets/heading.tsx
index 087ce7ebbd..13eaddff30 100644
--- a/canon-docs/src/snippets/heading.tsx
+++ b/canon-docs/src/snippets/heading.tsx
@@ -19,10 +19,9 @@ export const HeadingAllVariants = () => {
};
export const HeadingResponsive = () => {
- return null;
return (
-
+
Responsive heading
diff --git a/canon-docs/src/snippets/text.tsx b/canon-docs/src/snippets/text.tsx
index 633b3b45d7..d2e2020210 100644
--- a/canon-docs/src/snippets/text.tsx
+++ b/canon-docs/src/snippets/text.tsx
@@ -57,8 +57,9 @@ export const TextAllWeights = () => {
};
export const TextResponsive = () => {
- // TODO: Add responsive text
- return null;
+ return (
+ Responsive text
+ );
};
export const TextPlayground = () => {
diff --git a/packages/canon/.storybook/themes/backstage.css b/packages/canon/.storybook/themes/backstage.css
index 92884fa4e7..1f13b1ddae 100644
--- a/packages/canon/.storybook/themes/backstage.css
+++ b/packages/canon/.storybook/themes/backstage.css
@@ -60,9 +60,9 @@
--canon-bg: #f4f4f4;
/* Text colors */
- --canon-text-primary: #000;
+ --canon-fg-primary: #000;
--canon-fg-accent: #fff;
- --canon-text-secondary: #646464;
+ --canon-fg-secondary: #646464;
}
[data-theme-name='legacy'][data-theme='dark'] {
@@ -82,7 +82,7 @@
--canon-fg-danger: #f50000;
/* Text colors */
- --canon-text-primary: #fff;
+ --canon-fg-primary: #fff;
--canon-fg-accent: #000;
- --canon-text-secondary: #b3b3b3;
+ --canon-fg-secondary: #b3b3b3;
}
diff --git a/packages/canon/src/components/Box/Box.stories.tsx b/packages/canon/src/components/Box/Box.stories.tsx
index bf4b8ae5de..e9caa0a3f9 100644
--- a/packages/canon/src/components/Box/Box.stories.tsx
+++ b/packages/canon/src/components/Box/Box.stories.tsx
@@ -383,7 +383,7 @@ export const Border: Story = {
args: {
style: {
background: 'var(--canon-bg-elevated)',
- color: 'var(--canon-text-primary)',
+ color: 'var(--canon-fg-primary)',
padding: '4px 8px',
width: '80px',
height: '32px',
diff --git a/packages/canon/src/components/Box/styles.css b/packages/canon/src/components/Box/styles.css
index c36afdbdfc..f3b24793cf 100644
--- a/packages/canon/src/components/Box/styles.css
+++ b/packages/canon/src/components/Box/styles.css
@@ -1,4 +1,4 @@
.canon-Box {
font-family: var(--canon-font-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
diff --git a/packages/canon/src/components/Button/styles.css b/packages/canon/src/components/Button/styles.css
index 3456f8aa1a..a90fe59348 100644
--- a/packages/canon/src/components/Button/styles.css
+++ b/packages/canon/src/components/Button/styles.css
@@ -36,14 +36,14 @@
&:hover {
background-color: transparent;
box-shadow: inset 0 0 0 1px var(--canon-border-focus);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
}
}
.canon-Button--variant-secondary {
background-color: transparent;
box-shadow: inset 0 0 0 1px var(--canon-border);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
&:hover {
box-shadow: inset 0 0 0 1px var(--canon-border-hover);
@@ -52,10 +52,10 @@
.canon-Button--variant-tertiary {
background-color: transparent;
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
&:hover {
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
}
}
diff --git a/packages/canon/src/components/Checkbox/styles.css b/packages/canon/src/components/Checkbox/styles.css
index 76e14029ca..5dae047191 100644
--- a/packages/canon/src/components/Checkbox/styles.css
+++ b/packages/canon/src/components/Checkbox/styles.css
@@ -23,7 +23,7 @@
gap: var(--canon-space-2);
font-size: var(--canon-font-size-xs);
font-family: var(--canon-font-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
user-select: none;
&:hover {
diff --git a/packages/canon/src/components/Field/Field.styles.css b/packages/canon/src/components/Field/Field.styles.css
index 317dce8143..6a8e3c8e22 100644
--- a/packages/canon/src/components/Field/Field.styles.css
+++ b/packages/canon/src/components/Field/Field.styles.css
@@ -24,14 +24,14 @@
.canon-FieldLabel {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
margin-bottom: var(--canon-space-1_5);
}
.canon-FieldDescription {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
margin: 0;
padding-top: var(--canon-space-1_5);
}
@@ -47,7 +47,7 @@
.canon-FieldValidity {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
margin: 0;
padding-top: var(--canon-space-1_5);
}
diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css
index bc121c1063..2db11d7eb2 100644
--- a/packages/canon/src/components/Heading/styles.css
+++ b/packages/canon/src/components/Heading/styles.css
@@ -16,7 +16,7 @@
.canon-Heading {
font-family: var(--canon-font-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
line-height: 100%;
padding: 0;
margin: 0;
diff --git a/packages/canon/src/components/Input/Input.styles.css b/packages/canon/src/components/Input/Input.styles.css
index 51ad1c5afe..72248f887e 100644
--- a/packages/canon/src/components/Input/Input.styles.css
+++ b/packages/canon/src/components/Input/Input.styles.css
@@ -21,13 +21,13 @@
background-color: var(--canon-bg-elevated);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out;
width: 100%;
}
.canon-Input::placeholder {
- color: var(--canon-text-secondary);
+ color: var(--canon-fg-secondary);
}
.canon-Input:hover {
diff --git a/packages/canon/src/components/Text/styles.css b/packages/canon/src/components/Text/styles.css
index 62f9d1eec0..871960b8db 100644
--- a/packages/canon/src/components/Text/styles.css
+++ b/packages/canon/src/components/Text/styles.css
@@ -16,7 +16,7 @@
.canon-Text {
font-family: var(--canon-font-regular);
- color: var(--canon-text-primary);
+ color: var(--canon-fg-primary);
padding: 0;
margin: 0;
}
diff --git a/packages/canon/src/css/core.css b/packages/canon/src/css/core.css
index bd03d4d906..a2e561b134 100644
--- a/packages/canon/src/css/core.css
+++ b/packages/canon/src/css/core.css
@@ -75,7 +75,7 @@
--canon-bg: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg-accent: #000;
- --canon-bg-accent-active: #000;
+ --canon-bg-accent-focus: #000;
--canon-bg-accent-disabled: #000;
--canon-bg-accent-hover: #000;
--canon-bg-tint: #edf2fe;
@@ -95,14 +95,15 @@
--canon-border-hover: rgba(0, 0, 0, 0.2);
--canon-border-success: #008000;
--canon-border-warning: #e36d05;
+ --canon-fg-primary: #000;
+ --canon-fg-secondary: #646464;
+ --canon-fg-link: #fff;
+ --canon-fg-link-hover: #fff;
--canon-fg-accent: #fff;
+ --canon-fg-tint: #000;
--canon-fg-danger: #e22b2b;
- --canon-fg-success: #008000;
--canon-fg-warning: #e36d05;
- --canon-text-link: #fff;
- --canon-text-link-hover: #fff;
- --canon-text-primary: #000;
- --canon-text-secondary: #646464;
+ --canon-fg-success: #008000;
}
/* Dark theme tokens */
@@ -110,7 +111,7 @@
--canon-bg: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg-accent: #000;
- --canon-bg-accent-active: #000;
+ --canon-bg-accent-focus: #000;
--canon-bg-accent-disabled: #000;
--canon-bg-accent-hover: #000;
--canon-bg-tint: #edf2fe;
@@ -134,8 +135,8 @@
--canon-fg-danger: #e22b2b;
--canon-fg-success: #008000;
--canon-fg-warning: #e36d05;
- --canon-text-link: #fff;
- --canon-text-link-hover: #fff;
- --canon-text-primary: #000;
- --canon-text-secondary: #646464;
+ --canon-fg-link: #fff;
+ --canon-fg-link-hover: #fff;
+ --canon-fg-primary: #000;
+ --canon-fg-secondary: #646464;
}
From ad9aba258b9522bb994fa3e8a4c4375f4a9b6ae7 Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Thu, 23 Jan 2025 10:48:50 +0100
Subject: [PATCH 08/37] backend-app-api: immediately log plugin startup errors
Signed-off-by: Patrik Oldsberg
---
.changeset/grumpy-crews-sneeze.md | 5 +++++
packages/backend-app-api/src/wiring/BackendInitializer.ts | 7 ++++---
.../src/wiring/createInitializationLogger.ts | 7 ++++---
3 files changed, 13 insertions(+), 6 deletions(-)
create mode 100644 .changeset/grumpy-crews-sneeze.md
diff --git a/.changeset/grumpy-crews-sneeze.md b/.changeset/grumpy-crews-sneeze.md
new file mode 100644
index 0000000000..92aeff14a8
--- /dev/null
+++ b/.changeset/grumpy-crews-sneeze.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-app-api': patch
+---
+
+The log message written when plugins fail to initialize now includes the error that caused the plugin startup to fail.
diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts
index aa48c26877..6bec5439ec 100644
--- a/packages/backend-app-api/src/wiring/BackendInitializer.ts
+++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts
@@ -34,7 +34,7 @@ import type {
} from '../../../backend-plugin-api/src/wiring/types';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import type { InternalServiceFactory } from '../../../backend-plugin-api/src/services/system/types';
-import { ForwardedError, ConflictError } from '@backstage/errors';
+import { ForwardedError, ConflictError, assertError } from '@backstage/errors';
import {
instanceMetadataServiceRef,
featureDiscoveryServiceRef,
@@ -405,8 +405,9 @@ export class BackendInitializer {
// Once the plugin and all modules have been initialized, we can signal that the plugin has stared up successfully
const lifecycleService = await this.#getPluginLifecycleImpl(pluginId);
await lifecycleService.startup();
- } catch (error) {
- initLogger.onPluginFailed(pluginId);
+ } catch (error: unknown) {
+ assertError(error);
+ initLogger.onPluginFailed(pluginId, error);
throw error;
}
}),
diff --git a/packages/backend-app-api/src/wiring/createInitializationLogger.ts b/packages/backend-app-api/src/wiring/createInitializationLogger.ts
index 2a472dec5b..e623d43074 100644
--- a/packages/backend-app-api/src/wiring/createInitializationLogger.ts
+++ b/packages/backend-app-api/src/wiring/createInitializationLogger.ts
@@ -27,7 +27,7 @@ export function createInitializationLogger(
rootLogger?: RootLoggerService,
): {
onPluginStarted(pluginId: string): void;
- onPluginFailed(pluginId: string): void;
+ onPluginFailed(pluginId: string, error: Error): void;
onAllStarted(): void;
} {
const logger = rootLogger?.child({ type: 'initialization' });
@@ -68,14 +68,15 @@ export function createInitializationLogger(
starting.delete(pluginId);
started.add(pluginId);
},
- onPluginFailed(pluginId: string) {
+ onPluginFailed(pluginId: string, error: Error) {
starting.delete(pluginId);
const status =
starting.size > 0
? `, waiting for ${starting.size} other plugins to finish before shutting down the process`
: '';
logger?.error(
- `Plugin '${pluginId}' threw an error during startup${status}`,
+ `Plugin '${pluginId}' threw an error during startup${status}.`,
+ error,
);
},
onAllStarted() {
From 5e05c990ea0ea56e27cd0274eb1892d694ff65e5 Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Thu, 23 Jan 2025 12:55:15 +0100
Subject: [PATCH 09/37] repo-tools: work around test failure
Signed-off-by: Patrik Oldsberg
---
.../commands/package/schema/openapi/generate/index.test.ts | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/packages/repo-tools/src/commands/package/schema/openapi/generate/index.test.ts b/packages/repo-tools/src/commands/package/schema/openapi/generate/index.test.ts
index 73d26924be..20de746b25 100644
--- a/packages/repo-tools/src/commands/package/schema/openapi/generate/index.test.ts
+++ b/packages/repo-tools/src/commands/package/schema/openapi/generate/index.test.ts
@@ -82,7 +82,12 @@ describe('generateOpenApiSchema', () => {
}),
} as any);
- const { command } = await import('./index');
+ // Same logic as https://github.com/backstage/backstage/blob/547e41da5ac497e5a606c08c8fb57b429687d5f7/packages/repo-tools/src/commands/index.ts#L278-L297
+ const {
+ default: { command },
+ } = (await import('./index')) as unknown as {
+ default: typeof import('./index');
+ };
const actions = async () => {
while (!mockOn.ready) {
From fc3581065f890126f45f31be42d4948ecbeaa3a1 Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Thu, 23 Jan 2025 13:17:09 +0100
Subject: [PATCH 10/37] docs/tooling: add ESM module test coverage limitation
Signed-off-by: Patrik Oldsberg
---
docs/tooling/cli/02-build-system.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/tooling/cli/02-build-system.md b/docs/tooling/cli/02-build-system.md
index 8f9b086c33..f3b29e979d 100644
--- a/docs/tooling/cli/02-build-system.md
+++ b/docs/tooling/cli/02-build-system.md
@@ -515,6 +515,7 @@ The Backstage tooling supports [ECMAScript modules (ESM)](https://nodejs.org/doc
- To enable support for native ESM in tests, you need to run the tests with the `--experimental-vm-modules` flag enabled, typically via `NODE_OPTIONS='--experimental-vm-modules'`.
- Declaring a package as `"type": "module"` in `package.json` is supported, but in tests it will cause all local transitive dependencies to also be treated as ESM, regardless of whether they declare `"type": "module"` or not.
+- When running tests with coverage enabled the default `babel` coverage provider can mess with the hoisting of named exports. This can be worked around by using the `v8` provider instead by setting `"coverageProvider": "v8"` in the Jest configuration, although note that the `v8` provider is a fair bit slower than the `babel` one.
- Node.js has an [ESM interoperability layer with CommonJS](https://nodejs.org/docs/latest-v22.x/api/esm.html#interoperability-with-commonjs) that allows for imports from ESM to identify named exports in CommonJS packages. This interoperability layer is **only** enabled when importing packages with a `.cts` or `.cjs` extension. This is because the interoperability layer is not fully compatible with the NPM ecosystem, and would break package if it was enabled for `.js` files.
- Dynamic imports of CommonJS packages will vary in shape depending on the runtime, i.e. test vs local development, etc. It is therefore recommended to avoid dynamic imports of CommonJS packages and instead use `require`, or to use the explicit CommonJS extensions as mentioned above. If you do need to dynamically import CommonJS packages, avoid using `default` exports, as the shape of them vary across different environments and you would otherwise need to manually unwrap the import based on the shape of the module object.
From 207f88f0d7b12dca3c239fc0734b3cab820a5914 Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Thu, 23 Jan 2025 13:32:15 +0100
Subject: [PATCH 11/37] cli: fix .. in frontend build output
Signed-off-by: Patrik Oldsberg
---
.changeset/neat-singers-rhyme.md | 5 +++++
packages/cli/src/lib/bundler/transforms.ts | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
create mode 100644 .changeset/neat-singers-rhyme.md
diff --git a/.changeset/neat-singers-rhyme.md b/.changeset/neat-singers-rhyme.md
new file mode 100644
index 0000000000..5c12339d84
--- /dev/null
+++ b/.changeset/neat-singers-rhyme.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Fixed the file path pattern of many static assets output as part of the frontend build process, where there was an extra `.` before the extension, leading to names like `image-af7946b..png`.
diff --git a/packages/cli/src/lib/bundler/transforms.ts b/packages/cli/src/lib/bundler/transforms.ts
index addefacd6e..f0a8a9d01d 100644
--- a/packages/cli/src/lib/bundler/transforms.ts
+++ b/packages/cli/src/lib/bundler/transforms.ts
@@ -154,7 +154,7 @@ export const transforms = (options: TransformOptions): Transforms => {
],
type: 'asset/resource',
generator: {
- filename: 'static/[name].[hash:8].[ext]',
+ filename: 'static/[name].[hash:8][ext]',
},
},
{
From 636744a0ccf2db2905c47325b9c7e6fe59153c82 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?=
Date: Thu, 23 Jan 2025 16:21:12 +0100
Subject: [PATCH 12/37] make config key optional
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Fredrik Adelöw
---
.changeset/odd-countries-vanish.md | 5 +++++
plugins/catalog-backend-module-ldap/config.d.ts | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
create mode 100644 .changeset/odd-countries-vanish.md
diff --git a/.changeset/odd-countries-vanish.md b/.changeset/odd-countries-vanish.md
new file mode 100644
index 0000000000..4d56b1fdeb
--- /dev/null
+++ b/.changeset/odd-countries-vanish.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-ldap': patch
+---
+
+Make `ldapOrg` config key optional
diff --git a/plugins/catalog-backend-module-ldap/config.d.ts b/plugins/catalog-backend-module-ldap/config.d.ts
index e30aaab5d5..b04e9194d2 100644
--- a/plugins/catalog-backend-module-ldap/config.d.ts
+++ b/plugins/catalog-backend-module-ldap/config.d.ts
@@ -437,7 +437,7 @@ export interface Config {
/**
* LdapOrg provider key
*/
- ldapOrg: {
+ ldapOrg?: {
/**
* Id of the LdapOrg provider
*/
From b9cc37d62c6d3e6466705115ce5fc3cb44bf656a Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Thu, 23 Jan 2025 17:14:06 +0100
Subject: [PATCH 13/37] create-app: add lock seed for @types/node
Signed-off-by: Patrik Oldsberg
---
packages/create-app/seed-yarn.lock | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/packages/create-app/seed-yarn.lock b/packages/create-app/seed-yarn.lock
index 21b2aa543d..ebb1fb1e0b 100644
--- a/packages/create-app/seed-yarn.lock
+++ b/packages/create-app/seed-yarn.lock
@@ -41,3 +41,18 @@
version "22.2.0"
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e"
integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==
+
+"@types/node@*":
+ version "22.10.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.8.tgz#e7e2602c83d27d483c056302d76b86321c4e8697"
+ integrity sha512-rk+QvAEGsbX/ZPiiyel6hJHNUS9cnSbPWVaZLvE+Er3tLqQFzWMz9JOfWW7XUmKvRPfxJfbl3qYWve+RGXncFw==
+
+"@types/node@>=13.7.0":
+ version "22.10.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.8.tgz#e7e2602c83d27d483c056302d76b86321c4e8697"
+ integrity sha512-rk+QvAEGsbX/ZPiiyel6hJHNUS9cnSbPWVaZLvE+Er3tLqQFzWMz9JOfWW7XUmKvRPfxJfbl3qYWve+RGXncFw==
+
+"@types/node@^22.0.0":
+ version "22.10.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.8.tgz#e7e2602c83d27d483c056302d76b86321c4e8697"
+ integrity sha512-rk+QvAEGsbX/ZPiiyel6hJHNUS9cnSbPWVaZLvE+Er3tLqQFzWMz9JOfWW7XUmKvRPfxJfbl3qYWve+RGXncFw==
From 61e80ef3ad89a88daea6ba731d48837e18196f81 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 23 Jan 2025 18:24:22 +0000
Subject: [PATCH 14/37] chore(deps): update dependency @types/dockerode to
v3.3.34
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
yarn.lock | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index fb1806e230..88845c8dc7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -19313,13 +19313,13 @@ __metadata:
linkType: hard
"@types/dockerode@npm:^3.3.0, @types/dockerode@npm:^3.3.29":
- version: 3.3.33
- resolution: "@types/dockerode@npm:3.3.33"
+ version: 3.3.34
+ resolution: "@types/dockerode@npm:3.3.34"
dependencies:
"@types/docker-modem": "*"
"@types/node": "*"
"@types/ssh2": "*"
- checksum: 4e3ed41f3b89a213c9ba923862b653f54ee7232b2c95553410d0c3846396efb592d0291fa2f50d4b47d42a2ae0b49f422e72efcdd845d0ebb60da2e8990e9293
+ checksum: 0cb35276fc76ee8ae9d6db7054198e23370f753894d06aa56efbf232032009c6f63a3bfce9d71e6272f3240040d9da2d2a56671d24f34e598ff2000df946ecbd
languageName: node
linkType: hard
From e8492e7600dc72cbc7e81d14a041d80b1265a270 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 23 Jan 2025 18:34:39 +0000
Subject: [PATCH 15/37] chore(deps): update dependency typescript to v5.7.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
canon-docs/yarn.lock | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/canon-docs/yarn.lock b/canon-docs/yarn.lock
index 28810f8911..c963d193bc 100644
--- a/canon-docs/yarn.lock
+++ b/canon-docs/yarn.lock
@@ -5368,22 +5368,22 @@ __metadata:
linkType: hard
"typescript@npm:^5":
- version: 5.7.2
- resolution: "typescript@npm:5.7.2"
+ version: 5.7.3
+ resolution: "typescript@npm:5.7.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
- checksum: b55300c4cefee8ee380d14fa9359ccb41ff8b54c719f6bc49b424899d662a5ce62ece390ce769568c7f4d14af844085255e63788740084444eb12ef423b13433
+ checksum: 6c38b1e989918e576f0307e6ee013522ea480dfce5f3ca85c9b2d8adb1edeffd37f4f30cd68de0c38a44563d12ba922bdb7e36aa2dac9c51de5d561e6e9a2e9c
languageName: node
linkType: hard
"typescript@patch:typescript@^5#~builtin":
- version: 5.7.2
- resolution: "typescript@patch:typescript@npm%3A5.7.2#~builtin::version=5.7.2&hash=5adc0c"
+ version: 5.7.3
+ resolution: "typescript@patch:typescript@npm%3A5.7.3#~builtin::version=5.7.3&hash=5adc0c"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
- checksum: 803430c6da2ba73c25a21880d8d4f08a56d9d2444e6db2ea949ac4abceeece8e4a442b7b9b585db7d8a0b47ebda2060e45fe8ee8b8aca23e27ec1d4844987ee6
+ checksum: 633cd749d6cd7bc842c6b6245847173bba99742a60776fae3c0fbcc0d1733cd51a733995e5f4dadd8afb0e64e57d3c7dbbeae953a072ee303940eca69e22f311
languageName: node
linkType: hard
From 3d7e7f36c4cc9450963a0e9c564a6a32f38ee4cf Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 23 Jan 2025 18:54:16 +0000
Subject: [PATCH 16/37] chore(deps): update dependency @types/node to v20.17.16
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
canon-docs/yarn.lock | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/canon-docs/yarn.lock b/canon-docs/yarn.lock
index 28810f8911..453051ec54 100644
--- a/canon-docs/yarn.lock
+++ b/canon-docs/yarn.lock
@@ -925,11 +925,11 @@ __metadata:
linkType: hard
"@types/node@npm:^20":
- version: 20.17.12
- resolution: "@types/node@npm:20.17.12"
+ version: 20.17.16
+ resolution: "@types/node@npm:20.17.16"
dependencies:
undici-types: ~6.19.2
- checksum: 0c0dbeb4e1480a23071ec38e97bb3d776e0ae9828174bf45f9edcf277caa955945cb10d31d84f7a73c66aaf92ae2e022be6331bd00a4bed1f2ad9639a411d17e
+ checksum: dd19c04c592b602f20448187b4b6ab0293f22173a8bbe53aa3b559188f078b5261d748a107b84ee0580e2074cda760049b13d6e210f9850039bead01cb666a3f
languageName: node
linkType: hard
From 3696cbce714c7197be3135541d643618d3a60f89 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 23 Jan 2025 19:22:00 +0000
Subject: [PATCH 17/37] chore(deps): update dependency @types/ws to v8.5.14
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
yarn.lock | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index 88845c8dc7..ebfe2acde7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -20734,11 +20734,11 @@ __metadata:
linkType: hard
"@types/ws@npm:*, @types/ws@npm:^8.0.0, @types/ws@npm:^8.5.10, @types/ws@npm:^8.5.3, @types/ws@npm:^8.5.4":
- version: 8.5.13
- resolution: "@types/ws@npm:8.5.13"
+ version: 8.5.14
+ resolution: "@types/ws@npm:8.5.14"
dependencies:
"@types/node": "*"
- checksum: f17023ce7b89c6124249c90211803a4aaa02886e12bc2d0d2cd47fa665eeb058db4d871ce4397d8e423f6beea97dd56835dd3fdbb921030fe4d887601e37d609
+ checksum: b63d25146a0d2ebb9cb35e4b68c5a01d81b8f4657d62b0a0d9470df6a357798349a44064b2f84b8f98a553ba84d9a5ee302d3053feef02c7771010c55d290ca6
languageName: node
linkType: hard
From c54f45760bedae5846a06f9da1a54b72c2412536 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 23 Jan 2025 20:19:37 +0000
Subject: [PATCH 18/37] chore(deps): update dependency lint-staged to v15.4.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
yarn.lock | 65 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 36 insertions(+), 29 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index ebfe2acde7..7cd8bb3cdc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -24494,7 +24494,7 @@ __metadata:
languageName: node
linkType: hard
-"chalk@npm:^5.4.1, chalk@npm:~5.4.1":
+"chalk@npm:^5.4.1":
version: 5.4.1
resolution: "chalk@npm:5.4.1"
checksum: 0c656f30b782fed4d99198825c0860158901f449a6b12b818b0aabad27ec970389e7e8767d0e00762175b23620c812e70c4fd92c0210e55fc2d993638b74e86e
@@ -25166,10 +25166,10 @@ __metadata:
languageName: node
linkType: hard
-"commander@npm:*, commander@npm:^12.0.0, commander@npm:^12.1.0, commander@npm:~12.1.0":
- version: 12.1.0
- resolution: "commander@npm:12.1.0"
- checksum: 68e9818b00fc1ed9cdab9eb16905551c2b768a317ae69a5e3c43924c2b20ac9bb65b27e1cab36aeda7b6496376d4da908996ba2c0b5d79463e0fb1e77935d514
+"commander@npm:*, commander@npm:^13.1.0":
+ version: 13.1.0
+ resolution: "commander@npm:13.1.0"
+ checksum: 8ca2fcb33caf2aa06fba3722d7a9440921331d54019dabf906f3603313e7bf334b009b862257b44083ff65d5a3ab19e83ad73af282bd5319f01dc228bdf87ef0
languageName: node
linkType: hard
@@ -25208,6 +25208,13 @@ __metadata:
languageName: node
linkType: hard
+"commander@npm:^12.0.0, commander@npm:^12.1.0":
+ version: 12.1.0
+ resolution: "commander@npm:12.1.0"
+ checksum: 68e9818b00fc1ed9cdab9eb16905551c2b768a317ae69a5e3c43924c2b20ac9bb65b27e1cab36aeda7b6496376d4da908996ba2c0b5d79463e0fb1e77935d514
+ languageName: node
+ linkType: hard
+
"commander@npm:^2.19.0, commander@npm:^2.20.0":
version: 2.20.3
resolution: "commander@npm:2.20.3"
@@ -26458,7 +26465,7 @@ __metadata:
languageName: node
linkType: hard
-"debug@npm:4, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:~4.4.0":
+"debug@npm:4, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:^4.4.0":
version: 4.4.0
resolution: "debug@npm:4.4.0"
dependencies:
@@ -28835,7 +28842,7 @@ __metadata:
languageName: node
linkType: hard
-"execa@npm:~8.0.1":
+"execa@npm:^8.0.1":
version: 8.0.1
resolution: "execa@npm:8.0.1"
dependencies:
@@ -34712,7 +34719,7 @@ __metadata:
languageName: node
linkType: hard
-"lilconfig@npm:~3.1.3":
+"lilconfig@npm:^3.1.3":
version: 3.1.3
resolution: "lilconfig@npm:3.1.3"
checksum: 644eb10830350f9cdc88610f71a921f510574ed02424b57b0b3abb66ea725d7a082559552524a842f4e0272c196b88dfe1ff7d35ffcc6f45736777185cd67c9a
@@ -34762,22 +34769,22 @@ __metadata:
linkType: hard
"lint-staged@npm:^15.0.0":
- version: 15.4.1
- resolution: "lint-staged@npm:15.4.1"
+ version: 15.4.2
+ resolution: "lint-staged@npm:15.4.2"
dependencies:
- chalk: ~5.4.1
- commander: ~12.1.0
- debug: ~4.4.0
- execa: ~8.0.1
- lilconfig: ~3.1.3
- listr2: ~8.2.5
- micromatch: ~4.0.8
- pidtree: ~0.6.0
- string-argv: ~0.3.2
- yaml: ~2.6.1
+ chalk: ^5.4.1
+ commander: ^13.1.0
+ debug: ^4.4.0
+ execa: ^8.0.1
+ lilconfig: ^3.1.3
+ listr2: ^8.2.5
+ micromatch: ^4.0.8
+ pidtree: ^0.6.0
+ string-argv: ^0.3.2
+ yaml: ^2.7.0
bin:
lint-staged: bin/lint-staged.js
- checksum: 6c17747e9379a08ad3d15aab869a362c750d357182c76ca88121f01143910a2a2d5b1673536f3ba9db2331bf2102ffee115532736dd9c3fa2696344732a47d3d
+ checksum: bdb031d64f388aea166b3beaaff8a0a1503e50433959805985b43fcd788c9bfaf1e3a6c0852d830a6c75345b9c0809c5e6dab80d48460e3d6317b7ca0f842df8
languageName: node
linkType: hard
@@ -34788,7 +34795,7 @@ __metadata:
languageName: node
linkType: hard
-"listr2@npm:~8.2.5":
+"listr2@npm:^8.2.5":
version: 8.2.5
resolution: "listr2@npm:8.2.5"
dependencies:
@@ -36265,7 +36272,7 @@ __metadata:
languageName: node
linkType: hard
-"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.7, micromatch@npm:^4.0.8, micromatch@npm:~4.0.8":
+"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.7, micromatch@npm:^4.0.8":
version: 4.0.8
resolution: "micromatch@npm:4.0.8"
dependencies:
@@ -39211,7 +39218,7 @@ __metadata:
languageName: node
linkType: hard
-"pidtree@npm:~0.6.0":
+"pidtree@npm:^0.6.0":
version: 0.6.0
resolution: "pidtree@npm:0.6.0"
bin:
@@ -43958,7 +43965,7 @@ __metadata:
languageName: node
linkType: hard
-"string-argv@npm:~0.3.1, string-argv@npm:~0.3.2":
+"string-argv@npm:^0.3.2, string-argv@npm:~0.3.1":
version: 0.3.2
resolution: "string-argv@npm:0.3.2"
checksum: 8703ad3f3db0b2641ed2adbb15cf24d3945070d9a751f9e74a924966db9f325ac755169007233e8985a39a6a292f14d4fee20482989b89b96e473c4221508a0f
@@ -47656,12 +47663,12 @@ __metadata:
languageName: node
linkType: hard
-"yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2, yaml@npm:^2.3.3, yaml@npm:^2.3.4, yaml@npm:~2.6.1":
- version: 2.6.1
- resolution: "yaml@npm:2.6.1"
+"yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2, yaml@npm:^2.3.3, yaml@npm:^2.3.4, yaml@npm:^2.7.0":
+ version: 2.7.0
+ resolution: "yaml@npm:2.7.0"
bin:
yaml: bin.mjs
- checksum: 5cf2627f121dcf04ccdebce8e6cbac7c9983d465c4eab314f6fbdc13cda8a07f4e8f9c2252a382b30bcabe05ee3c683647293afd52eb37cbcefbdc7b6ebde9ee
+ checksum: 6e8b2f9b9d1b18b10274d58eb3a47ec223d9a93245a890dcb34d62865f7e744747190a9b9177d5f0ef4ea2e44ad2c0214993deb42e0800766203ac46f00a12dd
languageName: node
linkType: hard
From 8ddb719564e1a1e1a18a099e76ad58666644aab1 Mon Sep 17 00:00:00 2001
From: Juan Pablo Garcia Ripa
Date: Thu, 23 Jan 2025 21:23:36 +0100
Subject: [PATCH 19/37] make message clearer
Signed-off-by: Juan Pablo Garcia Ripa
---
.../src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts | 2 +-
.../src/scaffolder/tasks/NunjucksWorkflowRunner.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts
index 31ba7195b2..542a989d8a 100644
--- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts
@@ -1005,7 +1005,7 @@ describe('NunjucksWorkflowRunner', () => {
parameters: {},
});
await expect(runner.execute(task)).rejects.toThrow(
- 'Invalid each value passed to action jest-validated-action, "${{parameters.data}}" cannot be resolved to a value',
+ 'Invalid value on action jest-validated-action.each parameter, "${{parameters.data}}" cannot be resolved to a value',
);
expect(fakeActionHandler).not.toHaveBeenCalled();
});
diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts
index 9865f4db87..6fe92c0e2d 100644
--- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts
@@ -310,7 +310,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
if (step.each && !resolvedEach) {
throw new InputError(
- `Invalid each value passed to action ${action.id}, "${step.each}" cannot be resolved to a value`,
+ `Invalid value on action ${action.id}.each parameter, "${step.each}" cannot be resolved to a value`,
);
}
From 9ff33225fe05d8355436e7e84427a160dc52fcaa Mon Sep 17 00:00:00 2001
From: Patrik Oldsberg
Date: Fri, 24 Jan 2025 00:29:33 +0100
Subject: [PATCH 20/37] frontend-plugin-api: allow duplicate route ref IDs
Signed-off-by: Patrik Oldsberg
---
.changeset/witty-pets-march.md | 5 +++++
packages/frontend-plugin-api/src/routing/RouteRef.test.ts | 1 +
packages/frontend-plugin-api/src/routing/RouteRef.ts | 2 +-
3 files changed, 7 insertions(+), 1 deletion(-)
create mode 100644 .changeset/witty-pets-march.md
diff --git a/.changeset/witty-pets-march.md b/.changeset/witty-pets-march.md
new file mode 100644
index 0000000000..163d146027
--- /dev/null
+++ b/.changeset/witty-pets-march.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Allow route references to be installed in multiple app instances as long as their name is the same.
diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts
index de7a3de887..570723df9a 100644
--- a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts
+++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts
@@ -35,6 +35,7 @@ describe('RouteRef', () => {
internal.setId('some-id');
expect(String(internal)).toBe('RouteRef{some-id}');
+ internal.setId('some-id'); // Should allow same ID
expect(() => internal.setId('some-other-id')).toThrow(
"RouteRef was referenced twice as both 'some-id' and 'some-other-id'",
diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts
index da562e5273..1678e14cd4 100644
--- a/packages/frontend-plugin-api/src/routing/RouteRef.ts
+++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts
@@ -95,7 +95,7 @@ export class RouteRefImpl implements InternalRouteRef {
if (!id) {
throw new Error(`${this.#name} id must be a non-empty string`);
}
- if (this.#id) {
+ if (this.#id && this.#id !== id) {
throw new Error(
`${this.#name} was referenced twice as both '${this.#id}' and '${id}'`,
);
From 9c9f4ff99027a022b626ec1cb5960d2f621dcded Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Fri, 4 Oct 2024 15:10:32 +0200
Subject: [PATCH 21/37] feat: render nested metadata as yaml
Signed-off-by: Chris Langhout
---
.changeset/eight-cougars-collect.md | 5 +
.../StructuredMetadataTable.tsx | 110 +-----
plugins/kubernetes/dev/index.tsx | 14 +
.../src/__fixtures__/3-ingresses.json | 372 ++++++++++++++++++
4 files changed, 412 insertions(+), 89 deletions(-)
create mode 100644 .changeset/eight-cougars-collect.md
create mode 100644 plugins/kubernetes/src/__fixtures__/3-ingresses.json
diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md
new file mode 100644
index 0000000000..07b3a52ca1
--- /dev/null
+++ b/.changeset/eight-cougars-collect.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+better rendering of nested data; rendered as yaml now
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
index 3099edf9d8..657f656949 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
@@ -14,109 +14,41 @@
* limitations under the License.
*/
-import React, { Fragment, ReactElement } from 'react';
-import {
- withStyles,
- createStyles,
- WithStyles,
- Theme,
-} from '@material-ui/core/styles';
+import React, { Fragment } from 'react';
import startCase from 'lodash/startCase';
import Typography from '@material-ui/core/Typography';
import {
MetadataTable,
MetadataTableItem,
- MetadataList,
- MetadataListItem,
} from './MetadataTable';
+import { JsonArray, JsonObject, JsonValue } from '@backstage/types';
+import { CodeSnippet } from '../CodeSnippet';
+import jsyaml from 'js-yaml';
export type StructuredMetadataTableListClassKey = 'root';
-const listStyle = createStyles({
- root: {
- margin: '0 0',
- listStyleType: 'none',
- },
-});
-
export type StructuredMetadataTableNestedListClassKey = 'root';
-const nestedListStyle = (theme: Theme) =>
- createStyles({
- root: {
- ...listStyle.root,
- paddingLeft: theme.spacing(1),
- },
- });
-
-interface StyleProps extends WithStyles {
- children?: React.ReactNode;
-}
-// Sub Components
-const StyledList = withStyles(listStyle, {
- name: 'BackstageStructuredMetadataTableList',
-})(({ classes, children }: StyleProps) => (
- {children}
-));
-const StyledNestedList = withStyles(nestedListStyle, {
- name: 'BackstageStructuredMetadataTableNestedList',
-})(({ classes, children }: StyleProps) => (
- {children}
-));
-
-function renderList(list: Array, options: Options, nested: boolean) {
- const values = list.map((item: any, index: number) => (
-
- {toValue(item, options, nested)}
-
- ));
- return nested ? (
- {values}
- ) : (
- {values}
- );
-}
-
-function renderMap(
- map: { [key: string]: any },
- options: Options,
- nested: boolean,
-) {
- const values = Object.keys(map).map(key => {
- const value = toValue(map[key], options, true);
- return (
-
-
- {`${options.titleFormat(key)}: `}
-
- {value}
-
- );
- });
-
- return nested ? (
- {values}
- ) : (
- {values}
- );
-}
-
function toValue(
- value: ReactElement | object | Array | boolean,
- options: Options,
- nested: boolean,
+ value: object | Array | boolean | string,
) {
if (React.isValidElement(value)) {
return {value} ;
}
- if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
- return renderMap(value, options, nested);
- }
-
- if (Array.isArray(value)) {
- return renderList(value, options, nested);
+ if (value !== null && typeof value === 'object') {
+ return
}
if (typeof value === 'boolean') {
@@ -129,8 +61,8 @@ function toValue(
);
}
-const ItemValue = ({ value, options }: { value: any; options: Options }) => (
- {toValue(value, options, false)}
+const ItemValue = ({ value }: { value: any }) => (
+ {toValue(value)}
);
const TableItem = ({
@@ -139,12 +71,12 @@ const TableItem = ({
options,
}: {
title: string;
- value: any;
+ value: JsonObject | JsonArray | JsonValue;
options: Options;
}) => {
return (
-
+
);
};
diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx
index 2de5a17f25..008d6ce54b 100644
--- a/plugins/kubernetes/dev/index.tsx
+++ b/plugins/kubernetes/dev/index.tsx
@@ -34,6 +34,7 @@ import fixture2 from '../src/__fixtures__/2-deployments.json';
import fixture3 from '../src/__fixtures__/1-cronjobs.json';
import fixture4 from '../src/__fixtures__/2-cronjobs.json';
import fixture5 from '../src/__fixtures__/1-rollouts.json';
+import fixture6 from '../src/__fixtures__/3-ingresses.json';
import { TestApiProvider } from '@backstage/test-utils';
const mockEntity: Entity = {
@@ -200,5 +201,18 @@ createDevApp()
),
})
+ .addPage({
+ path: '/fixture-6',
+ title: 'Fixture 6',
+ element: (
+
+
+
+
+
+ ),
+ })
.registerPlugin(kubernetesPlugin)
.render();
diff --git a/plugins/kubernetes/src/__fixtures__/3-ingresses.json b/plugins/kubernetes/src/__fixtures__/3-ingresses.json
new file mode 100644
index 0000000000..94359c8239
--- /dev/null
+++ b/plugins/kubernetes/src/__fixtures__/3-ingresses.json
@@ -0,0 +1,372 @@
+{
+ "ingresses": [
+ {
+ "metadata": {
+ "name": "app-service-endpoint.dice-roller.backstage.io",
+ "namespace": "dice-roller",
+ "uid": "00000000-0000-0000-0000-000000000000",
+ "resourceVersion": "4749260703",
+ "generation": 1,
+ "creationTimestamp": "2023-08-16T14:52:16Z",
+ "labels": {
+ "backstage.io/kubernetes-id": "dice-roller",
+ "ingress-class": "istio-internal"
+ },
+ "annotations": {
+ "kubectl.kubernetes.io/last-applied-configuration": "spec",
+ "metacontroller.k8s.io/last-applied-configuration": "spec",
+ "nginx.ingress.kubernetes.io/auth-signin": "https://backstage.io/authenticate",
+ "nginx.ingress.kubernetes.io/configuration-snippet": "config",
+ "nginx.ingress.kubernetes.io/service-upstream": "true",
+ "nginx.ingress.kubernetes.io/upstream-vhost": "app-service-endpoint.dice-roller.backstage.services"
+ },
+ "ownerReferences": [
+ {
+ "apiVersion": "networking.backstage.com/v1beta1",
+ "kind": "MeshIntegration",
+ "name": "app-service-endpoint",
+ "uid": "00000000-0000-0000-0000-000000000000",
+ "controller": true,
+ "blockOwnerDeletion": true
+ }
+ ],
+ "managedFields": [
+ {
+ "manager": "nginx-ingress-controller",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2023-08-16T14:52:56Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:status": {
+ "f:loadBalancer": {
+ "f:ingress": {}
+ }
+ }
+ },
+ "subresource": "status"
+ },
+ {
+ "manager": "kubectl-client-side-apply",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2023-12-15T16:33:17Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ ".": {},
+ "f:kubectl.kubernetes.io/last-applied-configuration": {},
+ "f:nginx.ingress.kubernetes.io/auth-signin": {},
+ "f:nginx.ingress.kubernetes.io/configuration-snippet": {},
+ "f:nginx.ingress.kubernetes.io/service-upstream": {},
+ "f:nginx.ingress.kubernetes.io/upstream-vhost": {}
+ },
+ "f:labels": {
+ ".": {},
+ "f:backstage.io/kubernetes-id": {},
+ "f:ingress-class": {}
+ }
+ },
+ "f:spec": {
+ "f:ingressClassName": {},
+ "f:rules": {},
+ "f:tls": {}
+ }
+ }
+ },
+ {
+ "manager": "kubectl-label",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2024-02-21T15:00:44Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:labels": {
+ "f:controller-uid": {}
+ }
+ }
+ }
+ },
+ {
+ "manager": "metacontroller",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2024-02-21T15:01:01Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ "f:metacontroller.k8s.io/last-applied-configuration": {}
+ },
+ "f:ownerReferences": {
+ ".": {},
+ "k:{\"uid\":\"00000000-0000-0000-0000-000000000000\"}": {}
+ }
+ }
+ }
+ }
+ ]
+ },
+ "spec": {
+ "ingressClassName": "istio-internal",
+ "tls": {
+ "hosts": ["app-service-endpoint.dice-roller.backstage.io"],
+ "secretName": "dice-roller-wildcard-certificate"
+ },
+ "rules": [
+ {
+ "host": "app-service-endpoint.dice-roller.backstage.io",
+ "http": {
+ "paths": [
+ {
+ "pathType": "ImplementationSpecific",
+ "backend": {
+ "service": {
+ "name": "app-service-endpoint",
+ "port": {
+ "number": 8080
+ }
+ }
+ }
+ },
+ {
+ "pathType": "Second item in the list",
+ "backend": {
+ "service": {
+ "name": "app-service-endpoint",
+ "port": {
+ "number": 8080
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "status": {
+ "loadBalancer": {
+ "ingress": [
+ {
+ "ip": "1.2.3.4"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "deployments": [
+ {
+ "metadata": {
+ "annotations": {
+ "deployment.kubernetes.io/revision": "2",
+ "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"replicas\":10,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n"
+ },
+ "creationTimestamp": "2020-09-23T12:00:55.000Z",
+ "generation": 3,
+ "labels": {
+ "backstage.io/kubernetes-id": "dice-roller"
+ },
+ "managedFields": [
+ {
+ "apiVersion": "apps/v1",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ ".": {},
+ "f:kubectl.kubernetes.io/last-applied-configuration": {}
+ },
+ "f:labels": {
+ ".": {},
+ "f:backstage.io/kubernetes-id": {}
+ }
+ },
+ "f:spec": {
+ "f:progressDeadlineSeconds": {},
+ "f:replicas": {},
+ "f:revisionHistoryLimit": {},
+ "f:selector": {
+ "f:matchLabels": {
+ ".": {},
+ "f:app": {}
+ }
+ },
+ "f:strategy": {
+ "f:rollingUpdate": {
+ ".": {},
+ "f:maxSurge": {},
+ "f:maxUnavailable": {}
+ },
+ "f:type": {}
+ },
+ "f:template": {
+ "f:metadata": {
+ "f:labels": {
+ ".": {},
+ "f:app": {},
+ "f:backstage.io/kubernetes-id": {}
+ }
+ },
+ "f:spec": {
+ "f:containers": {
+ "k:{\"name\":\"nginx\"}": {
+ ".": {},
+ "f:image": {},
+ "f:imagePullPolicy": {},
+ "f:name": {},
+ "f:ports": {
+ ".": {},
+ "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": {
+ ".": {},
+ "f:containerPort": {},
+ "f:protocol": {}
+ }
+ },
+ "f:resources": {},
+ "f:terminationMessagePath": {},
+ "f:terminationMessagePolicy": {}
+ }
+ },
+ "f:dnsPolicy": {},
+ "f:restartPolicy": {},
+ "f:schedulerName": {},
+ "f:securityContext": {},
+ "f:terminationGracePeriodSeconds": {}
+ }
+ }
+ }
+ },
+ "manager": "kubectl",
+ "operation": "Update",
+ "time": "2020-09-25T09:58:50.000Z"
+ },
+ {
+ "apiVersion": "apps/v1",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ "f:deployment.kubernetes.io/revision": {}
+ }
+ },
+ "f:status": {
+ "f:availableReplicas": {},
+ "f:conditions": {
+ ".": {},
+ "k:{\"type\":\"Available\"}": {
+ ".": {},
+ "f:lastTransitionTime": {},
+ "f:lastUpdateTime": {},
+ "f:message": {},
+ "f:reason": {},
+ "f:status": {},
+ "f:type": {}
+ },
+ "k:{\"type\":\"Progressing\"}": {
+ ".": {},
+ "f:lastTransitionTime": {},
+ "f:lastUpdateTime": {},
+ "f:message": {},
+ "f:reason": {},
+ "f:status": {},
+ "f:type": {}
+ }
+ },
+ "f:observedGeneration": {},
+ "f:readyReplicas": {},
+ "f:replicas": {},
+ "f:updatedReplicas": {}
+ }
+ },
+ "manager": "kube-controller-manager",
+ "operation": "Update",
+ "time": "2020-09-25T09:58:55.000Z"
+ }
+ ],
+ "name": "dice-roller",
+ "namespace": "default",
+ "resourceVersion": "593230",
+ "selfLink": "/apis/apps/v1/namespaces/default/deployments/dice-roller",
+ "uid": "7551e949-42d1-4061-83c5-9da107186e47"
+ },
+ "spec": {
+ "progressDeadlineSeconds": 600,
+ "replicas": 10,
+ "revisionHistoryLimit": 10,
+ "selector": {
+ "matchLabels": {
+ "app": "dice-roller"
+ }
+ },
+ "strategy": {
+ "rollingUpdate": {
+ "maxSurge": "25%",
+ "maxUnavailable": "25%"
+ },
+ "type": "RollingUpdate"
+ },
+ "template": {
+ "metadata": {
+ "creationTimestamp": null,
+ "labels": {
+ "app": "dice-roller",
+ "backstage.io/kubernetes-id": "dice-roller"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "image": "nginx:1.14.2",
+ "imagePullPolicy": "IfNotPresent",
+ "name": "nginx",
+ "ports": [
+ {
+ "containerPort": 80,
+ "protocol": "TCP"
+ }
+ ],
+ "resources": {},
+ "terminationMessagePath": "/dev/termination-log",
+ "terminationMessagePolicy": "File"
+ }
+ ],
+ "dnsPolicy": "ClusterFirst",
+ "restartPolicy": "Always",
+ "schedulerName": "default-scheduler",
+ "securityContext": {},
+ "terminationGracePeriodSeconds": 30
+ }
+ }
+ },
+ "status": {
+ "availableReplicas": 10,
+ "conditions": [
+ {
+ "lastTransitionTime": "2020-09-23T12:00:55.000Z",
+ "lastUpdateTime": "2020-09-24T11:39:28.000Z",
+ "message": "ReplicaSet \"dice-roller-6c8646bfd\" has successfully progressed.",
+ "reason": "NewReplicaSetAvailable",
+ "status": "True",
+ "type": "Progressing"
+ },
+ {
+ "lastTransitionTime": "2020-09-25T09:58:55.000Z",
+ "lastUpdateTime": "2020-09-25T09:58:55.000Z",
+ "message": "Deployment has minimum availability.",
+ "reason": "MinimumReplicasAvailable",
+ "status": "True",
+ "type": "Available"
+ }
+ ],
+ "observedGeneration": 3,
+ "readyReplicas": 10,
+ "replicas": 10,
+ "updatedReplicas": 10
+ }
+ }
+ ]
+}
From 0d468fcd7852770bee7d6779ddff060f63b2108e Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Fri, 4 Oct 2024 15:31:37 +0200
Subject: [PATCH 22/37] fix: lint errors
Signed-off-by: Chris Langhout
---
packages/core-components/package.json | 1 +
.../StructuredMetadataTable.tsx | 35 ++++++++-----------
2 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/packages/core-components/package.json b/packages/core-components/package.json
index 13d3785c4d..add79c01f5 100644
--- a/packages/core-components/package.json
+++ b/packages/core-components/package.json
@@ -73,6 +73,7 @@
"d3-shape": "^3.0.0",
"d3-zoom": "^3.0.0",
"dagre": "^0.8.5",
+ "js-yaml": "^4.1.0",
"linkify-react": "4.1.3",
"linkifyjs": "4.1.3",
"lodash": "^4.17.21",
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
index 657f656949..55c8895dca 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
@@ -18,11 +18,7 @@ import React, { Fragment } from 'react';
import startCase from 'lodash/startCase';
import Typography from '@material-ui/core/Typography';
-import {
- MetadataTable,
- MetadataTableItem,
-} from './MetadataTable';
-import { JsonArray, JsonObject, JsonValue } from '@backstage/types';
+import { MetadataTable, MetadataTableItem } from './MetadataTable';
import { CodeSnippet } from '../CodeSnippet';
import jsyaml from 'js-yaml';
@@ -30,25 +26,24 @@ export type StructuredMetadataTableListClassKey = 'root';
export type StructuredMetadataTableNestedListClassKey = 'root';
-function toValue(
- value: object | Array | boolean | string,
-) {
+function toValue(value: object | Array | boolean | string) {
if (React.isValidElement(value)) {
return {value} ;
}
if (value !== null && typeof value === 'object') {
- return
+ return (
+
+ );
}
if (typeof value === 'boolean') {
@@ -71,7 +66,7 @@ const TableItem = ({
options,
}: {
title: string;
- value: JsonObject | JsonArray | JsonValue;
+ value: any;
options: Options;
}) => {
return (
From 28bb3749d8e09a43fec70a31c0d1407b15457e40 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Tue, 8 Oct 2024 11:17:21 +0200
Subject: [PATCH 23/37] chore: adapt tests; keys are displayed as is instead of
formatted and capitalized
Signed-off-by: Chris Langhout
---
.../components/IngressesAccordions/IngressDrawer.test.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx
index cfacb24ee4..e504aefbb9 100644
--- a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx
@@ -37,13 +37,13 @@ describe('IngressDrawer', () => {
expect(screen.getByText('YAML')).toBeInTheDocument();
expect(screen.getByText('Rules')).toBeInTheDocument();
expect(
- screen.getByText(textContentMatcher('Host: api.awesome-host.io')),
+ screen.getByText(textContentMatcher('host: api.awesome-host.io')),
).toBeInTheDocument();
expect(
- screen.getAllByText(textContentMatcher('Service Port: 80')),
+ screen.getAllByText(textContentMatcher('servicePort: 80')),
).toHaveLength(2);
expect(
- screen.getAllByText(textContentMatcher('Service Name: awesome-service')),
+ screen.getAllByText(textContentMatcher('serviceName: awesome-service')),
).toHaveLength(2);
});
});
From cd1256e5a4aa2605e95e6f074c58afcd3ce00c30 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Tue, 8 Oct 2024 11:39:34 +0200
Subject: [PATCH 24/37] chore: change more tests to match yaml display
Signed-off-by: Chris Langhout
---
.../DeploymentDrawer.test.tsx | 8 ++++----
.../ServicesAccordions/ServiceDrawer.test.tsx | 4 ++--
.../StatefulSetDrawer.test.tsx | 12 ++++++------
plugins/kubernetes/dev/index.tsx | 14 ++++++++++++++
4 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx
index 1e8515f81a..002c4c8ff4 100644
--- a/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx
@@ -40,13 +40,13 @@ describe('DeploymentDrawer', () => {
expect(getAllByText('Deployment')).toHaveLength(2);
expect(getByText('YAML')).toBeInTheDocument();
expect(getByText('Strategy')).toBeInTheDocument();
- expect(getByText('Rolling Update:')).toBeInTheDocument();
- expect(getByText(textContentMatcher('Max Surge: 25%'))).toBeInTheDocument();
+ expect(getByText('rollingUpdate:')).toBeInTheDocument();
+ expect(getByText(textContentMatcher('maxSurge: 25%'))).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Max Unavailable: 25%')),
+ getByText(textContentMatcher('maxUnavailable: 25%')),
).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Type: RollingUpdate')),
+ getByText(textContentMatcher('type: RollingUpdate')),
).toBeInTheDocument();
expect(getByText('Min Ready Seconds')).toBeInTheDocument();
expect(getByText('???')).toBeInTheDocument();
diff --git a/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx
index 7eec2926c4..692c0a7c8c 100644
--- a/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx
@@ -39,10 +39,10 @@ describe('ServiceDrawer', () => {
expect(screen.getByText('Cluster IP')).toBeInTheDocument();
expect(screen.getByText('Ports')).toBeInTheDocument();
expect(
- screen.getByText(textContentMatcher('Target Port: 1997')),
+ screen.getByText(textContentMatcher('targetPort: 1997')),
).toBeInTheDocument();
expect(
- screen.getByText(textContentMatcher('App: awesome-service')),
+ screen.getByText(textContentMatcher('app: awesome-service')),
).toBeInTheDocument();
});
});
diff --git a/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx
index d69ab15f1a..3e4ff56a35 100644
--- a/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx
@@ -40,20 +40,20 @@ describe('StatefulSetDrawer', () => {
expect(getByText('StatefulSet')).toBeInTheDocument();
expect(getByText('YAML')).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Type: RollingUpdate')),
+ getByText(textContentMatcher('type: RollingUpdate')),
).toBeInTheDocument();
- expect(getByText('Rolling Update:')).toBeInTheDocument();
- expect(getByText(textContentMatcher('Max Surge: 25%'))).toBeInTheDocument();
+ expect(getByText('rollingUpdate:')).toBeInTheDocument();
+ expect(getByText(textContentMatcher('maxSurge: 25%'))).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Max Unavailable: 25%')),
+ getByText(textContentMatcher('maxUnavailable: 25%')),
).toBeInTheDocument();
expect(getByText('Pod Management Policy')).toBeInTheDocument();
expect(getByText('Parallel')).toBeInTheDocument();
expect(getByText('Service Name')).toBeInTheDocument();
expect(getByText('Selector')).toBeInTheDocument();
- expect(getByText('Match Labels:')).toBeInTheDocument();
+ expect(getByText('matchLabels:')).toBeInTheDocument();
expect(
- getByText(textContentMatcher('App: dice-roller')),
+ getByText(textContentMatcher('app: dice-roller')),
).toBeInTheDocument();
expect(getByText('Revision History Limit')).toBeInTheDocument();
expect(getByText('10')).toBeInTheDocument();
diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx
index 008d6ce54b..a33d3beee9 100644
--- a/plugins/kubernetes/dev/index.tsx
+++ b/plugins/kubernetes/dev/index.tsx
@@ -35,6 +35,7 @@ import fixture3 from '../src/__fixtures__/1-cronjobs.json';
import fixture4 from '../src/__fixtures__/2-cronjobs.json';
import fixture5 from '../src/__fixtures__/1-rollouts.json';
import fixture6 from '../src/__fixtures__/3-ingresses.json';
+import fixture7 from '../src/__fixtures__/2-statefulsets.json';
import { TestApiProvider } from '@backstage/test-utils';
const mockEntity: Entity = {
@@ -214,5 +215,18 @@ createDevApp()
),
})
+ .addPage({
+ path: '/fixture-7',
+ title: 'Fixture 7',
+ element: (
+
+
+
+
+
+ ),
+ })
.registerPlugin(kubernetesPlugin)
.render();
From 4a58a408896d8ff84ed019bf1950dd045f356242 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Tue, 8 Oct 2024 12:54:24 +0200
Subject: [PATCH 25/37] chore: change more tests to match yaml display
Signed-off-by: Chris Langhout
---
.../StructuredMetadataTable.test.tsx | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
index 4eb05e715e..25c5d0687c 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
@@ -66,7 +66,7 @@ describe(' ', () => {
expect(getByText(startCase(value))).toBeInTheDocument();
});
metadata.arrayField.forEach(value => {
- expect(getByText(value)).toBeInTheDocument();
+ expect(getByText(new RegExp(value))).toBeInTheDocument();
});
});
@@ -127,9 +127,11 @@ describe(' ', () => {
const rendered = render( );
expect(rendered.queryByText(/^Test A/)).toBeInTheDocument();
expect(rendered.queryByText(/^Test B/)).toBeInTheDocument();
- expect(rendered.queryByText(/^Test C/)).toBeInTheDocument();
expect(rendered.queryByText(/^Test D/)).toBeInTheDocument();
- expect(rendered.queryByText(/^Test E/)).toBeInTheDocument();
+
+ // nested content is displayed as yaml, so not affected by formatting
+ expect(rendered.queryByText(/^testC/)).toBeInTheDocument();
+ expect(rendered.queryByText(/^testE/)).toBeInTheDocument();
});
it('should be possible to disable it', async () => {
@@ -166,9 +168,11 @@ describe(' ', () => {
);
expect(rendered.queryByText(/^tEsTa/)).toBeInTheDocument();
expect(rendered.queryByText(/^tEsTb/)).toBeInTheDocument();
- expect(rendered.queryByText(/^tEsTc/)).toBeInTheDocument();
expect(rendered.queryByText(/^tEsTd/)).toBeInTheDocument();
- expect(rendered.queryByText(/^tEsTe/)).toBeInTheDocument();
+
+ // nested content is displayed as yaml, so not affected by formatting
+ expect(rendered.queryByText(/^testC/)).toBeInTheDocument();
+ expect(rendered.queryByText(/^testE/)).toBeInTheDocument();
});
});
});
From 58e13832418cb5051fbde2cdff641b7d14a37b73 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Tue, 8 Oct 2024 14:15:22 +0200
Subject: [PATCH 26/37] fix: changeset properly states what is changing
Signed-off-by: Chris Langhout
---
.changeset/eight-cougars-collect.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md
index 07b3a52ca1..3acb521bc4 100644
--- a/.changeset/eight-cougars-collect.md
+++ b/.changeset/eight-cougars-collect.md
@@ -2,4 +2,4 @@
'@backstage/core-components': patch
---
-better rendering of nested data; rendered as yaml now
+`StructuredMetadataTable` now renders data as yaml, improving readability.
From b6c5ea2abac8feb6ad7ef0ade8c8dafb99d5be0e Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Sat, 4 Jan 2025 16:01:35 +0200
Subject: [PATCH 27/37] chore: change yaml rendering to be an option and enable
for kubernetes plugin FE components
Signed-off-by: Chris Langhout
---
app-config.yaml | 2 +
.../StructuredMetadataTable.tsx | 134 +++++++++++++++---
.../ClusterOverview/ClusterOverview.tsx | 1 +
.../src/components/Nodes/Nodes.tsx | 7 +-
.../CustomResources/DefaultCustomResource.tsx | 5 +-
.../IngressesAccordions.tsx | 3 +
...ubernetesStructuredMetadataTableDrawer.tsx | 1 +
.../Pods/PodDrawer/ContainerCard.tsx | 1 +
.../ServicesAccordions/ServicesAccordions.tsx | 1 +
9 files changed, 131 insertions(+), 24 deletions(-)
diff --git a/app-config.yaml b/app-config.yaml
index 64c2fa5c4c..3abf08af0e 100644
--- a/app-config.yaml
+++ b/app-config.yaml
@@ -322,6 +322,8 @@ catalog:
# Backstage example templates
- type: file
target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml
+ - type: file
+ target: ../../plugins/scaffolder-backend/sample-templates/big-review-step.yaml
rules:
- allow: [Template]
scaffolder:
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
index 55c8895dca..b839280cdd 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
@@ -14,50 +14,138 @@
* limitations under the License.
*/
-import React, { Fragment } from 'react';
+import React, { Fragment, ReactElement } from 'react';
import startCase from 'lodash/startCase';
import Typography from '@material-ui/core/Typography';
-import { MetadataTable, MetadataTableItem } from './MetadataTable';
+import {
+ MetadataList,
+ MetadataListItem,
+ MetadataTable,
+ MetadataTableItem,
+} from './MetadataTable';
import { CodeSnippet } from '../CodeSnippet';
import jsyaml from 'js-yaml';
+import {
+ Theme,
+ createStyles,
+ WithStyles,
+ withStyles,
+} from '@material-ui/core/styles';
export type StructuredMetadataTableListClassKey = 'root';
-export type StructuredMetadataTableNestedListClassKey = 'root';
+const listStyle = createStyles({
+ root: {
+ margin: '0 0',
+ listStyleType: 'none',
+ },
+});
-function toValue(value: object | Array | boolean | string) {
+export type StructuredMetadataTableNestedListClassKey = 'root';
+const nestedListStyle = (theme: Theme) =>
+ createStyles({
+ root: {
+ ...listStyle.root,
+ paddingLeft: theme.spacing(1),
+ },
+ });
+
+interface StyleProps extends WithStyles {
+ children?: React.ReactNode;
+}
+// Sub Components
+const StyledList = withStyles(listStyle, {
+ name: 'BackstageStructuredMetadataTableList',
+})(({ classes, children }: StyleProps) => (
+ {children}
+));
+const StyledNestedList = withStyles(nestedListStyle, {
+ name: 'BackstageStructuredMetadataTableNestedList',
+})(({ classes, children }: StyleProps) => (
+ {children}
+));
+
+function renderList(list: Array, options: Options, nested: boolean) {
+ const values = list.map((item: any, index: number) => (
+
+ {toValue(item, options, nested)}
+
+ ));
+ return nested ? (
+ {values}
+ ) : (
+ {values}
+ );
+}
+
+function renderMap(
+ map: { [key: string]: any },
+ options: Options,
+ nested: boolean,
+) {
+ const values = Object.keys(map).map(key => {
+ const value = toValue(map[key], options, true);
+ return (
+
+
+ {`${options.titleFormat(key)}: `}
+
+ {value}
+
+ );
+ });
+
+ return nested ? (
+ {values}
+ ) : (
+ {values}
+ );
+}
+
+function toValue(
+ value: ReactElement | object | Array | boolean,
+ options: Options,
+ nested: boolean,
+) {
if (React.isValidElement(value)) {
return {value} ;
}
-
if (value !== null && typeof value === 'object') {
- return (
-
- );
+ if (options.nestedValuesAsYaml) {
+ return (
+
+ );
+ }
+ if (!Array.isArray(value)) {
+ return renderMap(value, options, nested);
+ }
+ }
+
+ if (Array.isArray(value)) {
+ return renderList(value, options, nested);
}
if (typeof value === 'boolean') {
return {value ? '✅' : '❌'} ;
}
-
return (
{value}
);
}
-const ItemValue = ({ value }: { value: any }) => (
- {toValue(value)}
+const ItemValue = ({ value, options }: { value: any; options: Options }) => (
+ {toValue(value, options, false)}
);
const TableItem = ({
@@ -71,7 +159,7 @@ const TableItem = ({
}) => {
return (
-
+
);
};
@@ -94,6 +182,7 @@ export interface StructuredMetadataTableProps {
* @returns Formatted key
*/
titleFormat?: (key: string) => string;
+ nestedValuesAsYaml?: boolean;
};
}
@@ -101,9 +190,10 @@ type Options = Required>;
/** @public */
export function StructuredMetadataTable(props: StructuredMetadataTableProps) {
- const { metadata, dense = true, options = {} } = props;
+ const { metadata, dense = true, options } = props;
const metadataItems = mapToItems(metadata, {
titleFormat: startCase,
+ nestedValuesAsYaml: options?.nestedValuesAsYaml ?? false,
...options,
});
return {metadataItems} ;
diff --git a/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx b/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx
index b77b2dff88..af741239e5 100644
--- a/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx
+++ b/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx
@@ -58,6 +58,7 @@ export const ClusterOverview = () => {
'OIDC Token Provider': value.oidcTokenProvider ?? 'N/A',
'Dashboard Link': value.dashboardUrl ?? 'N/A',
}}
+ options={{ nestedValuesAsYaml: true }}
/>
)}
diff --git a/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx b/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx
index 0b3f7ddb60..9307b11a6e 100644
--- a/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx
+++ b/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx
@@ -50,7 +50,10 @@ const defaultColumns: TableColumn[] = [
Node Info
-
+
Addresses
@@ -61,6 +64,7 @@ const defaultColumns: TableColumn[] = [
return accum;
}, {} as any) ?? {}
}
+ options={{ nestedValuesAsYaml: true }}
/>
@@ -72,6 +76,7 @@ const defaultColumns: TableColumn[] = [
return accum;
}, {} as any) ?? {}
}
+ options={{ nestedValuesAsYaml: true }}
/>
diff --git a/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx
index ee484ecda8..d34ba23f7b 100644
--- a/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx
+++ b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx
@@ -84,7 +84,10 @@ const DefaultCustomResourceAccordion = ({
{Object.prototype.hasOwnProperty.call(customResource, 'status') && (
-
+
)}
diff --git a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx
index 5962e78f59..d2d674042b 100644
--- a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx
+++ b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx
@@ -65,6 +65,9 @@ const IngressCard = ({ ingress }: IngressCardProps) => {
metadata={{
...ingress.spec,
}}
+ options={{
+ nestedValuesAsYaml: true,
+ }}
/>
);
};
diff --git a/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx
index b31d3f9aa7..0a5802ddc8 100644
--- a/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx
+++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx
@@ -237,6 +237,7 @@ const KubernetesStructuredMetadataTableDrawerContent = <
{!isYaml && (
)}
diff --git a/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx
index 1919bc112d..6aed2c75d7 100644
--- a/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx
+++ b/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx
@@ -176,6 +176,7 @@ export const ContainerCard: React.FC = ({
containerSpec,
containerStatus,
)}
+ options={{ nestedValuesAsYaml: true }}
/>
{containerMetrics && (
diff --git a/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx
index 71832fd35c..c44a1d158c 100644
--- a/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx
+++ b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx
@@ -77,6 +77,7 @@ const ServiceCard = ({ service }: ServiceCardProps) => {
ports: service.spec?.ports,
...metadata,
}}
+ options={{ nestedValuesAsYaml: true }}
/>
);
};
From 9602eb06ce3dc234d4d34ef494bb8d92d6c21ffe Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Sat, 4 Jan 2025 17:33:29 +0200
Subject: [PATCH 28/37] fix: build api reports
Signed-off-by: Chris Langhout
---
packages/core-components/report.api.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md
index c3f7cf9a6a..c706eef2bb 100644
--- a/packages/core-components/report.api.md
+++ b/packages/core-components/report.api.md
@@ -1307,6 +1307,7 @@ export interface StructuredMetadataTableProps {
// (undocumented)
options?: {
titleFormat?: (key: string) => string;
+ nestedValuesAsYaml?: boolean;
};
}
From b7d03476785fe1e01fe266e44c9985bc7ae3ae07 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Sat, 4 Jan 2025 18:28:54 +0200
Subject: [PATCH 29/37] fix: tests
Signed-off-by: Chris Langhout
---
.../StructuredMetadataTable.test.tsx | 11 ++++++++---
plugins/kubernetes/dev/index.tsx | 11 +++++++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
index 25c5d0687c..8e6c4bbff0 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
@@ -124,14 +124,19 @@ describe(' ', () => {
};
it('should make keys human readable', async () => {
- const rendered = render( );
+ const rendered = render(
+ ,
+ );
expect(rendered.queryByText(/^Test A/)).toBeInTheDocument();
expect(rendered.queryByText(/^Test B/)).toBeInTheDocument();
expect(rendered.queryByText(/^Test D/)).toBeInTheDocument();
// nested content is displayed as yaml, so not affected by formatting
expect(rendered.queryByText(/^testC/)).toBeInTheDocument();
- expect(rendered.queryByText(/^testE/)).toBeInTheDocument();
+ expect(rendered.queryByText(/testE: stuff/)).toBeInTheDocument();
});
it('should be possible to disable it', async () => {
@@ -163,7 +168,7 @@ describe(' ', () => {
const rendered = render(
,
);
expect(rendered.queryByText(/^tEsTa/)).toBeInTheDocument();
diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx
index a33d3beee9..91b97cbfc5 100644
--- a/plugins/kubernetes/dev/index.tsx
+++ b/plugins/kubernetes/dev/index.tsx
@@ -37,6 +37,7 @@ import fixture5 from '../src/__fixtures__/1-rollouts.json';
import fixture6 from '../src/__fixtures__/3-ingresses.json';
import fixture7 from '../src/__fixtures__/2-statefulsets.json';
import { TestApiProvider } from '@backstage/test-utils';
+import { StructuredMetadataTable } from '@backstage/core-components';
const mockEntity: Entity = {
apiVersion: 'backstage.io/v1alpha1',
@@ -136,6 +137,12 @@ class MockKubernetesClient implements KubernetesApi {
}
}
+const metadata = {
+ testA: 'stuff',
+ testB: { testC: 'stuff' },
+ testD: [{ testE: 'stuff' }],
+};
+
createDevApp()
.addPage({
path: '/fixture-1',
@@ -223,6 +230,10 @@ createDevApp()
apis={[[kubernetesApiRef, new MockKubernetesClient(fixture7)]]}
>
+
From eddcb72514136394b8f0e7bd289442b25294b51a Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Wed, 8 Jan 2025 16:07:03 +0200
Subject: [PATCH 30/37] fix: remove unneeded change
Signed-off-by: Chris Langhout
---
app-config.yaml | 2 --
1 file changed, 2 deletions(-)
diff --git a/app-config.yaml b/app-config.yaml
index 3abf08af0e..64c2fa5c4c 100644
--- a/app-config.yaml
+++ b/app-config.yaml
@@ -322,8 +322,6 @@ catalog:
# Backstage example templates
- type: file
target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml
- - type: file
- target: ../../plugins/scaffolder-backend/sample-templates/big-review-step.yaml
rules:
- allow: [Template]
scaffolder:
From ebd3e85e1479d3316eacb4fa1dc98e8846b648a2 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Thu, 9 Jan 2025 13:01:43 +0100
Subject: [PATCH 31/37] Update .changeset/eight-cougars-collect.md
Co-authored-by: Vincenzo Scamporlino
Signed-off-by: Chris Langhout
---
.changeset/eight-cougars-collect.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md
index 3acb521bc4..edaa18d826 100644
--- a/.changeset/eight-cougars-collect.md
+++ b/.changeset/eight-cougars-collect.md
@@ -2,4 +2,4 @@
'@backstage/core-components': patch
---
-`StructuredMetadataTable` now renders data as yaml, improving readability.
+Added `nestedValuesAsYaml` option to `StructuredMetadataTable` to render data as yaml.
From b3000dc294b6158ff0a71078a888bf1cd593d308 Mon Sep 17 00:00:00 2001
From: Chris Langhout
Date: Thu, 9 Jan 2025 14:09:52 +0200
Subject: [PATCH 32/37] chore: add kubernetes packages in changeset
Signed-off-by: Chris Langhout
---
.changeset/eight-cougars-collect.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md
index edaa18d826..66ae59a27f 100644
--- a/.changeset/eight-cougars-collect.md
+++ b/.changeset/eight-cougars-collect.md
@@ -1,5 +1,7 @@
---
'@backstage/core-components': patch
+'@backstage/plugin-kubernetes-cluster': patch
+'@backstage/plugin-kubernetes-react': patch
---
Added `nestedValuesAsYaml` option to `StructuredMetadataTable` to render data as yaml.
From d80b08f066a3f67996218804c13fea51ce626559 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 16 Jan 2025 20:00:40 +0100
Subject: [PATCH 33/37] kubernetes: split changeset
Signed-off-by: Vincenzo Scamporlino
---
.changeset/eight-cougars-collect-due.md | 6 ++++++
.changeset/eight-cougars-collect.md | 2 --
2 files changed, 6 insertions(+), 2 deletions(-)
create mode 100644 .changeset/eight-cougars-collect-due.md
diff --git a/.changeset/eight-cougars-collect-due.md b/.changeset/eight-cougars-collect-due.md
new file mode 100644
index 0000000000..ff997f876a
--- /dev/null
+++ b/.changeset/eight-cougars-collect-due.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-kubernetes-cluster': patch
+'@backstage/plugin-kubernetes-react': patch
+---
+
+Improved rendering of Kubernetes resources' metadata.
diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md
index 66ae59a27f..edaa18d826 100644
--- a/.changeset/eight-cougars-collect.md
+++ b/.changeset/eight-cougars-collect.md
@@ -1,7 +1,5 @@
---
'@backstage/core-components': patch
-'@backstage/plugin-kubernetes-cluster': patch
-'@backstage/plugin-kubernetes-react': patch
---
Added `nestedValuesAsYaml` option to `StructuredMetadataTable` to render data as yaml.
From 86c218a9a114ce7cbfab5ea5bdc7f473ccb86d90 Mon Sep 17 00:00:00 2001
From: blam
Date: Fri, 24 Jan 2025 08:53:36 +0100
Subject: [PATCH 34/37] chore: fix yarn.lock Signed-off-by: blam
---
yarn.lock | 1 +
1 file changed, 1 insertion(+)
diff --git a/yarn.lock b/yarn.lock
index 7cd8bb3cdc..e212f245b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4291,6 +4291,7 @@ __metadata:
d3-zoom: ^3.0.0
dagre: ^0.8.5
history: ^5.0.0
+ js-yaml: ^4.1.0
linkify-react: 4.1.3
linkifyjs: 4.1.3
lodash: ^4.17.21
From a2c1ed1e3d993a1950f18535b39e314e6c7503e7 Mon Sep 17 00:00:00 2001
From: Charles de Dreuille
Date: Fri, 24 Jan 2025 15:06:49 +0000
Subject: [PATCH 35/37] Update text tokens
Signed-off-by: Charles de Dreuille
---
canon-docs/src/app/(docs)/theme/theming/page.mdx | 4 ++--
canon-docs/src/app/globals.css | 2 +-
canon-docs/src/app/page.module.css | 2 +-
.../src/components/CodeBlock/styles.module.css | 2 +-
.../src/components/CustomTheme/styles.module.css | 2 +-
.../src/components/HeadlessBanners/styles.module.css | 4 ++--
canon-docs/src/components/Sidebar/Sidebar.module.css | 8 ++++----
canon-docs/src/components/Tabs/parts.tsx | 4 ++--
canon-docs/src/components/Tabs/styles.module.css | 2 +-
canon-docs/src/components/Toolbar/nav.module.css | 12 ++++++------
canon-docs/src/components/Toolbar/theme.module.css | 10 +++++-----
canon-docs/src/mdx-components.tsx | 4 ++--
packages/canon/.storybook/themes/backstage.css | 8 ++++----
packages/canon/src/components/Box/Box.stories.tsx | 2 +-
packages/canon/src/components/Box/styles.css | 2 +-
packages/canon/src/components/Button/styles.css | 8 ++++----
packages/canon/src/components/Checkbox/styles.css | 2 +-
packages/canon/src/components/Field/Field.styles.css | 6 +++---
packages/canon/src/components/Heading/styles.css | 2 +-
packages/canon/src/components/Input/Input.styles.css | 4 ++--
packages/canon/src/components/Text/styles.css | 2 +-
packages/canon/src/css/core.css | 8 ++++----
22 files changed, 50 insertions(+), 50 deletions(-)
diff --git a/canon-docs/src/app/(docs)/theme/theming/page.mdx b/canon-docs/src/app/(docs)/theme/theming/page.mdx
index 14cd06cb8f..4cb03859f9 100644
--- a/canon-docs/src/app/(docs)/theme/theming/page.mdx
+++ b/canon-docs/src/app/(docs)/theme/theming/page.mdx
@@ -186,7 +186,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-primary
+ --canon-fg-text-primary
It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
@@ -194,7 +194,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-secondary
+ --canon-fg-text-secondary
It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
diff --git a/canon-docs/src/app/globals.css b/canon-docs/src/app/globals.css
index 6f3702c950..343f23a38f 100644
--- a/canon-docs/src/app/globals.css
+++ b/canon-docs/src/app/globals.css
@@ -2,7 +2,7 @@ body {
display: flex;
flex-direction: row;
background-color: var(--canon-bg);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
transition: background-color 0.2s ease-in-out;
--docs-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
diff --git a/canon-docs/src/app/page.module.css b/canon-docs/src/app/page.module.css
index 3d22802a3c..bc28185d48 100644
--- a/canon-docs/src/app/page.module.css
+++ b/canon-docs/src/app/page.module.css
@@ -17,7 +17,7 @@
}
.page p {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
font-size: 1rem;
line-height: 1.5rem;
margin-top: 0;
diff --git a/canon-docs/src/components/CodeBlock/styles.module.css b/canon-docs/src/components/CodeBlock/styles.module.css
index fcd5309f14..966b3ff72b 100644
--- a/canon-docs/src/components/CodeBlock/styles.module.css
+++ b/canon-docs/src/components/CodeBlock/styles.module.css
@@ -18,7 +18,7 @@
border-bottom: 1px solid var(--canon-border);
padding: 12px 20px;
font-size: 0.875rem;
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
}
.code {
diff --git a/canon-docs/src/components/CustomTheme/styles.module.css b/canon-docs/src/components/CustomTheme/styles.module.css
index 8f72b15d02..ac7d7f36f1 100644
--- a/canon-docs/src/components/CustomTheme/styles.module.css
+++ b/canon-docs/src/components/CustomTheme/styles.module.css
@@ -66,7 +66,7 @@
padding: 0 8px;
color: #fff;
background-color: var(--canon-bg);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
transition: background-color 0.2s ease-in-out;
border-radius: 0.25rem;
cursor: pointer;
diff --git a/canon-docs/src/components/HeadlessBanners/styles.module.css b/canon-docs/src/components/HeadlessBanners/styles.module.css
index 6cbb107aa7..4817ab569f 100644
--- a/canon-docs/src/components/HeadlessBanners/styles.module.css
+++ b/canon-docs/src/components/HeadlessBanners/styles.module.css
@@ -10,7 +10,7 @@
}
.icon path {
- fill: var(--canon-fg-primary);
+ fill: var(--canon-fg-text-primary);
}
.content {
@@ -37,6 +37,6 @@
border-radius: 100px;
margin-top: var(--canon-space-3);
font-size: var(--canon-font-size-3);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
gap: var(--canon-space-2);
}
diff --git a/canon-docs/src/components/Sidebar/Sidebar.module.css b/canon-docs/src/components/Sidebar/Sidebar.module.css
index d87be799d0..feb9f8bea3 100644
--- a/canon-docs/src/components/Sidebar/Sidebar.module.css
+++ b/canon-docs/src/components/Sidebar/Sidebar.module.css
@@ -10,7 +10,7 @@
left: 0;
width: 300px;
height: 100vh;
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
background-color: var(--canon-bg-elevated);
border-right: 1px solid var(--canon-border);
padding-left: 20px;
@@ -26,7 +26,7 @@
}
.logo path {
- fill: var(--canon-fg-primary);
+ fill: var(--canon-fg-text-primary);
}
.menu {
@@ -75,11 +75,11 @@
font-family: var(--docs-font);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
.lineStatus {
font-family: var(--docs-font);
font-size: var(--canon-font-size-3);
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
}
diff --git a/canon-docs/src/components/Tabs/parts.tsx b/canon-docs/src/components/Tabs/parts.tsx
index 0139d3be1a..41dfadf2ea 100644
--- a/canon-docs/src/components/Tabs/parts.tsx
+++ b/canon-docs/src/components/Tabs/parts.tsx
@@ -34,8 +34,8 @@ export const Tab = (props: React.ComponentProps) => (
{...rest}
style={{
color: state.selected
- ? 'var(--canon-fg-primary)'
- : 'var(--canon-fg-secondary)',
+ ? 'var(--canon-fg-text-primary)'
+ : 'var(--canon-fg-text-secondary)',
}}
>
{children}
diff --git a/canon-docs/src/components/Tabs/styles.module.css b/canon-docs/src/components/Tabs/styles.module.css
index 2ce4d81064..137bc7470d 100644
--- a/canon-docs/src/components/Tabs/styles.module.css
+++ b/canon-docs/src/components/Tabs/styles.module.css
@@ -22,6 +22,6 @@
left: var(--active-tab-left);
width: var(--active-tab-width);
height: 1px;
- background-color: var(--canon-fg-primary);
+ background-color: var(--canon-fg-text-primary);
transition: all 0.2s ease-in-out;
}
diff --git a/canon-docs/src/components/Toolbar/nav.module.css b/canon-docs/src/components/Toolbar/nav.module.css
index 123817c323..526d7bf918 100644
--- a/canon-docs/src/components/Toolbar/nav.module.css
+++ b/canon-docs/src/components/Toolbar/nav.module.css
@@ -27,21 +27,21 @@
all: unset;
height: 60px;
font-family: var(--docs-font);
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-bold);
cursor: pointer;
transition: color 0.2s ease-in-out;
&:hover {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
&[data-selected] {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
& p {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
}
@@ -60,7 +60,7 @@
}
.tab p {
- color: var(--canon-fg-secondary) !important;
+ color: var(--canon-fg-text-secondary) !important;
}
.indicator {
@@ -72,7 +72,7 @@
width: var(--active-tab-width);
height: 1px;
border-radius: 0.25rem;
- background-color: var(--canon-fg-primary);
+ background-color: var(--canon-fg-text-primary);
transition-property: translate, width, background-color;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
diff --git a/canon-docs/src/components/Toolbar/theme.module.css b/canon-docs/src/components/Toolbar/theme.module.css
index 4da56e31f3..ac3701541f 100644
--- a/canon-docs/src/components/Toolbar/theme.module.css
+++ b/canon-docs/src/components/Toolbar/theme.module.css
@@ -29,23 +29,23 @@
outline: 0;
background: none;
appearance: none;
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
user-select: none;
height: 2rem;
flex: 1;
cursor: pointer;
&[data-selected] {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
& p {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
}
@media (hover: hover) {
&:hover {
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
}
@@ -64,7 +64,7 @@
}
.tab p {
- color: var(--canon-fg-secondary) !important;
+ color: var(--canon-fg-text-secondary) !important;
}
.indicator {
diff --git a/canon-docs/src/mdx-components.tsx b/canon-docs/src/mdx-components.tsx
index 6d94175619..182eaa03b4 100644
--- a/canon-docs/src/mdx-components.tsx
+++ b/canon-docs/src/mdx-components.tsx
@@ -62,7 +62,7 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
),
a: ({ children, href }) => (
-
+
{children as ReactNode}
),
@@ -83,7 +83,7 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
backgroundColor: 'var(--canon-bg-elevated)',
padding: '0.2rem 0.375rem',
borderRadius: '0.25rem',
- color: 'var(--canon-fg-secondary)',
+ color: 'var(--canon-fg-text-secondary)',
border: '1px solid var(--canon-border)',
fontSize: '0.875rem',
}}
diff --git a/packages/canon/.storybook/themes/backstage.css b/packages/canon/.storybook/themes/backstage.css
index 1f13b1ddae..653836c558 100644
--- a/packages/canon/.storybook/themes/backstage.css
+++ b/packages/canon/.storybook/themes/backstage.css
@@ -60,9 +60,9 @@
--canon-bg: #f4f4f4;
/* Text colors */
- --canon-fg-primary: #000;
+ --canon-fg-text-primary: #000;
--canon-fg-accent: #fff;
- --canon-fg-secondary: #646464;
+ --canon-fg-text-secondary: #646464;
}
[data-theme-name='legacy'][data-theme='dark'] {
@@ -82,7 +82,7 @@
--canon-fg-danger: #f50000;
/* Text colors */
- --canon-fg-primary: #fff;
+ --canon-fg-text-primary: #fff;
--canon-fg-accent: #000;
- --canon-fg-secondary: #b3b3b3;
+ --canon-fg-text-secondary: #b3b3b3;
}
diff --git a/packages/canon/src/components/Box/Box.stories.tsx b/packages/canon/src/components/Box/Box.stories.tsx
index e9caa0a3f9..52dd7bc782 100644
--- a/packages/canon/src/components/Box/Box.stories.tsx
+++ b/packages/canon/src/components/Box/Box.stories.tsx
@@ -383,7 +383,7 @@ export const Border: Story = {
args: {
style: {
background: 'var(--canon-bg-elevated)',
- color: 'var(--canon-fg-primary)',
+ color: 'var(--canon-fg-text-primary)',
padding: '4px 8px',
width: '80px',
height: '32px',
diff --git a/packages/canon/src/components/Box/styles.css b/packages/canon/src/components/Box/styles.css
index f3b24793cf..229f322343 100644
--- a/packages/canon/src/components/Box/styles.css
+++ b/packages/canon/src/components/Box/styles.css
@@ -1,4 +1,4 @@
.canon-Box {
font-family: var(--canon-font-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
diff --git a/packages/canon/src/components/Button/styles.css b/packages/canon/src/components/Button/styles.css
index a90fe59348..6bfd93a8ea 100644
--- a/packages/canon/src/components/Button/styles.css
+++ b/packages/canon/src/components/Button/styles.css
@@ -36,14 +36,14 @@
&:hover {
background-color: transparent;
box-shadow: inset 0 0 0 1px var(--canon-border-focus);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
}
}
.canon-Button--variant-secondary {
background-color: transparent;
box-shadow: inset 0 0 0 1px var(--canon-border);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
&:hover {
box-shadow: inset 0 0 0 1px var(--canon-border-hover);
@@ -52,10 +52,10 @@
.canon-Button--variant-tertiary {
background-color: transparent;
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
&:hover {
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
}
}
diff --git a/packages/canon/src/components/Checkbox/styles.css b/packages/canon/src/components/Checkbox/styles.css
index 5dae047191..1da96e8344 100644
--- a/packages/canon/src/components/Checkbox/styles.css
+++ b/packages/canon/src/components/Checkbox/styles.css
@@ -23,7 +23,7 @@
gap: var(--canon-space-2);
font-size: var(--canon-font-size-xs);
font-family: var(--canon-font-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
user-select: none;
&:hover {
diff --git a/packages/canon/src/components/Field/Field.styles.css b/packages/canon/src/components/Field/Field.styles.css
index 6a8e3c8e22..6bf695fc97 100644
--- a/packages/canon/src/components/Field/Field.styles.css
+++ b/packages/canon/src/components/Field/Field.styles.css
@@ -24,14 +24,14 @@
.canon-FieldLabel {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
margin-bottom: var(--canon-space-1_5);
}
.canon-FieldDescription {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
margin: 0;
padding-top: var(--canon-space-1_5);
}
@@ -47,7 +47,7 @@
.canon-FieldValidity {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
margin: 0;
padding-top: var(--canon-space-1_5);
}
diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css
index 2db11d7eb2..a730afe9f0 100644
--- a/packages/canon/src/components/Heading/styles.css
+++ b/packages/canon/src/components/Heading/styles.css
@@ -16,7 +16,7 @@
.canon-Heading {
font-family: var(--canon-font-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
line-height: 100%;
padding: 0;
margin: 0;
diff --git a/packages/canon/src/components/Input/Input.styles.css b/packages/canon/src/components/Input/Input.styles.css
index 72248f887e..cfeed27b48 100644
--- a/packages/canon/src/components/Input/Input.styles.css
+++ b/packages/canon/src/components/Input/Input.styles.css
@@ -21,13 +21,13 @@
background-color: var(--canon-bg-elevated);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out;
width: 100%;
}
.canon-Input::placeholder {
- color: var(--canon-fg-secondary);
+ color: var(--canon-fg-text-secondary);
}
.canon-Input:hover {
diff --git a/packages/canon/src/components/Text/styles.css b/packages/canon/src/components/Text/styles.css
index 871960b8db..9cf8c884fb 100644
--- a/packages/canon/src/components/Text/styles.css
+++ b/packages/canon/src/components/Text/styles.css
@@ -16,7 +16,7 @@
.canon-Text {
font-family: var(--canon-font-regular);
- color: var(--canon-fg-primary);
+ color: var(--canon-fg-text-primary);
padding: 0;
margin: 0;
}
diff --git a/packages/canon/src/css/core.css b/packages/canon/src/css/core.css
index a2e561b134..d744d468d0 100644
--- a/packages/canon/src/css/core.css
+++ b/packages/canon/src/css/core.css
@@ -95,8 +95,8 @@
--canon-border-hover: rgba(0, 0, 0, 0.2);
--canon-border-success: #008000;
--canon-border-warning: #e36d05;
- --canon-fg-primary: #000;
- --canon-fg-secondary: #646464;
+ --canon-fg-text-primary: #000;
+ --canon-fg-text-secondary: #646464;
--canon-fg-link: #fff;
--canon-fg-link-hover: #fff;
--canon-fg-accent: #fff;
@@ -137,6 +137,6 @@
--canon-fg-warning: #e36d05;
--canon-fg-link: #fff;
--canon-fg-link-hover: #fff;
- --canon-fg-primary: #000;
- --canon-fg-secondary: #646464;
+ --canon-fg-text-primary: #000;
+ --canon-fg-text-secondary: #646464;
}
From 5258c3511aa7e8985f00b4aa8e08df3e464c1a16 Mon Sep 17 00:00:00 2001
From: esw-afabiano <135993301+esw-afabiano@users.noreply.github.com>
Date: Fri, 24 Jan 2025 13:29:40 -0300
Subject: [PATCH 36/37] Update .changeset/loud-baboons-relate.md
Co-authored-by: Ben Lambert
Signed-off-by: esw-afabiano <135993301+esw-afabiano@users.noreply.github.com>
---
.changeset/loud-baboons-relate.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.changeset/loud-baboons-relate.md b/.changeset/loud-baboons-relate.md
index 408188abd0..a6ea65f685 100644
--- a/.changeset/loud-baboons-relate.md
+++ b/.changeset/loud-baboons-relate.md
@@ -3,5 +3,4 @@
'@backstage/plugin-scaffolder': minor
---
-Changes the TaskLogStream to take up all remaining space
-Changes the RealLogViewer to always display the last line by default
+Updating the `TaskLogStream` to take up all space in a running task, and also show the last line of the log by default
From 5b78cd9c17842d99e65c0831a244b2f22f213e2f Mon Sep 17 00:00:00 2001
From: esw-afabiano <135993301+esw-afabiano@users.noreply.github.com>
Date: Fri, 24 Jan 2025 13:29:47 -0300
Subject: [PATCH 37/37] Update .changeset/loud-baboons-relate.md
Co-authored-by: Ben Lambert
Signed-off-by: esw-afabiano <135993301+esw-afabiano@users.noreply.github.com>
---
.changeset/loud-baboons-relate.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.changeset/loud-baboons-relate.md b/.changeset/loud-baboons-relate.md
index a6ea65f685..8f719861e1 100644
--- a/.changeset/loud-baboons-relate.md
+++ b/.changeset/loud-baboons-relate.md
@@ -1,5 +1,5 @@
---
-'@backstage/core-components': minor
+'@backstage/core-components': patch
'@backstage/plugin-scaffolder': minor
---