Merge branch 'canon-styles-updates' into canon-website

This commit is contained in:
Charles de Dreuille
2025-01-07 15:18:04 +00:00
21 changed files with 213 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Allow passing down `withSearch` prop to `EntityTechdocsContent` component since it was `true` by default, now user can use the `EntityTechdocsContent` component _without_ showing the search field on top of the content.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Fix field extension validation not working when field is in dependencies in an array field
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': patch
---
Fixing spelling mistake in translation
+1 -1
View File
@@ -59,7 +59,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
- name: Build and push
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0
+1
View File
@@ -281,4 +281,5 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [Tele2 Kazakhstan](https://tele2.kz/) / [Altel Digital](https://digital.altel.kz/) | [Kuanysh Bekkulov](https://www.linkedin.com/in/kuanysh-bekkulov/), [Alexandr Puzeyev](https://www.linkedin.com/in/alexandr-puzeyev/) | Developer portal: services, components, APIs, and resources; includes documentation (Docs-as-Code), service templates, and plugins for integration with internal systems and tools.
| [Axelerant](https://www.axelerant.com/) | [Zeshan Ziya](https://github.com/zeshanziya) | Developer portal, main gateway to infrastructure, documentation, internal tooling, and service catalog with a focus on project visibility.
| [KnowBe4](https://www.knowbe4.com) | [Brandon Vicinus](https://www.linkedin.com/in/bvicinus/) | Internal Developer Portal managed by the Developer Experience Team. IDP hosts many different internal tools as plugins created by multiple teams, many of which are directly integrated with the Service Catalog. |
| [Scalepoint](https://scalepoint.com) | [Yuriy Ostapenko](https://github.com/yuriyostapenko), [Dmytro Pasko](https://github.com/dimapasko), [Yuri Sedykh ](https://github.com/yuiri-sedykh), [Bartosz Wisniewski](https://github.com/Epgor) | Internal Developer Portal: Software Catalog with infrastructure resources and dependencies, Software Templates, TechDocs, Tech Radar, Kubernetes and Observability, as well as custom CI/CD components |
+4 -1
View File
@@ -239,4 +239,7 @@ privateKey: |
-----END RSA PRIVATE KEY-----
```
**Warning: Sensitive information, such as private keys, should not be hard coded**. We recommend that this entire file should be a secret and stored as such in a secure storage solution like Vault, to ensure they are neither exposed nor misused. This example key part only shows the format on how to use the yaml | syntax to make sure that the key is valid.
> [!WARNING]
> Sensitive information, such as private keys, should not be hard coded.
We recommend that this entire file should be a secret and stored as such in a secure storage solution like Vault, to ensure they are neither exposed nor misused. This example key part only shows the format on how to use the yaml | syntax to make sure that the key is valid.
@@ -220,7 +220,7 @@ const scaffolderModuleCustomExtensions = createBackendModule({
async init({ scaffolder /* ..., other dependencies */ }) {
// Here you have the opportunity to interact with the extension
// point before the plugin itself gets instantiated
scaffolder.addActions(new createNewFileAction()); // just an example
scaffolder.addActions(createNewFileAction()); // just an example
},
});
},
@@ -0,0 +1,14 @@
---
title: Cyclops Modules
author: Cyclops UI
authorUrl: https://cyclops-ui.com/
category: App Delivery
description: Manage Cyclops Modules through Backstage catalog
documentation: https://github.com/cyclops-ui/backstage-plugins#readme
iconUrl: /img/cyclops.svg
npmPackageName: '@cyclopsui/backstage-plugin-cyclops-modules'
tags:
- Kubernetes
- Productivity
- Delivery
addedDate: '2024-01-02'
@@ -6,4 +6,5 @@ category: Monitoring
description: A plugin that provides a way to view and manage Knative Event Mesh resources.
documentation: https://knative.dev/docs/install/installing-backstage-plugins/
npmPackageName: '@knative-extensions/plugin-knative-event-mesh-backend'
iconUrl: https://raw.githubusercontent.com/knative/community/refs/heads/main/icons/logo.svg
addedDate: '2024-12-16'
+5
View File
@@ -106,6 +106,11 @@ const Community = () => {
url: 'https://www.alauda.io/community/169249',
logo: 'img/partner-logo-alauda.png',
},
{
name: 'Liatrio',
url: 'https://www.liatrio.com/service-offerings/backstage',
logo: 'img/partner-logo-liatrio.png',
},
];
//#endregion
+51
View File
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 480.6 480">
<defs>
<style>
.cls-1 {
fill: #fff;
}
.cls-2 {
fill: none;
}
.cls-2, .cls-3 {
stroke: #000;
stroke-miterlimit: 10;
stroke-width: .4px;
}
.cls-4 {
fill: #ff8901;
}
.cls-5 {
fill: #f27221;
}
.cls-6 {
fill: #dbdbdb;
}
</style>
</defs>
<g>
<g id="Layer_1">
<rect class="cls-4" x=".6" width="480" height="480" rx="52.2" ry="52.2"/>
<g>
<path class="cls-2" d="M240.7,109.4"/>
<path class="cls-2" d="M240.7,316.5"/>
<g>
<path class="cls-5" d="M169.9,265.8"/>
<line class="cls-5" x1="143.8" y1="248.4" x2="143.8" y2="248.4"/>
</g>
<path class="cls-5" d="M291.9,145.8c-35-13-68.6-13.9-103.6-.9-28.3,10.5-57,40-54.5,74.7,1.4,20.2,13.8,35.7,33.2,41.6,16.8,5.1,34.3,3.4,51.2,1.8,4.8-.5,11.2-2,16-2.3,10.5-.7,23.2.4,33.5,1.4,8.1.8,13,2.6,21.4,2.6s4.7,0,7.1-.2c18.3-1.1,48.2-8.8,50.7-45.1,2.4-34.8-26.7-63-55-73.5ZM344.1,219.4c-2.2,31.6-27.4,39.8-48.2,41.1-10.4.7-21.1-.4-31.3-1.4-8.1-.8-16.5-1.6-24.8-1.6s-4.8,0-7.2.2c-4.9.3-9.9.8-14.7,1.3-16.5,1.6-33.6,3.3-49.7-1.6-17.8-5.4-30.5-19.2-31.8-37.6-2.3-32.7,27.1-58.8,54-68.8,34-12.7,67.1-12.7,101.2,0,26.9,10,54.9,35.7,52.6,68.4Z"/>
<path class="cls-1" d="M289.7,154.4c-33-12.3-65-12.3-98,0-26.1,9.7-54.5,35-52.3,66.8,1.2,17.9,13.6,31.3,30.8,36.5,15.6,4.7,32.1,3.1,48.1,1.6,4.7-.5,9.5-.9,14.3-1.2,2.3-.1,4.7-.2,7-.2,8.1,0,16.2.8,24.1,1.5,9.9,1,20.2,2,30.3,1.3,20.1-1.3,44.5-9.2,46.6-39.9,2.2-31.7-24.9-56.6-50.9-66.3Z"/>
<path class="cls-3" d="M224.9,170.1c-1.6,1.2-3.9,3.3-5.6,6.6-5.1,9.9,1.1,20.2,1.4,20.6,6.6,10.6,19.6,10.7,20.3,10.7.8,0,15.1-.2,21-10.9,4.6-8.2-.1-18.8-.7-20.5-.7-2.1-1.8-5-7-8.5-5.6-3.9-11.6-3.6-14.4-3.4-7.5.4-12.8,3.8-15.1,5.5"/>
<path class="cls-1" d="M243.3,172.2c-.5.4-1.3,1.2-1.9,2.5-1.7,3.7.4,7.5.5,7.7,2.3,3.9,6.7,4,7,4,.3,0,5.2,0,7.2-4,1.6-3,0-7-.3-7.6-.3-.8-.6-1.9-2.4-3.2-1.9-1.4-4-1.3-4.9-1.3-2.6.1-4.4,1.4-5.2,2.1"/>
<path class="cls-6" d="M291.9,153.7c-11.6-4.3-23.2-7.1-34.7-8.4,1.8.2-1.7-.8,0,0,5.5,2.6,11.5,4.1,17,6.7,10.5,5,21.9,8.9,30.4,16.9,8.4,7.8,15.8,16.9,19.9,28.3,3.2,8.9,6.2,18.7,4.5,28.4-1.4,8-4.2,15.1-9.7,21-4,4.2-8.9,8.3-14.8,9.4-6.3,1.2-4.1.8-10.8,1.3-3.1.2-13.2.7-17.2,1.2-3,.4-8.2.9-11,.6,10.1,1.2,20.4,2.4,30.6,1.8,20.1-1.3,44.5-10.1,46.7-40.8,2.2-31.7-24.9-56.6-50.9-66.3Z"/>
<path d="M291.1,150.8c-33.9-12.6-66.8-12.6-100.7,0-27.4,10.2-55.8,36.5-53.5,70.3,1.4,19.6,13.4,34.6,32.2,40.3,16.3,4.9,33.2,3.3,49.6,1.7,4.7-.5,10.8-1.9,15.5-2.2,10.1-.6,22.4.4,32.4,1.4,7.9.8,12.6,2.5,20.7,2.5s4.6,0,6.9-.2c17.7-1.1,46.7-8.5,49.1-43.8,2.3-33.7-24.9-59.7-52.3-70ZM340.7,220.8c-2.1,30.7-26.5,38.6-46.6,39.9-10.1.6-20.4-.4-30.3-1.3-7.9-.8-15.9-1.5-24.1-1.5s-4.7,0-7,.2c-4.7.3-9.6.8-14.3,1.2-16,1.6-32.6,3.2-48.1-1.6-17.2-5.2-29.6-18.6-30.8-36.5-2.2-31.7,26.3-57,52.3-66.8,33-12.3,65-12.3,98,0,26.1,9.7,53.1,34.6,50.9,66.3Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+14
View File
@@ -24,3 +24,17 @@ The resulting changes in the file system should be committed to your repo.
The yarn plugin recognizes the version string `"backstage:^"`, and replaces it
with the appropriate version based on the overall Backstage version in
backstage.json.
## Local Development
- Run unit tests: `yarn test`
- Build the plugin locally: `yarn build`
- Rebuild whenever plugin files change: `yarn start`
- Install local build (in a package directory outside the Backstage monorepo):
`yarn plugin import
/path/to/backstage-repo/packages/yarn-plugin/bundles/@yarnpkg/plugin-backstage.js`
The plugin can be manually tested in any repository running at least yarn 4.1.1.
Sadly it can't be manually tested directly in the Backstage monorepo - since
packages in this repository use `workspace:^` dependencies, there's no use case
for the yarn plugin.
+1 -1
View File
@@ -115,7 +115,7 @@ export const catalogTranslationRef: TranslationRef<
readonly 'hasSystemsCard.emptyMessage': 'No system is part of this domain';
readonly 'relatedEntitiesCard.emptyHelpLinkTitle': 'Learn how to change this';
readonly 'systemDiagramCard.title': 'System Diagram';
readonly 'systemDiagramCard.description': 'Use pinch & zoo to move around the diagram.';
readonly 'systemDiagramCard.description': 'Use pinch & zoom to move around the diagram.';
readonly 'systemDiagramCard.edgeLabels.dependsOn': 'depends on';
readonly 'systemDiagramCard.edgeLabels.partOf': 'part of';
readonly 'systemDiagramCard.edgeLabels.provides': 'provides';
+1 -1
View File
@@ -156,7 +156,7 @@ export const catalogTranslationRef = createTranslationRef({
},
systemDiagramCard: {
title: 'System Diagram',
description: 'Use pinch & zoo to move around the diagram.',
description: 'Use pinch & zoom to move around the diagram.',
edgeLabels: {
partOf: 'part of',
provides: 'provides',
@@ -435,4 +435,62 @@ describe('createAsyncValidators', () => {
expect(validators.CustomLinkField).toHaveBeenCalled();
});
it('should validate field in the dependencies in an array field', async () => {
const schema: JsonObject = {
title: 'Make a choice',
properties: {
myArray: {
type: 'array',
title: 'Array',
items: {
type: 'object',
required: ['selector'],
properties: {
selector: {
title: 'Selector',
type: 'string',
enum: ['Choice 1', 'Choice 2'],
},
},
dependencies: {
selector: {
oneOf: [
{ properties: { selector: { enum: ['Choice 1'] } } },
{
properties: {
selector: { enum: ['Choice 2'] },
customValidatedField: {
title: 'Custom validated field',
type: 'string',
'ui:field': 'ValidateKebabCase',
},
},
},
],
},
},
},
},
},
};
const validators = { ValidateKebabCase: jest.fn() };
const validate = createAsyncValidators(schema, validators, {
apiHolder: { get: jest.fn() },
});
await validate({
myArray: [
{
selector: 'Choice 2',
customValidatedField: 'apple',
},
{ selector: 'Choice 1' },
],
});
expect(validators.ValidateKebabCase).toHaveBeenCalled();
});
});
@@ -135,6 +135,26 @@ export const createAsyncValidators = (
for (const [, propValue] of Object.entries(properties)) {
await doValidate(propValue);
}
if (Array.isArray(value)) {
for (const [_, v] of Object.entries(value)) {
const { schema: itemSchema, uiSchema: itemUiSchema } =
extractSchemaFromStep(definitionInSchema.items);
if (isObject(v)) {
for (const [pK, pV] of Object.entries(v)) {
if ('ui:field' in itemUiSchema[pK]) {
await validateForm(
itemUiSchema[pK]['ui:field'],
pK,
pV,
itemSchema,
itemUiSchema,
);
}
}
}
}
}
} else if (isObject(value)) {
formValidation[key] = await validate(formData, pointer, value);
}
+12 -6
View File
@@ -133,9 +133,12 @@ export type DocsTableRow = {
};
// @public
export const EmbeddedDocsRouter: (
props: PropsWithChildren<{}>,
) => React_2.JSX.Element;
export const EmbeddedDocsRouter: ({
children,
withSearch,
}: React_2.PropsWithChildren<{
withSearch?: boolean | undefined;
}>) => React_2.JSX.Element;
// @public
export const EntityListDocsGrid: (
@@ -191,9 +194,12 @@ export type EntityListDocsTableProps = {
};
// @public
export const EntityTechdocsContent: (props: {
children?: ReactNode;
}) => JSX_2.Element;
export const EntityTechdocsContent: ({
children,
withSearch,
}: PropsWithChildren<{
withSearch?: boolean | undefined;
}>) => JSX_2.Element;
// @public
export const isTechDocsAvailable: (entity: Entity) => boolean;
+11 -5
View File
@@ -57,16 +57,19 @@ export const Router = () => {
};
export const EmbeddedDocsRouter = (
props: PropsWithChildren<{ emptyState?: React.ReactElement }>,
props: PropsWithChildren<{
emptyState?: React.ReactElement;
withSearch?: boolean;
}>,
) => {
const { children, emptyState } = props;
const { children, emptyState, withSearch = true } = props;
const { entity } = useEntity();
// Using objects instead of <Route> elements, otherwise "outlet" will be null on sub-pages and add-ons won't render
const element = useRoutes([
{
path: '/*',
element: <EntityPageDocs entity={entity} />,
element: <EntityPageDocs entity={entity} withSearch={withSearch} />,
children: [
{
path: '*',
@@ -96,8 +99,11 @@ export const EmbeddedDocsRouter = (
*
* @public
*/
export const LegacyEmbeddedDocsRouter = (props: PropsWithChildren<{}>) => {
export const LegacyEmbeddedDocsRouter = ({
children,
withSearch = true,
}: PropsWithChildren<{ withSearch?: boolean }>) => {
// Wrap the Router to avoid exposing the emptyState prop in the non-alpha
// public API and make it easier for us to change later.
return <EmbeddedDocsRouter children={props.children} />;
return <EmbeddedDocsRouter children={children} withSearch={withSearch} />;
};
+3 -3
View File
@@ -19434,13 +19434,13 @@ __metadata:
linkType: hard
"@types/dockerode@npm:^3.3.0, @types/dockerode@npm:^3.3.29":
version: 3.3.32
resolution: "@types/dockerode@npm:3.3.32"
version: 3.3.33
resolution: "@types/dockerode@npm:3.3.33"
dependencies:
"@types/docker-modem": "*"
"@types/node": "*"
"@types/ssh2": "*"
checksum: 17bfa92511cdc6ab51a67cb4678931b43670feffd737ba593c3ff90a6f71673aa04f8a81524690dddc08b483628d657a338a176171ff131de9e0efba4c3ecc11
checksum: 4e3ed41f3b89a213c9ba923862b653f54ee7232b2c95553410d0c3846396efb592d0291fa2f50d4b47d42a2ae0b49f422e72efcdd845d0ebb60da2e8990e9293
languageName: node
linkType: hard