From 9861bddf5cb503eb471bd1d9bd9cfdd188fc0d62 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Mon, 17 Mar 2025 11:45:01 +0530 Subject: [PATCH 001/143] Fix:Add auth provider docs Signed-off-by: AmbrishRamachandiran --- docs/auth/add-auth-provider.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md index 51424f1c10..8f04f71a39 100644 --- a/docs/auth/add-auth-provider.md +++ b/docs/auth/add-auth-provider.md @@ -123,9 +123,9 @@ due to its comprehensive set of supported authentication [1.](#create-new-auth-provider-module) Create a new auth provider module -[3.](#adding-an-oauth-based-provider) or [adding a proxy auth based provider](#creating-proxy-auth-based-provider) depending on your needs. +[2.](#adding-an-oauth-based-provider) or [adding a proxy auth based provider](#creating-proxy-auth-based-provider) depending on your needs. -[4.](#add-the-provider-to-the-backend) Add the provider to the backend. +[3.](#add-the-provider-to-the-backend) Add the provider to the backend. ### Create new auth provider module From d945206377ae7a94303c5d00587aef4062058c77 Mon Sep 17 00:00:00 2001 From: Sander Aernouts Date: Wed, 8 Jan 2025 17:08:56 +0100 Subject: [PATCH 002/143] feat(azure): support managed identity federated credentials Signed-off-by: Sander Aernouts --- .changeset/four-snails-argue.md | 26 +++ docs/integrations/azure/locations.md | 167 ++++++++++++++++-- packages/integration/config.d.ts | 1 + packages/integration/report.api.md | 16 +- ...chedAzureDevOpsCredentialsProvider.test.ts | 74 ++++++++ .../CachedAzureDevOpsCredentialsProvider.ts | 21 ++- .../integration/src/azure/ClientAssertion.ts | 26 +++ .../ManagedIdentityClientAssertion.test.ts | 124 +++++++++++++ .../azure/ManagedIdentityClientAssertion.ts | 75 ++++++++ packages/integration/src/azure/config.test.ts | 60 ++++++- packages/integration/src/azure/config.ts | 44 ++++- packages/integration/src/azure/index.ts | 1 + 12 files changed, 611 insertions(+), 24 deletions(-) create mode 100644 .changeset/four-snails-argue.md create mode 100644 packages/integration/src/azure/ClientAssertion.ts create mode 100644 packages/integration/src/azure/ManagedIdentityClientAssertion.test.ts create mode 100644 packages/integration/src/azure/ManagedIdentityClientAssertion.ts diff --git a/.changeset/four-snails-argue.md b/.changeset/four-snails-argue.md new file mode 100644 index 0000000000..905e52a559 --- /dev/null +++ b/.changeset/four-snails-argue.md @@ -0,0 +1,26 @@ +--- +'@backstage/integration': minor +--- + +Added support for federated credentials using managed identities in the Azure DevOps integration. Federated credentials are only available for Azure DevOps organizations that have been configured to use Entra ID for authentication. + +```diff +integrations: + azure: + - host: dev.azure.com + credentials: ++ - clientId: ${APP_REGISTRATION_CLIENT_ID} ++ managedIdentityClientId: system-assigned ++ tenantId: ${AZURE_TENANT_ID} +``` + +This also adds support for automatically using the system-assigned managed identity of an Azure resource by specifying `system-assigned` as the client ID of the managed identity. + +```diff +integrations: + azure: + - host: dev.azure.com + credentials: +- - clientId: ${AZURE_CLIENT_ID} ++ - clientId: system-assigned +``` diff --git a/docs/integrations/azure/locations.md b/docs/integrations/azure/locations.md index ddc95b65eb..61c54287c9 100644 --- a/docs/integrations/azure/locations.md +++ b/docs/integrations/azure/locations.md @@ -13,7 +13,17 @@ or registered with the [catalog-import](https://github.com/backstage/backstage/tree/master/plugins/catalog-import) plugin. -Using a service principal: +## Authentication + +The Azure integration supports several methods to authenticate against Azure DevOps. The following sections describe how to configure the integration for each authentication method. + +It is also possible to configure separate authentication methods for different Azure DevOps organizations. This is useful if you have multiple organizations and want to use (or have to) different credentials for each organization. + +### Using a service principal with a client secret + +A service principal is an Entra ID identity that can be used to authenticate against Azure DevOps. The service principal is created in Entra ID and has a client ID and client secret (akin to a username and password). + +The following configuration shows how to use a service principal to authenticate against Azure DevOps: ```yaml integrations: @@ -25,7 +35,29 @@ integrations: tenantId: ${AZURE_TENANT_ID} ``` -Using a managed identity: +See the Azure DevOps documentation on how to grant access to the [service principal](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity). + +#### Using a system-assigned managed identity + +A system-assigned [managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) is an Entra ID identity that is tied to a specific Azure resource and managed by Azure. In contrast to a user-assigned managed identity, a system-assigned managed identity shares the lifecycle of the resource to which it is assigned and Azure guarantees that the identity can only be used by the specific resource. + +The following configuration shows how to use a system-assigned managed identity to authenticate against Azure DevOps: + +```yaml +integrations: + azure: + - host: dev.azure.com + credentials: + - clientId: system-assigned +``` + +See the Azure DevOps documentation on how to grant access to the [managed identity](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity). + +#### Using a user-assigned managed identity + +A user-assigned [managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) is an Entra ID identity that is created as a standalone resource by the user and assigned to one or more Azure resources. This allows you to use the same managed identity across multiple resources. + +The following configuration shows how to use a user-assigned managed identity to authenticate against Azure DevOps: ```yaml integrations: @@ -35,7 +67,13 @@ integrations: - clientId: ${AZURE_CLIENT_ID} ``` -Using a personal access token (PAT): +See the Azure DevOps documentation on how to grant access to the [managed identity](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity). + +### Using a personal access token (PAT) + +A personal access token (PAT) is a token you generate with a specific scope and expiration date. It allows Backstage to authenticate against Azure DevOps on your behalf. + +The following configuration shows how to use a personal access token to authenticate against Azure DevOps: ```yaml integrations: @@ -45,6 +83,55 @@ integrations: - personalAccessToken: ${PERSONAL_ACCESS_TOKEN} ``` +See the Azure DevOps documentation on how to create a [personal access token](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate) + +### Using a service principal with a managed identity to generate the client assertion + +Using a managed identity to generate a client assertion is an advanced scenario. It requires you to setup a federated credential for the app registration in Azure Entra ID. + +It is most useful when you want to [authenticate against an Azure DevOps organization in a different tenant](#authenticate-against-an-azure-devops-organization-in-a-different-tenant) than the managed identity itself. Otherwise [a regular managed identity](#using-a-system-assigned-managed-identity) is probably a more suitable choice. + +#### Add a federated credential + +To be able to use a managed identity to generate a client assertion, you need to create a federated credential in Azure Entra ID. Follow these steps: + +1. Create an app registration in Entra ID (or use an existing one). +2. Navigate to the "Certificates & secrets" tab for your app registration. +3. Add a new federated credential using the "Customer managed keys" scenario. +4. Select the managed identity you want to use to generate the client assertion. +5. Enter the name and description. +6. Click "Add". + +You can now add the required configuration to the Azure DevOps integration in Backstage. The `${APP_REGISTRATION_CLIENT_ID}` is the client ID of the app registration in Entra ID where you added the federated credential. + +#### Using a system-assigned managed identity to generate the client assertion + +This is the most secure option because Azure guarantees that the identity can only be used by the specific resource, whereas a user-assigned managed identity can be assigned to any resource in the same tenant. + +```yaml +integrations: + azure: + - host: dev.azure.com + credentials: + - clientId: ${APP_REGISTRATION_CLIENT_ID} + managedIdentityClientId: system-assigned + tenantId: ${AZURE_TENANT_ID} +``` + +#### Using a user-assigned managed identity to generate the client assertion + +```yaml +integrations: + azure: + - host: dev.azure.com + credentials: + - clientId: ${APP_REGISTRATION_CLIENT_ID} + managedIdentityClientId: ${MANAGED_IDENTITY_CLIENT_ID} + tenantId: ${AZURE_TENANT_ID} +``` + +### Authenticating against multiple Azure DevOps organizations + You can use specific credentials for different Azure DevOps organizations by specifying the `organizations` field on the credential: ```yaml @@ -68,27 +155,76 @@ integrations: If you do not specify the `organizations` field the credential will be used for all organizations for which no other credential is configured. +### Authenticate against an Azure DevOps organization in a different tenant + +If you need to authenticate against an Azure DevOps organization in a different tenant than the service principal, you have to either: + +- [Create a multi-tenant application in Entra ID](https://learn.microsoft.com/en-us/entra/identity-platform/single-and-multi-tenant-apps). +- [Convert the existing application to a multi-tenant application](https://learn.microsoft.com/en-gb/entra/identity-platform/howto-convert-app-to-be-multi-tenant#update-registration-to-be-multitenant). + :::note Note -An Azure DevOps provider is added automatically at startup for -convenience, so you only need to list it if you want to supply a -[personalAccessToken](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate), -a [service principal](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity), -or a [managed identity](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity) +Make sure that your application requests at least one Graph API permission. This is required to be able to install the application in another tenant. The least privileged permission you can request is the [`email` permission](https://learn.microsoft.com/en-us/graph/permissions-reference#email) with type `Delegated`. This allows the application to read the e-mail address of the signed-in user, but without the [`openid` permission](https://learn.microsoft.com/en-us/graph/permissions-reference#openid) users cannot actually sign in. ::: +After you have done that, an admin from the other tenant has to install your application by providing admin consent for the requested permissions. This can be done by visiting the following URL: + +```plaintext +https://login.microsoftonline.com//oauth2/authorize?client_id=&response_type=code&redirect_uri= +``` + +The `` is the tenant ID of the other tenant, `` is the client ID of the application (in your tenant), and `` is the redirect URI configured for the application. The redirect URI must be a valid URI in the application registration, but you can use any valid URI for this purpose, for example `https://backstage.io`. + +After the admin has consented to the application, an Enterprise Application, also called a Service Principal, will be created in the other tenant with the same client ID as the app registration in the original tenant. You can now grant the service principal access to the Azure DevOps organization in the other tenant. To authenticate against the Azure DevOps organization in the other tenant, you can use the same service principal as before, but with the tenant ID of the other tenant: + +```yaml +integrations: + azure: + - host: dev.azure.com + credentials: + - clientId: ${APP_REGISTRATION_CLIENT_ID} + managedIdentityClientId: system-assigned + tenantId: ${OTHER_TENANT_ID} +``` + +Where `${APP_REGISTRATION_CLIENT_ID}` is the client ID of the multi-tenant app registration in you created in your own tenant, and `${OTHER_TENANT_ID}` is the tenant ID of the other tenant where you . + +:::note Note + +The example above uses a [system-assigned managed identity to generate the client assertion](#using-a-system-assigned-managed-identity-to-generate-the-client-assertion). You can also use a [user-assigned managed identity to generate the client assertion](#using-a-user-assigned-managed-identity-to-generate-the-client-assertion) or a client secret to authenticate for the application. + +However a system-assigned managed identity is the most secure option because: + +- Azure guarantees that the identity can only be used by the specific resource, whereas a user-assigned managed identity can be used by any resource. +- There is no need to manage the underlying secrets, Azure takes care of that for you. + +::: + +## Configuration schema + The configuration is a structure with these elements: -- `credentials`: (optional): A service principal, managed identity, or personal access token +- `credentials`: (optional): must be one of the following: + - A service principal using a client secret + - A service principal using a managed identity client assertion + - A managed identity + - A personal access token -The `credentials` element is a structure with these elements: +The `credentials` element is an array where each entry is a structure with exactly these of elements: -- `organizations`: (optional): A list of organizations for which this credential should be used. If not specified the credential will be used for all organizations for which no other credential is configured. -- `clientId`: The client ID of the service principal or managed identity (required for service principal and managed identities) -- `clientSecret`: The client secret of the service principal (required for service principal) -- `tenantId`: The tenant ID of the service principal (required for service principal) -- `personalAccessToken`: The personal access token (required for personal access token) +- For a service principal with client secret: + - `clientId`: The client ID of the service principal + - `clientSecret`: The client secret of the service principal + - `tenantId`: The tenant ID of the service principal +- For a service principal with managed identity client assertion: + - `clientId`: The client ID of the service principal + - `managedIdentityClientId`: the client ID of the managed identity used to generate the client assertion token. Use `system-assigned` for system-assigned managed identities or the client ID of a user-assigned managed identity. + - `tenantId`: The tenant ID of the service principal +- For managed identity: + - `clientId`: the client ID of the managed identity used to generate the client assertion token. +- For personal access token: + - `personalAccessToken`: The personal access token :::note Note @@ -96,5 +232,6 @@ The `credentials` element is a structure with these elements: - You can only use a service principal or managed identity for Microsoft Entra ID (formerly Azure Active Directory) backed Azure DevOps organizations - You can only specify one credential per host without any organizations specified - The personal access token should just be provided as the raw token generated by Azure DevOps using the format `raw_token` with no base64 encoding. Formatting and base64'ing is handled by dependent libraries handling the Azure DevOps API +- The managed identity used to generate the client assertion must be in the same Entra ID tenant as the app registration. ::: diff --git a/packages/integration/config.d.ts b/packages/integration/config.d.ts index bd5267ab3d..ac3deb736a 100644 --- a/packages/integration/config.d.ts +++ b/packages/integration/config.d.ts @@ -61,6 +61,7 @@ export interface Config { clientSecret?: string; tenantId?: string; personalAccessToken?: string; + managedIdentityClientId?: string; }[]; /** * PGP signing key for signing commits. diff --git a/packages/integration/report.api.md b/packages/integration/report.api.md index c85db9306b..a4a6aa2f14 100644 --- a/packages/integration/report.api.md +++ b/packages/integration/report.api.md @@ -137,6 +137,7 @@ export interface AzureCredentialsManager { // @public export type AzureDevOpsCredential = | AzureClientSecretCredential + | AzureManagedIdentityClientAssertionCredential | AzureManagedIdentityCredential | PersonalAccessTokenCredential; @@ -144,11 +145,13 @@ export type AzureDevOpsCredential = export type AzureDevOpsCredentialKind = | 'PersonalAccessToken' | 'ClientSecret' - | 'ManagedIdentity'; + | 'ManagedIdentity' + | 'ManagedIdentityClientAssertion'; // @public export type AzureDevOpsCredentialLike = Omit< Partial & + Partial & Partial & Partial, 'kind' @@ -204,10 +207,19 @@ export type AzureIntegrationConfig = { commitSigningKey?: string; }; +// @public +export type AzureManagedIdentityClientAssertionCredential = + AzureCredentialBase & { + kind: 'ManagedIdentityClientAssertion'; + tenantId: string; + clientId: string; + managedIdentityClientId: 'system-assigned' | string; + }; + // @public export type AzureManagedIdentityCredential = AzureCredentialBase & { kind: 'ManagedIdentity'; - clientId: string; + clientId: 'system-assigned' | string; }; // @public diff --git a/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.test.ts b/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.test.ts index c9fbb4c324..e65d127ce8 100644 --- a/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.test.ts +++ b/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.test.ts @@ -16,6 +16,7 @@ import { CachedAzureDevOpsCredentialsProvider } from './CachedAzureDevOpsCredentialsProvider'; import { AccessToken, + ClientAssertionCredential, ClientSecretCredential, ManagedIdentityCredential, } from '@azure/identity'; @@ -24,6 +25,11 @@ const MockedClientSecretCredential = ClientSecretCredential as jest.MockedClass< typeof ClientSecretCredential >; +const MockedClientAssertionCredential = + ClientAssertionCredential as jest.MockedClass< + typeof ClientAssertionCredential + >; + const MockedManagedIdentityCredential = ManagedIdentityCredential as jest.MockedClass< typeof ManagedIdentityCredential @@ -46,6 +52,13 @@ describe('CachedAzureDevOpsCredentialsProvider', () => { } as AccessToken), ); + MockedClientAssertionCredential.prototype.getToken.mockImplementation(() => + Promise.resolve({ + expiresOnTimestamp: Date.now() + hours(8), + token: 'fake-client-assertion-token', + } as AccessToken), + ); + MockedManagedIdentityCredential.prototype.getToken.mockImplementation(() => Promise.resolve({ expiresOnTimestamp: Date.now() + hours(8), @@ -89,6 +102,25 @@ describe('CachedAzureDevOpsCredentialsProvider', () => { expect(token).toBe('fake-client-secret-token'); }); + it('Should return a bearer credential when a managed identity client assertion is configured', async () => { + const manager = + CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential({ + kind: 'ManagedIdentityClientAssertion', + clientId: 'id', + managedIdentityClientId: 'managedIdentityClientId', + tenantId: 'tenantId', + }); + + const { headers, type, token } = await manager.getCredentials(); + + expect(headers).toStrictEqual({ + Authorization: `Bearer fake-client-assertion-token`, + }); + + expect(type).toBe('bearer'); + expect(token).toBe('fake-client-assertion-token'); + }); + it('Should return a bearer credential when a managed identity is configured', async () => { const manager = CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential({ @@ -124,6 +156,24 @@ describe('CachedAzureDevOpsCredentialsProvider', () => { ).toHaveBeenCalledTimes(1); }); + it('Should not refresh the managed identity client assertion token when it does not expire within 10 minutes', async () => { + const manager = + CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential({ + kind: 'ManagedIdentityClientAssertion', + clientId: 'id', + managedIdentityClientId: 'managedIdentityClientId', + tenantId: 'tenantId', + }); + + await manager.getCredentials(); + await manager.getCredentials(); + await manager.getCredentials(); + + expect( + MockedClientAssertionCredential.prototype.getToken, + ).toHaveBeenCalledTimes(1); + }); + it('Should return the managed identity token when it does not expire within 10 minutes', async () => { const manager = CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential({ @@ -164,6 +214,30 @@ describe('CachedAzureDevOpsCredentialsProvider', () => { ).toHaveBeenCalledTimes(2); }); + it('Should refresh the managed identity client assertion token when it expires within 10 minutes', async () => { + const manager = + CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential({ + kind: 'ManagedIdentityClientAssertion', + clientId: 'id', + managedIdentityClientId: 'managedIdentityClientId', + tenantId: 'tenantId', + }); + + MockedClientAssertionCredential.prototype.getToken.mockImplementation(() => + Promise.resolve({ + expiresOnTimestamp: Date.now() + minutes(9) + seconds(59), + token: 'fake-client-assertion-token', + } as AccessToken), + ); + + await manager.getCredentials(); + await manager.getCredentials(); + + expect( + MockedClientAssertionCredential.prototype.getToken, + ).toHaveBeenCalledTimes(2); + }); + it('Should refresh the managed identity token when it expires within 10 minutes', async () => { const manager = CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential({ diff --git a/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.ts b/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.ts index aee4cefc41..be721e483e 100644 --- a/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.ts +++ b/packages/integration/src/azure/CachedAzureDevOpsCredentialsProvider.ts @@ -15,6 +15,7 @@ */ import { AzureDevOpsCredential, PersonalAccessTokenCredential } from './config'; import { + ClientAssertionCredential, ClientSecretCredential, ManagedIdentityCredential, TokenCredential, @@ -23,6 +24,7 @@ import { AzureDevOpsCredentials, AzureDevOpsCredentialsProvider, } from './types'; +import { ManagedIdentityClientAssertion } from './ManagedIdentityClientAssertion'; type CachedAzureDevOpsCredentials = AzureDevOpsCredentials & { expiresAt?: number; @@ -59,9 +61,26 @@ export class CachedAzureDevOpsCredentialsProvider credential.clientSecret, ), ); + + case 'ManagedIdentityClientAssertion': { + const clientAssertion = new ManagedIdentityClientAssertion({ + clientId: credential.managedIdentityClientId, + }); + + return CachedAzureDevOpsCredentialsProvider.fromTokenCredential( + new ClientAssertionCredential( + credential.tenantId, + credential.clientId, + () => clientAssertion.getSignedAssertion(), + ), + ); + } + case 'ManagedIdentity': return CachedAzureDevOpsCredentialsProvider.fromTokenCredential( - new ManagedIdentityCredential(credential.clientId), + credential.clientId === 'system-assigned' + ? new ManagedIdentityCredential() + : new ManagedIdentityCredential(credential.clientId), ); default: exhaustiveCheck(credential); diff --git a/packages/integration/src/azure/ClientAssertion.ts b/packages/integration/src/azure/ClientAssertion.ts new file mode 100644 index 0000000000..752dcf4dd1 --- /dev/null +++ b/packages/integration/src/azure/ClientAssertion.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type ClientAssertion = { + /** + * The signed assertion token + */ + signedAssertion: string; + /** + * The assertion's expiration timestamp in milliseconds, UNIX epoch time. + */ + expiresOnTimestamp: number; +}; diff --git a/packages/integration/src/azure/ManagedIdentityClientAssertion.test.ts b/packages/integration/src/azure/ManagedIdentityClientAssertion.test.ts new file mode 100644 index 0000000000..102081c698 --- /dev/null +++ b/packages/integration/src/azure/ManagedIdentityClientAssertion.test.ts @@ -0,0 +1,124 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ManagedIdentityClientAssertion } from './ManagedIdentityClientAssertion'; +import { ManagedIdentityCredential, AccessToken } from '@azure/identity'; + +const seconds = (s: number) => s * 1000; +const minutes = (m: number) => seconds(60) * m; +const hours = (h: number) => minutes(60) * h; +const MockedManagedIdentityCredential = + ManagedIdentityCredential as jest.MockedClass< + typeof ManagedIdentityCredential + >; + +jest.mock('@azure/identity'); + +describe('ManagedIdentityClientAssertion', () => { + beforeEach(() => { + jest.resetAllMocks(); + + MockedManagedIdentityCredential.prototype.getToken.mockImplementation(() => + Promise.resolve({ + expiresOnTimestamp: Date.now() + hours(8), + token: 'fake-managed-identity-token', + } as AccessToken), + ); + }); + + it('Should return a cached token if it does not expire within 5 minutes', async () => { + const clientAssertion = new ManagedIdentityClientAssertion({ + clientId: 'clientId', + }); + + // First call to getToken to cache the token + await clientAssertion.getSignedAssertion(); + // Second call should return the cached token + const token = await clientAssertion.getSignedAssertion(); + + expect(token).toBe('fake-managed-identity-token'); + expect( + MockedManagedIdentityCredential.prototype.getToken, + ).toHaveBeenCalledTimes(1); + }); + + it('Should obtain a new token if the cached token expires within 5 minutes', async () => { + const clientAssertion = new ManagedIdentityClientAssertion({ + clientId: 'clientId', + }); + + MockedManagedIdentityCredential.prototype.getToken.mockImplementationOnce( + () => + Promise.resolve({ + expiresOnTimestamp: Date.now() + minutes(4), + token: 'expiring-soon-token', + } as AccessToken), + ); + + // First call to getToken to cache the expiring token + await clientAssertion.getSignedAssertion(); + + MockedManagedIdentityCredential.prototype.getToken.mockImplementationOnce( + () => + Promise.resolve({ + expiresOnTimestamp: Date.now() + hours(8), + token: 'new-managed-identity-token', + } as AccessToken), + ); + + // Second call should obtain a new token + const token = await clientAssertion.getSignedAssertion(); + + expect(token).toBe('new-managed-identity-token'); + expect( + MockedManagedIdentityCredential.prototype.getToken, + ).toHaveBeenCalledTimes(2); + }); + + it('Should obtain a new token if no token is cached', async () => { + const clientAssertion = new ManagedIdentityClientAssertion({ + clientId: 'clientId', + }); + + const token = await clientAssertion.getSignedAssertion(); + + expect(token).toBe('fake-managed-identity-token'); + expect( + MockedManagedIdentityCredential.prototype.getToken, + ).toHaveBeenCalledTimes(1); + }); + + it('Should request a token for the correct scope', async () => { + const clientAssertion = new ManagedIdentityClientAssertion({ + clientId: 'clientId', + }); + + await clientAssertion.getSignedAssertion(); + + expect( + MockedManagedIdentityCredential.prototype.getToken, + ).toHaveBeenCalledWith('api://AzureADTokenExchange'); + }); + + it('Should handle system-assigned managed identity', async () => { + const clientAssertion = new ManagedIdentityClientAssertion(); + + await clientAssertion.getSignedAssertion(); + + expect( + MockedManagedIdentityCredential.prototype.getToken, + ).toHaveBeenCalledWith('api://AzureADTokenExchange'); + }); +}); diff --git a/packages/integration/src/azure/ManagedIdentityClientAssertion.ts b/packages/integration/src/azure/ManagedIdentityClientAssertion.ts new file mode 100644 index 0000000000..5fca816634 --- /dev/null +++ b/packages/integration/src/azure/ManagedIdentityClientAssertion.ts @@ -0,0 +1,75 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ManagedIdentityCredential } from '@azure/identity'; +import { ClientAssertion } from './ClientAssertion'; + +export type ManagedIdentityClientAssertionOptions = { + clientId?: string; +}; + +const fiveMinutes = 5 * 60 * 1000; // 5 minutes in milliseconds +const expiresWithinFiveMinutes = (clientAssertion: ClientAssertion) => + clientAssertion.expiresOnTimestamp - Date.now() <= fiveMinutes; + +/** + * Class representing a Managed Identity Client Assertion. + * This class is responsible for obtaining a signed client assertion using Azure Managed Identity. + */ +export class ManagedIdentityClientAssertion { + private credential: ManagedIdentityCredential; + private clientAssertion?: ClientAssertion; + + /** + * Creates an instance of ManagedIdentityClientAssertion. + * @param options - Optional parameters for the ManagedIdentityClientAssertion. + * - clientId: The client ID of the managed identity. If not provided, 'system-assigned' is used. + */ + constructor(options?: ManagedIdentityClientAssertionOptions) { + let { clientId } = options || {}; + clientId ??= 'system-assigned'; + + this.credential = + clientId === 'system-assigned' + ? new ManagedIdentityCredential() + : new ManagedIdentityCredential(clientId); + } + + /** + * Gets a signed client assertion. + * If a valid client assertion is already cached which doesn't expire soon, it returns the cached assertion. + * Otherwise, it obtains a new access token and creates a new client assertion. + * @returns A promise that resolves to the signed client assertion. + */ + public async getSignedAssertion(): Promise { + if ( + this.clientAssertion !== undefined && + !expiresWithinFiveMinutes(this.clientAssertion) + ) { + return this.clientAssertion.signedAssertion; + } + + const accessToken = await this.credential.getToken( + 'api://AzureADTokenExchange', + ); + + this.clientAssertion = { + signedAssertion: accessToken.token, + expiresOnTimestamp: accessToken.expiresOnTimestamp, + }; + + return accessToken.token; + } +} diff --git a/packages/integration/src/azure/config.test.ts b/packages/integration/src/azure/config.test.ts index dc6781c45e..c1ddf1590f 100644 --- a/packages/integration/src/azure/config.test.ts +++ b/packages/integration/src/azure/config.test.ts @@ -167,7 +167,7 @@ describe('readAzureIntegrationConfig', () => { }); }); - it('reads all values when using a managed identity credential', () => { + it('reads all values when using a managed identity client assertion credential', () => { const output = readAzureIntegrationConfig( buildConfig({ host: 'dev.azure.com', @@ -175,6 +175,62 @@ describe('readAzureIntegrationConfig', () => { { organizations: ['org1', 'org2'], clientId: 'id', + managedIdentityClientId: 'system-assigned', + tenantId: 'tenant', + }, + ], + }), + ); + + expect(output).toEqual({ + host: 'dev.azure.com', + credentials: [ + { + kind: 'ManagedIdentityClientAssertion', + organizations: ['org1', 'org2'], + clientId: 'id', + managedIdentityClientId: 'system-assigned', + tenantId: 'tenant', + }, + ], + }); + }); + + it('reads all values when using a managed identity client assertion credential (without organizations)', () => { + const output = readAzureIntegrationConfig( + buildConfig({ + host: 'dev.azure.com', + credentials: [ + { + clientId: 'id', + managedIdentityClientId: 'system-assigned', + tenantId: 'tenant', + }, + ], + }), + ); + + expect(output).toEqual({ + host: 'dev.azure.com', + credentials: [ + { + kind: 'ManagedIdentityClientAssertion', + clientId: 'id', + managedIdentityClientId: 'system-assigned', + tenantId: 'tenant', + }, + ], + }); + }); + + it('reads all values when using a managed identity credential', () => { + const output = readAzureIntegrationConfig( + buildConfig({ + host: 'dev.azure.com', + credentials: [ + { + organizations: ['org1', 'org2'], + clientId: 'system-assigned', }, ], }), @@ -186,7 +242,7 @@ describe('readAzureIntegrationConfig', () => { { kind: 'ManagedIdentity', organizations: ['org1', 'org2'], - clientId: 'id', + clientId: 'system-assigned', }, ], }); diff --git a/packages/integration/src/azure/config.ts b/packages/integration/src/azure/config.ts index 2910387829..09b97755ec 100644 --- a/packages/integration/src/azure/config.ts +++ b/packages/integration/src/azure/config.ts @@ -71,7 +71,8 @@ export type AzureIntegrationConfig = { export type AzureDevOpsCredentialKind = | 'PersonalAccessToken' | 'ClientSecret' - | 'ManagedIdentity'; + | 'ManagedIdentity' + | 'ManagedIdentityClientAssertion'; /** * Common fields for the Azure DevOps credentials. @@ -109,6 +110,31 @@ export type AzureClientSecretCredential = AzureCredentialBase & { clientSecret: string; }; +/** + * A client assertion credential that uses a managed identity to generate a client assertion (JWT). + * @public + */ +export type AzureManagedIdentityClientAssertionCredential = + AzureCredentialBase & { + kind: 'ManagedIdentityClientAssertion'; + /** + * The Entra ID tenant + */ + tenantId: string; + + /** + * The client ID of the app registration you want to authenticate as. + */ + clientId: string; + + /** + * The client ID of the managed identity used to generate a client assertion (JWT). + * Set to "system-assigned" to automatically use the system-assigned managed identity. + * For user-assigned managed identities, specify the client ID of the managed identity you want to use. + */ + managedIdentityClientId: 'system-assigned' | string; + }; + /** * A managed identity credential. * @public @@ -118,7 +144,7 @@ export type AzureManagedIdentityCredential = AzureCredentialBase & { /** * The clientId */ - clientId: string; + clientId: 'system-assigned' | string; }; /** @@ -136,6 +162,7 @@ export type PersonalAccessTokenCredential = AzureCredentialBase & { */ export type AzureDevOpsCredentialLike = Omit< Partial & + Partial & Partial & Partial, 'kind' @@ -147,12 +174,14 @@ export type AzureDevOpsCredentialLike = Omit< */ export type AzureDevOpsCredential = | AzureClientSecretCredential + | AzureManagedIdentityClientAssertionCredential | AzureManagedIdentityCredential | PersonalAccessTokenCredential; const AzureDevOpsCredentialFields = [ 'clientId', 'clientSecret', + 'managedIdentityClientId', 'tenantId', 'personalAccessToken', ] as const; @@ -164,6 +193,10 @@ const AzureDevopsCredentialFieldMap = new Map< >([ ['ClientSecret', ['clientId', 'clientSecret', 'tenantId']], ['ManagedIdentity', ['clientId']], + [ + 'ManagedIdentityClientAssertion', + ['clientId', 'managedIdentityClientId', 'tenantId'], + ], ['PersonalAccessToken', ['personalAccessToken']], ]); @@ -213,9 +246,12 @@ export function readAzureIntegrationConfig( personalAccessToken: credential .getOptionalString('personalAccessToken') ?.trim(), - tenantId: credential.getOptionalString('tenantId'), - clientId: credential.getOptionalString('clientId'), + tenantId: credential.getOptionalString('tenantId')?.trim(), + clientId: credential.getOptionalString('clientId')?.trim(), clientSecret: credential.getOptionalString('clientSecret')?.trim(), + managedIdentityClientId: credential + .getOptionalString('managedIdentityClientId') + ?.trim(), }; return result; diff --git a/packages/integration/src/azure/index.ts b/packages/integration/src/azure/index.ts index b5f5c0a316..a447c8ffd8 100644 --- a/packages/integration/src/azure/index.ts +++ b/packages/integration/src/azure/index.ts @@ -25,6 +25,7 @@ export type { AzureCredentialBase, AzureClientSecretCredential, AzureManagedIdentityCredential, + AzureManagedIdentityClientAssertionCredential, PersonalAccessTokenCredential, AzureDevOpsCredentialLike, AzureDevOpsCredential, From b7e3e383723ce61a70126d7211fa1b0c4fd8dc53 Mon Sep 17 00:00:00 2001 From: Ambrish R Date: Wed, 2 Apr 2025 12:46:32 +0530 Subject: [PATCH 003/143] Update add-auth-provider.md Signed-off-by: Ambrish R --- docs/auth/add-auth-provider.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md index 8f04f71a39..cf27403bab 100644 --- a/docs/auth/add-auth-provider.md +++ b/docs/auth/add-auth-provider.md @@ -121,11 +121,9 @@ due to its comprehensive set of supported authentication ### Quick guide -[1.](#create-new-auth-provider-module) Create a new auth provider module +[1.](#create-new-auth-provider-module) Create a new auth provider module or [add a proxy auth based provider](#creating-proxy-auth-based-provider) depending on your needs. -[2.](#adding-an-oauth-based-provider) or [adding a proxy auth based provider](#creating-proxy-auth-based-provider) depending on your needs. - -[3.](#add-the-provider-to-the-backend) Add the provider to the backend. +[2.](#add-the-provider-to-the-backend) Add the provider to the backend. ### Create new auth provider module From 16eb4bf98fdb80f87235ae8495638e51845af54a Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Tue, 8 Apr 2025 12:30:40 -0700 Subject: [PATCH 004/143] export contentModal and make docsLinkTitle Signed-off-by: Reyna Nikolayev --- .changeset/honest-teams-shave.md | 8 +++++ plugins/home-react/report.api.md | 27 ++++++++++++++ .../src/components}/ContentModal.tsx | 33 +++++++++++++++-- plugins/home-react/src/components/index.ts | 4 +++ plugins/home-react/src/index.ts | 1 + .../home-react/src/overridableComponents.ts | 36 +++++++++++++++++++ plugins/home/report.api.md | 2 +- .../homePageComponents/QuickStart/Content.tsx | 4 +-- .../QuickStart/QuickStart.stories.tsx | 28 +++++++++++++++ 9 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 .changeset/honest-teams-shave.md rename plugins/{home/src/homePageComponents/QuickStart => home-react/src/components}/ContentModal.tsx (69%) create mode 100644 plugins/home-react/src/overridableComponents.ts diff --git a/.changeset/honest-teams-shave.md b/.changeset/honest-teams-shave.md new file mode 100644 index 0000000000..c779f20c8f --- /dev/null +++ b/.changeset/honest-teams-shave.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-home-react': patch +'@backstage/plugin-home': patch +--- + +Export ContentModal from @backstage/plugin-home-react so people can use this in other scenarios. + +Make QuickStartCard docsLinkTitle prop more flexible to allow for any React.JSX.Element instead of just a string diff --git a/plugins/home-react/report.api.md b/plugins/home-react/report.api.md index c7e847fb36..c5a90553a9 100644 --- a/plugins/home-react/report.api.md +++ b/plugins/home-react/report.api.md @@ -5,9 +5,22 @@ ```ts import { Extension } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react/jsx-runtime'; +import { JSX as JSX_3 } from 'react'; +import { Overrides } from '@material-ui/core/styles/overrides'; import { RJSFSchema } from '@rjsf/utils'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; import { UiSchema } from '@rjsf/utils'; +// @public (undocumented) +export type BackstageContentModalClassKey = 'contentModal' | 'linkText'; + +// @public (undocumented) +export type BackstageOverrides = Overrides & { + [Name in keyof CatalogReactComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; + // @public (undocumented) export type CardConfig = { layout?: CardLayout; @@ -39,6 +52,11 @@ export type CardSettings = { uiSchema?: UiSchema; }; +// @public (undocumented) +export type CatalogReactComponentsNameToClassKey = { + BackstageContentModal: BackstageContentModalClassKey; +}; + // @public (undocumented) export type ComponentParts = { Content: (props?: any) => JSX.Element; @@ -52,6 +70,15 @@ export type ComponentRenderer = { Renderer?: (props: RendererProps) => JSX.Element; }; +// @public +export const ContentModal: (props: ContentModalProps) => JSX_2.Element; + +// @public +export type ContentModalProps = { + modalContent: JSX_3.Element; + linkContent: string | JSX_3.Element; +}; + // @public export function createCardExtension(options: { title?: string; diff --git a/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx b/plugins/home-react/src/components/ContentModal.tsx similarity index 69% rename from plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx rename to plugins/home-react/src/components/ContentModal.tsx index ff917f367c..7dfb746390 100644 --- a/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx +++ b/plugins/home-react/src/components/ContentModal.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,43 @@ import { JSX, useState } from 'react'; import { Link } from '@backstage/core-components'; import Modal from '@material-ui/core/Modal'; import Box from '@material-ui/core/Box'; +import { makeStyles, Theme } from '@material-ui/core/styles'; -import { useStyles } from './styles'; +/** @public */ +export type BackstageContentModalClassKey = 'contentModal' | 'linkText'; +export const useStyles = makeStyles( + (theme: Theme) => ({ + contentModal: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + height: 'auto', + }, + linkText: { + marginBottom: theme.spacing(1.5), + }, + }), + { name: 'BackstageContentModal' }, +); + +/** + * Props customizing the component. + * + * @public + */ export type ContentModalProps = { modalContent: JSX.Element; linkContent: string | JSX.Element; }; +/** + * A component to expand given content into a full screen modal. + * + * @public + */ export const ContentModal = (props: ContentModalProps) => { const { modalContent, linkContent } = props; const styles = useStyles(); diff --git a/plugins/home-react/src/components/index.ts b/plugins/home-react/src/components/index.ts index dce6968b36..9271da0e48 100644 --- a/plugins/home-react/src/components/index.ts +++ b/plugins/home-react/src/components/index.ts @@ -15,3 +15,7 @@ */ export { SettingsModal } from './SettingsModal'; +export { ContentModal } from './ContentModal'; + +export type { BackstageContentModalClassKey } from './ContentModal'; +export type { ContentModalProps } from './ContentModal'; diff --git a/plugins/home-react/src/index.ts b/plugins/home-react/src/index.ts index 1f02ded1c6..54602dc814 100644 --- a/plugins/home-react/src/index.ts +++ b/plugins/home-react/src/index.ts @@ -30,3 +30,4 @@ export type { CardSettings, CardConfig, } from './extensions'; +export * from './overridableComponents'; diff --git a/plugins/home-react/src/overridableComponents.ts b/plugins/home-react/src/overridableComponents.ts new file mode 100644 index 0000000000..8c5dff4465 --- /dev/null +++ b/plugins/home-react/src/overridableComponents.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Overrides } from '@material-ui/core/styles/overrides'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; +import { BackstageContentModalClassKey } from './'; + +/** @public */ +export type CatalogReactComponentsNameToClassKey = { + BackstageContentModal: BackstageContentModalClassKey; +}; + +/** @public */ +export type BackstageOverrides = Overrides & { + [Name in keyof CatalogReactComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; + +declare module '@backstage/theme' { + interface OverrideComponentNameToClassKeys + extends CatalogReactComponentsNameToClassKey {} +} diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 7c7f55fd47..0bfa6230e7 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -194,7 +194,7 @@ export const QuickStartCard: ( // @public export type QuickStartCardProps = { modalTitle?: string | JSX_3.Element; - docsLinkTitle?: string; + docsLinkTitle?: string | React.JSX.Element; docsLink?: string; video?: JSX_3.Element; image: JSX_3.Element; diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx index 829b9ed191..3cb92f7178 100644 --- a/plugins/home/src/homePageComponents/QuickStart/Content.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -18,7 +18,7 @@ import { JSX } from 'react'; import { Link } from '@backstage/core-components'; import Typography from '@material-ui/core/Typography'; import Grid from '@material-ui/core/Grid'; -import { ContentModal } from './ContentModal'; +import { ContentModal } from '@backstage/plugin-home-react'; import { useStyles } from './styles'; /** @@ -30,7 +30,7 @@ export type QuickStartCardProps = { /** The modal link title */ modalTitle?: string | JSX.Element; /** The link to docs title */ - docsLinkTitle?: string; + docsLinkTitle?: string | JSX.Element; /** The link to docs */ docsLink?: string; /** The video to play on the card */ diff --git a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx index 18375c9c27..acc7c5d15e 100644 --- a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx @@ -18,6 +18,7 @@ import { QuickStartCard } from '../../plugin'; import { ComponentType, PropsWithChildren } from 'react'; import { wrapInTestApp } from '@backstage/test-utils'; import Grid from '@material-ui/core/Grid'; +import OpenInNewIcon from '@material-ui/icons/OpenInNew'; import ContentImage from './static/backstageSystemModel.png'; export default { @@ -65,3 +66,30 @@ export const Customized = () => { ); }; + +export const CustomDocLink = () => { + return ( + + + + Learn more with getting started docs + + } + docsLink="https://backstage.io/docs/getting-started" + image={ + quick start + } + cardDescription="Backstage system model will help you create new entities" + /> + + ); +}; From 95af6f3d198b059b099bf460f99ca20251e01b81 Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Tue, 8 Apr 2025 12:56:00 -0700 Subject: [PATCH 005/143] fix api report Signed-off-by: Reyna Nikolayev --- plugins/home/report.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 0bfa6230e7..37630e2e11 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -194,7 +194,7 @@ export const QuickStartCard: ( // @public export type QuickStartCardProps = { modalTitle?: string | JSX_3.Element; - docsLinkTitle?: string | React.JSX.Element; + docsLinkTitle?: string | JSX_3.Element; docsLink?: string; video?: JSX_3.Element; image: JSX_3.Element; From 00e0941e7436f4adc0b114515d982fad40311afc Mon Sep 17 00:00:00 2001 From: Ben McNicholl Date: Sat, 12 Apr 2025 21:09:20 +1000 Subject: [PATCH 006/143] chore: add official buildkite plugin Signed-off-by: Ben McNicholl --- microsite/data/plugins/buildkite.yaml | 14 +++++++------- microsite/static/img/buildkite.svg | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 microsite/static/img/buildkite.svg diff --git a/microsite/data/plugins/buildkite.yaml b/microsite/data/plugins/buildkite.yaml index 5713b6b9e4..78daf1dcc4 100644 --- a/microsite/data/plugins/buildkite.yaml +++ b/microsite/data/plugins/buildkite.yaml @@ -1,13 +1,13 @@ --- title: Buildkite -author: roadie.io -authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=buildkite +author: Buildkite +authorUrl: https://buildkite.com category: CI/CD -description: View Buildkite CI builds for your service in Backstage. -documentation: https://roadie.io/backstage/plugins/buildkite/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=buildkite -iconUrl: https://roadie.io/images/logos/buildkite.png -npmPackageName: '@roadiehq/backstage-plugin-buildkite' +description: View Buildkite CI builds from within Backstage +documentation: https://github.com/buildkite/backstage-plugin +iconUrl: /img/buildkite.svg +npmPackageName: '@buildkite/plugin-buildkite' tags: - ci - cd -addedDate: '2021-04-20' +addedDate: '2025-04-12' diff --git a/microsite/static/img/buildkite.svg b/microsite/static/img/buildkite.svg new file mode 100644 index 0000000000..cc6bb28961 --- /dev/null +++ b/microsite/static/img/buildkite.svg @@ -0,0 +1 @@ + From ba65404cdf14bc50a475c502cfaea04860abbe30 Mon Sep 17 00:00:00 2001 From: Ben McNicholl Date: Sat, 12 Apr 2025 22:19:28 +1000 Subject: [PATCH 007/143] chore: remove tags for linter Signed-off-by: Ben McNicholl --- microsite/data/plugins/buildkite.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/microsite/data/plugins/buildkite.yaml b/microsite/data/plugins/buildkite.yaml index 78daf1dcc4..0bb57f1df6 100644 --- a/microsite/data/plugins/buildkite.yaml +++ b/microsite/data/plugins/buildkite.yaml @@ -7,7 +7,4 @@ description: View Buildkite CI builds from within Backstage documentation: https://github.com/buildkite/backstage-plugin iconUrl: /img/buildkite.svg npmPackageName: '@buildkite/plugin-buildkite' -tags: - - ci - - cd addedDate: '2025-04-12' From eee94f3232b621bddae3bc8b98fd423d62dc38b8 Mon Sep 17 00:00:00 2001 From: Ben McNicholl Date: Sat, 12 Apr 2025 22:37:42 +1000 Subject: [PATCH 008/143] chore: remove whitespace Signed-off-by: Ben McNicholl --- microsite/data/plugins/buildkite.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/buildkite.yaml b/microsite/data/plugins/buildkite.yaml index 0bb57f1df6..ba199a5d02 100644 --- a/microsite/data/plugins/buildkite.yaml +++ b/microsite/data/plugins/buildkite.yaml @@ -1,7 +1,7 @@ --- title: Buildkite author: Buildkite -authorUrl: https://buildkite.com +authorUrl: https://buildkite.com category: CI/CD description: View Buildkite CI builds from within Backstage documentation: https://github.com/buildkite/backstage-plugin From 2f3623ed199ba365e6a2880e3515aa5f6da099ef Mon Sep 17 00:00:00 2001 From: Ben McNicholl Date: Thu, 17 Apr 2025 15:56:27 +1000 Subject: [PATCH 009/143] chore: rename package Signed-off-by: Ben McNicholl --- microsite/data/plugins/buildkite.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/buildkite.yaml b/microsite/data/plugins/buildkite.yaml index ba199a5d02..48754f6ae6 100644 --- a/microsite/data/plugins/buildkite.yaml +++ b/microsite/data/plugins/buildkite.yaml @@ -6,5 +6,5 @@ category: CI/CD description: View Buildkite CI builds from within Backstage documentation: https://github.com/buildkite/backstage-plugin iconUrl: /img/buildkite.svg -npmPackageName: '@buildkite/plugin-buildkite' +npmPackageName: '@buildkite/backstage-plugin-buildkite' addedDate: '2025-04-12' From 623f3c6df5422db0d30936798a42b2a73efdc49f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 07:56:52 +0000 Subject: [PATCH 010/143] build(deps): bump http-proxy-middleware in /microsite Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.7 to 2.0.9. - [Release notes](https://github.com/chimurai/http-proxy-middleware/releases) - [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.9/CHANGELOG.md) - [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.7...v2.0.9) --- updated-dependencies: - dependency-name: http-proxy-middleware dependency-version: 2.0.9 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- microsite/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 618b716f4d..d048b5a74e 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -7749,8 +7749,8 @@ __metadata: linkType: hard "http-proxy-middleware@npm:^2.0.3": - version: 2.0.7 - resolution: "http-proxy-middleware@npm:2.0.7" + version: 2.0.9 + resolution: "http-proxy-middleware@npm:2.0.9" dependencies: "@types/http-proxy": "npm:^1.17.8" http-proxy: "npm:^1.18.1" @@ -7762,7 +7762,7 @@ __metadata: peerDependenciesMeta: "@types/express": optional: true - checksum: 10/4a51bf612b752ad945701995c1c029e9501c97e7224c0cf3f8bf6d48d172d6a8f2b57c20fec469534fdcac3aa8a6f332224a33c6b0d7f387aa2cfff9b67216fd + checksum: 10/4ece416a91d52e96f8136c5f4abfbf7ac2f39becbad21fa8b158a12d7e7d8f808287ff1ae342b903fd1f15f2249dee87fabc09e1f0e73106b83331c496d67660 languageName: node linkType: hard From b9b3b3520deae9766c5fb64daeaeb12423673075 Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Fri, 18 Apr 2025 15:47:18 -0700 Subject: [PATCH 011/143] update video prop name Signed-off-by: Reyna Nikolayev --- .changeset/honest-teams-shave.md | 4 +++- plugins/home/report.api.md | 2 +- .../home/src/homePageComponents/QuickStart/Content.tsx | 6 +++--- .../homePageComponents/QuickStart/QuickStart.stories.tsx | 7 +++++++ plugins/home/src/homePageComponents/QuickStart/styles.ts | 9 +-------- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.changeset/honest-teams-shave.md b/.changeset/honest-teams-shave.md index c779f20c8f..f4c62b348f 100644 --- a/.changeset/honest-teams-shave.md +++ b/.changeset/honest-teams-shave.md @@ -5,4 +5,6 @@ Export ContentModal from @backstage/plugin-home-react so people can use this in other scenarios. -Make QuickStartCard docsLinkTitle prop more flexible to allow for any React.JSX.Element instead of just a string +Make QuickStartCard docsLinkTitle prop more flexible to allow for any React.JSX.Element instead of just a string. +Update QuickStartCard prop name from video to additionalContent. +Remove unused styles. diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 37630e2e11..15c12e2c7d 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -196,7 +196,7 @@ export type QuickStartCardProps = { modalTitle?: string | JSX_3.Element; docsLinkTitle?: string | JSX_3.Element; docsLink?: string; - video?: JSX_3.Element; + additionalContent?: JSX_3.Element; image: JSX_3.Element; cardDescription?: string; downloadImage?: JSX_3.Element; diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx index 3cb92f7178..61752e3fad 100644 --- a/plugins/home/src/homePageComponents/QuickStart/Content.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -33,8 +33,8 @@ export type QuickStartCardProps = { docsLinkTitle?: string | JSX.Element; /** The link to docs */ docsLink?: string; - /** The video to play on the card */ - video?: JSX.Element; + /** Additional card content */ + additionalContent?: JSX.Element; /** A quickstart image to display on the card */ image: JSX.Element; /** The card description*/ @@ -78,7 +78,7 @@ export const Content = (props: QuickStartCardProps): JSX.Element => { - {props.video && props.video} + {props.additionalContent && props.additionalContent} ); }; diff --git a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx index acc7c5d15e..c0963b88a1 100644 --- a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx @@ -62,6 +62,13 @@ export const Customized = () => { /> } cardDescription="Backstage system model will help you create new entities" + additionalContent={ +

+ This is a custom description for the Quick Start card. It can be + used to provide additional information or context about the Quick + Start process. +

+ } /> ); diff --git a/plugins/home/src/homePageComponents/QuickStart/styles.ts b/plugins/home/src/homePageComponents/QuickStart/styles.ts index f6f93f7070..8cc8c291c4 100644 --- a/plugins/home/src/homePageComponents/QuickStart/styles.ts +++ b/plugins/home/src/homePageComponents/QuickStart/styles.ts @@ -23,8 +23,7 @@ export type QuickStartCardClassKey = | 'contentModal' | 'imageSize' | 'link' - | 'linkText' - | 'videoContainer'; + | 'linkText'; export const useStyles = makeStyles( (theme: Theme) => ({ @@ -57,12 +56,6 @@ export const useStyles = makeStyles( linkText: { marginBottom: theme.spacing(1.5), }, - videoContainer: { - borderRadius: '10px', - width: '100%', - height: 'auto', - background: `${theme.palette.background.default}`, - }, }), { name: 'HomeQuickStartCard' }, ); From 61f2aac5e448fe998916fae254b6a57a12e4eeb7 Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Mon, 21 Apr 2025 09:28:36 -0700 Subject: [PATCH 012/143] review suggestions Signed-off-by: Reyna Nikolayev --- .changeset/honest-teams-shave.md | 6 +++--- plugins/home-react/report.api.md | 8 ++++---- plugins/home-react/src/components/ContentModal.tsx | 6 +++--- plugins/home-react/src/components/index.ts | 2 +- plugins/home-react/src/overridableComponents.ts | 4 ++-- plugins/home/report.api.md | 1 + .../home/src/homePageComponents/QuickStart/Content.tsx | 3 +++ 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.changeset/honest-teams-shave.md b/.changeset/honest-teams-shave.md index f4c62b348f..cf5c4b9987 100644 --- a/.changeset/honest-teams-shave.md +++ b/.changeset/honest-teams-shave.md @@ -3,8 +3,8 @@ '@backstage/plugin-home': patch --- -Export ContentModal from @backstage/plugin-home-react so people can use this in other scenarios. +Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. -Make QuickStartCard docsLinkTitle prop more flexible to allow for any React.JSX.Element instead of just a string. -Update QuickStartCard prop name from video to additionalContent. +Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. +Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. Remove unused styles. diff --git a/plugins/home-react/report.api.md b/plugins/home-react/report.api.md index c5a90553a9..ee14be9a3f 100644 --- a/plugins/home-react/report.api.md +++ b/plugins/home-react/report.api.md @@ -11,9 +11,6 @@ import { RJSFSchema } from '@rjsf/utils'; import { StyleRules } from '@material-ui/core/styles/withStyles'; import { UiSchema } from '@rjsf/utils'; -// @public (undocumented) -export type BackstageContentModalClassKey = 'contentModal' | 'linkText'; - // @public (undocumented) export type BackstageOverrides = Overrides & { [Name in keyof CatalogReactComponentsNameToClassKey]?: Partial< @@ -54,7 +51,7 @@ export type CardSettings = { // @public (undocumented) export type CatalogReactComponentsNameToClassKey = { - BackstageContentModal: BackstageContentModalClassKey; + PluginHomeContentModal: PluginHomeContentModalClassKey; }; // @public (undocumented) @@ -89,6 +86,9 @@ export function createCardExtension(options: { settings?: CardSettings; }): Extension<(props: CardExtensionProps) => JSX_2.Element>; +// @public (undocumented) +export type PluginHomeContentModalClassKey = 'contentModal' | 'linkText'; + // @public (undocumented) export type RendererProps = { title?: string; diff --git a/plugins/home-react/src/components/ContentModal.tsx b/plugins/home-react/src/components/ContentModal.tsx index 7dfb746390..cde317e248 100644 --- a/plugins/home-react/src/components/ContentModal.tsx +++ b/plugins/home-react/src/components/ContentModal.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import Box from '@material-ui/core/Box'; import { makeStyles, Theme } from '@material-ui/core/styles'; /** @public */ -export type BackstageContentModalClassKey = 'contentModal' | 'linkText'; +export type PluginHomeContentModalClassKey = 'contentModal' | 'linkText'; export const useStyles = makeStyles( (theme: Theme) => ({ @@ -37,7 +37,7 @@ export const useStyles = makeStyles( marginBottom: theme.spacing(1.5), }, }), - { name: 'BackstageContentModal' }, + { name: 'PluginHomeContentModal' }, ); /** diff --git a/plugins/home-react/src/components/index.ts b/plugins/home-react/src/components/index.ts index 9271da0e48..8a982075eb 100644 --- a/plugins/home-react/src/components/index.ts +++ b/plugins/home-react/src/components/index.ts @@ -17,5 +17,5 @@ export { SettingsModal } from './SettingsModal'; export { ContentModal } from './ContentModal'; -export type { BackstageContentModalClassKey } from './ContentModal'; +export type { PluginHomeContentModalClassKey } from './ContentModal'; export type { ContentModalProps } from './ContentModal'; diff --git a/plugins/home-react/src/overridableComponents.ts b/plugins/home-react/src/overridableComponents.ts index 8c5dff4465..e9ee530de0 100644 --- a/plugins/home-react/src/overridableComponents.ts +++ b/plugins/home-react/src/overridableComponents.ts @@ -16,11 +16,11 @@ import { Overrides } from '@material-ui/core/styles/overrides'; import { StyleRules } from '@material-ui/core/styles/withStyles'; -import { BackstageContentModalClassKey } from './'; +import { PluginHomeContentModalClassKey } from './'; /** @public */ export type CatalogReactComponentsNameToClassKey = { - BackstageContentModal: BackstageContentModalClassKey; + PluginHomeContentModal: PluginHomeContentModalClassKey; }; /** @public */ diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 15c12e2c7d..f15ffde38d 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -196,6 +196,7 @@ export type QuickStartCardProps = { modalTitle?: string | JSX_3.Element; docsLinkTitle?: string | JSX_3.Element; docsLink?: string; + video?: JSX_3.Element; additionalContent?: JSX_3.Element; image: JSX_3.Element; cardDescription?: string; diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx index 61752e3fad..2047a158a6 100644 --- a/plugins/home/src/homePageComponents/QuickStart/Content.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -33,6 +33,8 @@ export type QuickStartCardProps = { docsLinkTitle?: string | JSX.Element; /** The link to docs */ docsLink?: string; + /** The video to play on the card */ + video?: JSX.Element; /** Additional card content */ additionalContent?: JSX.Element; /** A quickstart image to display on the card */ @@ -78,6 +80,7 @@ export const Content = (props: QuickStartCardProps): JSX.Element => { + {props.video && props.video} {props.additionalContent && props.additionalContent} ); From d710d746c584d71ac1131cd037c8fb71542ba0c4 Mon Sep 17 00:00:00 2001 From: Gabriel Dugny Date: Tue, 22 Apr 2025 17:49:43 +0200 Subject: [PATCH 013/143] docs(home): Wrong default for preventCollision since #28397 Signed-off-by: Gabriel Dugny --- .changeset/tidy-paths-count.md | 5 +++++ plugins/home/src/components/CustomHomepage/types.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/tidy-paths-count.md diff --git a/.changeset/tidy-paths-count.md b/.changeset/tidy-paths-count.md new file mode 100644 index 0000000000..190df58043 --- /dev/null +++ b/.changeset/tidy-paths-count.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +docs: Update default for `preventCollision` prop diff --git a/plugins/home/src/components/CustomHomepage/types.ts b/plugins/home/src/components/CustomHomepage/types.ts index 6bbcb759d3..49eb443c6d 100644 --- a/plugins/home/src/components/CustomHomepage/types.ts +++ b/plugins/home/src/components/CustomHomepage/types.ts @@ -95,7 +95,7 @@ export type CustomHomepageGridProps = { allowOverlap?: boolean; /** * Controls if widgets can collide with each other. If true, grid items won't change position when being dragged over. - * @defaultValue false + * @defaultValue true */ preventCollision?: boolean; }; From 2f550c37cc801545150f3ca2346ae8c3344b946f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 07:05:33 +0000 Subject: [PATCH 014/143] chore(deps): update dependency eslint-plugin-storybook to ^0.12.0 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- storybook/package.json | 2 +- storybook/yarn.lock | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/storybook/package.json b/storybook/package.json index 58cce5e57e..c122639045 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -34,7 +34,7 @@ "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "eslint": "^9.11.1", - "eslint-plugin-storybook": "^0.11.0", + "eslint-plugin-storybook": "^0.12.0", "globals": "^15.9.0", "react-router-dom": "^6.3.0", "storybook": "^8.3.5", diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 6f2d88d134..7bf985d1bc 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2036,7 +2036,7 @@ __metadata: "@typescript-eslint/eslint-plugin": "npm:^5.0.0" "@typescript-eslint/parser": "npm:^5.0.0" eslint: "npm:^9.11.1" - eslint-plugin-storybook: "npm:^0.11.0" + eslint-plugin-storybook: "npm:^0.12.0" globals: "npm:^15.9.0" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" @@ -2675,17 +2675,16 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-storybook@npm:^0.11.0": - version: 0.11.4 - resolution: "eslint-plugin-storybook@npm:0.11.4" +"eslint-plugin-storybook@npm:^0.12.0": + version: 0.12.0 + resolution: "eslint-plugin-storybook@npm:0.12.0" dependencies: "@storybook/csf": "npm:^0.1.11" "@typescript-eslint/utils": "npm:^8.8.1" ts-dedent: "npm:^2.2.0" peerDependencies: eslint: ">=8" - typescript: ">=4.8.4 <5.8.0" - checksum: 10/f0fbeef2686e399861db644fd3ffa2759ea50e99a84dc25cf43ff6dd12ac8d12d34b90722e56139a43b58f65a4ea69c36d6919c5224943998a902d2b1d5d13cc + checksum: 10/278ea59565e30b74ee1d57f0a8f704906eaf40973b13999ec2c44872bb90c7505dfb12777b264940e2b480e81ace85c0532af69666e76a783b8ffa898a1d49ad languageName: node linkType: hard From b883f85f1377d23e330365c440abcda1e249a351 Mon Sep 17 00:00:00 2001 From: Tim Klever Date: Mon, 7 Apr 2025 18:51:17 -0700 Subject: [PATCH 015/143] feat: expand the configuration options for release manifests Ultimately, this paves the way for more configuration options with cli bump command when working in environments that are closed / air-gapped from the public internet. Signed-off-by: Tim Klever --- .../release-manifests/src/manifest.test.ts | 180 ++++++++++++++++++ packages/release-manifests/src/manifest.ts | 36 ++-- 2 files changed, 205 insertions(+), 11 deletions(-) diff --git a/packages/release-manifests/src/manifest.test.ts b/packages/release-manifests/src/manifest.test.ts index ad5bf13496..9cb100376a 100644 --- a/packages/release-manifests/src/manifest.test.ts +++ b/packages/release-manifests/src/manifest.test.ts @@ -86,6 +86,71 @@ describe('Release Manifests', () => { getManifestByVersion({ version: '0.0.0', fetch: mockFetch }), ).rejects.toThrow('No release found for 0.0.0 version'); }); + + it('should allow overriding the versions host', async () => { + const mockFetch = jest.fn().mockImplementation(async url => ({ + status: 200, + url, + json: () => ({ + packages: [{ name: '@backstage/core', version: '2.3.4' }], + }), + })); + + const pkgs = await getManifestByVersion({ + version: '0.0.0', + fetch: mockFetch, + versionsBaseUrl: 'https://versions.some-test-host.com', + }); + + expect(pkgs.packages).toEqual([ + { + name: '@backstage/core', + version: '2.3.4', + }, + ]); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://versions.some-test-host.com/v1/releases/0.0.0/manifest.json', + expect.anything(), + ); + }); + + it('should allow overriding github host', async () => { + const mockFetch = jest.fn().mockImplementation(async url => { + if ( + url === + 'https://versions.some-test-host.com/v1/releases/0.0.0/manifest.json' + ) { + return { + status: 200, + url, + json: () => ({ + packages: [{ name: '@backstage/core', version: '2.3.4' }], + }), + }; + } + + throw new Error('Host not found'); + }); + + const pkgs = await getManifestByVersion({ + version: '0.0.0', + fetch: mockFetch, + gitHubRawBaseUrl: 'https://versions.some-test-host.com', + }); + + expect(pkgs.packages).toEqual([ + { + name: '@backstage/core', + version: '2.3.4', + }, + ]); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://versions.some-test-host.com/v1/releases/0.0.0/manifest.json', + expect.anything(), + ); + }); }); describe('getManifestByReleaseLine', () => { @@ -119,6 +184,121 @@ describe('Release Manifests', () => { getManifestByReleaseLine({ releaseLine: 'foo' }), ).rejects.toThrow("No 'foo' release line found"); }); + + it('should allow overriding the fetch implementation', async () => { + const mockFetch = jest.fn().mockImplementation(async url => ({ + status: 200, + url, + json: () => ({ + packages: [{ name: '@backstage/core', version: '1.2.3' }], + }), + })); + + const pkgs = await getManifestByReleaseLine({ + releaseLine: 'main', + fetch: mockFetch, + }); + + expect(pkgs.packages).toEqual([ + { + name: '@backstage/core', + version: '1.2.3', + }, + ]); + + mockFetch.mockImplementation(async url => ({ + status: 404, + url, + })); + + await expect( + getManifestByReleaseLine({ releaseLine: 'foo', fetch: mockFetch }), + ).rejects.toThrow("No 'foo' release line found"); + }); + + it('should allow overriding the versions host', async () => { + const mockFetch = jest.fn().mockImplementation(async url => ({ + status: 200, + url, + json: () => ({ + packages: [{ name: '@backstage/core', version: '1.2.3' }], + }), + })); + + const pkgs = await getManifestByReleaseLine({ + releaseLine: 'main', + fetch: mockFetch, + versionsBaseUrl: 'https://versions.some-test-host.com', + }); + + expect(pkgs.packages).toEqual([ + { + name: '@backstage/core', + version: '1.2.3', + }, + ]); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://versions.some-test-host.com/v1/tags/main/manifest.json', + expect.anything(), + ); + }); + + it('should allow overriding github host', async () => { + const mockFetch = jest.fn().mockImplementation(async url => { + if ( + url === + 'https://hosted.raw.internal-github.com/backstage/versions/main/v1/tags/main' + ) { + return { + ok: true, + status: 200, + url, + text: () => + 'https://hosted.raw.internal-github.com/backstage/versions/tags/main', + }; + } + + if ( + url === + 'https://hosted.raw.internal-github.com/backstage/versions/tags/main/manifest.json' + ) { + return { + status: 200, + url, + json: () => ({ + packages: [{ name: '@backstage/core', version: '1.2.3' }], + }), + }; + } + + throw new Error('Host Not Found'); + }); + + const pkgs = await getManifestByReleaseLine({ + releaseLine: 'main', + fetch: mockFetch, + gitHubRawBaseUrl: + 'https://hosted.raw.internal-github.com/backstage/versions/main', + }); + + expect(pkgs.packages).toEqual([ + { + name: '@backstage/core', + version: '1.2.3', + }, + ]); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://hosted.raw.internal-github.com/backstage/versions/main/v1/tags/main', + expect.anything(), + ); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://hosted.raw.internal-github.com/backstage/versions/tags/main/manifest.json', + expect.anything(), + ); + }); }); }); diff --git a/packages/release-manifests/src/manifest.ts b/packages/release-manifests/src/manifest.ts index 66a5f62151..8db9d59d39 100644 --- a/packages/release-manifests/src/manifest.ts +++ b/packages/release-manifests/src/manifest.ts @@ -37,6 +37,8 @@ export type GetManifestByVersionOptions = { url: string, options?: { signal?: AbortSignal }, ) => Promise>; + gitHubRawBaseUrl?: string; + versionsBaseUrl?: string; }; // Wait for waitMs, or until signal is aborted. @@ -88,19 +90,18 @@ export async function getManifestByVersion( const versionEnc = encodeURIComponent(options.version); const fetchFn = options.fetch ?? fetch; + const versionsHost = options.versionsBaseUrl ?? VERSIONS_BASE_URL; + const gitHubRawBaseUrl = options.gitHubRawBaseUrl ?? GITHUB_RAW_BASE_URL; const res = await withFallback( signal => - fetchFn(`${VERSIONS_BASE_URL}/v1/releases/${versionEnc}/manifest.json`, { + fetchFn(`${versionsHost}/v1/releases/${versionEnc}/manifest.json`, { signal, }), signal => - fetchFn( - `${GITHUB_RAW_BASE_URL}/v1/releases/${versionEnc}/manifest.json`, - { - signal, - }, - ), + fetchFn(`${gitHubRawBaseUrl}/v1/releases/${versionEnc}/manifest.json`, { + signal, + }), 500, ); if (res.status === 404) { @@ -120,6 +121,12 @@ export async function getManifestByVersion( */ export type GetManifestByReleaseLineOptions = { releaseLine: string; + fetch?: ( + url: string, + options?: { signal?: AbortSignal }, + ) => Promise>; + gitHubRawBaseUrl?: string; + versionsBaseUrl?: string; }; /** @@ -130,20 +137,27 @@ export async function getManifestByReleaseLine( options: GetManifestByReleaseLineOptions, ): Promise { const releaseEnc = encodeURIComponent(options.releaseLine); + + const fetchFn = options.fetch ?? fetch; + const versionsHost = options.versionsBaseUrl ?? VERSIONS_BASE_URL; + const gitHubRawBaseUrl = options.gitHubRawBaseUrl ?? GITHUB_RAW_BASE_URL; + const res = await withFallback( signal => - fetch(`${VERSIONS_BASE_URL}/v1/tags/${releaseEnc}/manifest.json`, { + fetchFn(`${versionsHost}/v1/tags/${releaseEnc}/manifest.json`, { signal, }), async signal => { // The release tags are symlinks, which we need to follow manually when fetching from GitHub. - const baseUrl = `${GITHUB_RAW_BASE_URL}/v1/tags/${releaseEnc}`; - const linkRes = await fetch(baseUrl, { signal }); + const baseUrl = `${gitHubRawBaseUrl}/v1/tags/${releaseEnc}`; + const linkRes = await fetchFn(baseUrl, { signal }); if (!linkRes.ok) { return linkRes; } const link = (await linkRes.text()).trim(); - return fetch(new URL(`${link}/manifest.json`, baseUrl), { signal }); + return fetchFn(new URL(`${link}/manifest.json`, baseUrl).toString(), { + signal, + }); }, 1000, ); From 163f3dabf1ec568e69e73713bbe415c1aef31c79 Mon Sep 17 00:00:00 2001 From: Tim Klever Date: Mon, 7 Apr 2025 19:14:47 -0700 Subject: [PATCH 016/143] docs: documentation for contribution of change Signed-off-by: Tim Klever --- .changeset/eleven-beans-relax.md | 9 +++++++++ packages/release-manifests/report.api.md | 10 ++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .changeset/eleven-beans-relax.md diff --git a/.changeset/eleven-beans-relax.md b/.changeset/eleven-beans-relax.md new file mode 100644 index 0000000000..fd01394d2d --- /dev/null +++ b/.changeset/eleven-beans-relax.md @@ -0,0 +1,9 @@ +--- +'@backstage/release-manifests': patch +--- + +This expands the configurability of `release-manifests` to pave the road for more configuration options in the `cli`. + +Specifically it allows the specification of mirrored, proxied, or air-gapped hosts when upgrading across releases when +working in restricted or heavily governed development environments (common in large enterprises and government +entities). diff --git a/packages/release-manifests/report.api.md b/packages/release-manifests/report.api.md index 2d2cc00767..5ef8345ec0 100644 --- a/packages/release-manifests/report.api.md +++ b/packages/release-manifests/report.api.md @@ -11,6 +11,14 @@ export function getManifestByReleaseLine( // @public export type GetManifestByReleaseLineOptions = { releaseLine: string; + fetch?: ( + url: string, + options?: { + signal?: AbortSignal; + }, + ) => Promise>; + gitHubRawBaseUrl?: string; + versionsBaseUrl?: string; }; // @public @@ -27,6 +35,8 @@ export type GetManifestByVersionOptions = { signal?: AbortSignal; }, ) => Promise>; + gitHubRawBaseUrl?: string; + versionsBaseUrl?: string; }; // @public From 19f2aa04a8e655cb762200da526e77cc6923dcac Mon Sep 17 00:00:00 2001 From: Musaab Elfaqih Date: Thu, 24 Apr 2025 14:03:09 +0200 Subject: [PATCH 017/143] Add support for filtering the extensions config by what is discovered in the provided features Signed-off-by: Musaab Elfaqih --- .../src/tree/readAppExtensionsConfig.ts | 30 +++++++++++++++++-- .../src/wiring/createSpecializedApp.tsx | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts index cca7064add..e676e1ee41 100644 --- a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts +++ b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts @@ -16,6 +16,7 @@ import { Config } from '@backstage/config'; import { JsonValue } from '@backstage/types'; +import { FrontendFeature } from '../wiring'; export interface ExtensionParameters { id: string; @@ -26,12 +27,34 @@ export interface ExtensionParameters { const knownExtensionParameters = ['attachTo', 'disabled', 'config']; +/** + * Returns a filtered list of extensions based on what is discovered in the + * provided features. + */ +export const filterExtensionsByFeatures = ( + extensions: ExtensionParameters[], + features: FrontendFeature[], +): ExtensionParameters[] => { + // Get a list of all extension IDs discovered in the provided features. + const discoveredExtensionIds = features.flatMap(feature => + ('extensions' in feature && Array.isArray(feature.extensions) + ? feature.extensions + : [] + ).map((extension: { id: string }) => extension.id), + ); + + return extensions.filter(extension => + discoveredExtensionIds.includes(extension.id), + ); +}; + // Since we'll never merge arrays in config the config reader context // isn't too much of a help. Fall back to manual config reading logic // as the Config interface makes it quite hard for us otherwise. /** @internal */ export function readAppExtensionsConfig( rootConfig: Config, + features: FrontendFeature[] = [], ): ExtensionParameters[] { const arr = rootConfig.getOptional('app.extensions'); if (!Array.isArray(arr)) { @@ -43,8 +66,11 @@ export function readAppExtensionsConfig( return []; } - return arr.map((arrayEntry, arrayIndex) => - expandShorthandExtensionParameters(arrayEntry, arrayIndex), + return filterExtensionsByFeatures( + arr.map((arrayEntry, arrayIndex) => + expandShorthandExtensionParameters(arrayEntry, arrayIndex), + ), + features, ); } diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 21fde6547b..29d6b7a0b7 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -219,7 +219,7 @@ export function createSpecializedApp(options?: { builtinExtensions: [ resolveExtensionDefinition(Root, { namespace: 'root' }), ], - parameters: readAppExtensionsConfig(config), + parameters: readAppExtensionsConfig(config, features), forbidden: new Set(['root']), }), ); From 679207e918178e2a51626bbfad4f25772c45ae39 Mon Sep 17 00:00:00 2001 From: Musaab Elfaqih Date: Thu, 24 Apr 2025 17:22:08 +0200 Subject: [PATCH 018/143] Ignore stale extension config errors based on flag Signed-off-by: Musaab Elfaqih --- .../src/tree/readAppExtensionsConfig.ts | 30 ++----------------- .../src/tree/resolveAppNodeSpecs.ts | 4 ++- .../src/wiring/createSpecializedApp.tsx | 5 +++- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts index e676e1ee41..cca7064add 100644 --- a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts +++ b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts @@ -16,7 +16,6 @@ import { Config } from '@backstage/config'; import { JsonValue } from '@backstage/types'; -import { FrontendFeature } from '../wiring'; export interface ExtensionParameters { id: string; @@ -27,34 +26,12 @@ export interface ExtensionParameters { const knownExtensionParameters = ['attachTo', 'disabled', 'config']; -/** - * Returns a filtered list of extensions based on what is discovered in the - * provided features. - */ -export const filterExtensionsByFeatures = ( - extensions: ExtensionParameters[], - features: FrontendFeature[], -): ExtensionParameters[] => { - // Get a list of all extension IDs discovered in the provided features. - const discoveredExtensionIds = features.flatMap(feature => - ('extensions' in feature && Array.isArray(feature.extensions) - ? feature.extensions - : [] - ).map((extension: { id: string }) => extension.id), - ); - - return extensions.filter(extension => - discoveredExtensionIds.includes(extension.id), - ); -}; - // Since we'll never merge arrays in config the config reader context // isn't too much of a help. Fall back to manual config reading logic // as the Config interface makes it quite hard for us otherwise. /** @internal */ export function readAppExtensionsConfig( rootConfig: Config, - features: FrontendFeature[] = [], ): ExtensionParameters[] { const arr = rootConfig.getOptional('app.extensions'); if (!Array.isArray(arr)) { @@ -66,11 +43,8 @@ export function readAppExtensionsConfig( return []; } - return filterExtensionsByFeatures( - arr.map((arrayEntry, arrayIndex) => - expandShorthandExtensionParameters(arrayEntry, arrayIndex), - ), - features, + return arr.map((arrayEntry, arrayIndex) => + expandShorthandExtensionParameters(arrayEntry, arrayIndex), ); } diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index 0abbbb3560..cf28a80b6a 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -33,12 +33,14 @@ export function resolveAppNodeSpecs(options: { builtinExtensions?: Extension[]; parameters?: Array; forbidden?: Set; + ignoreStaleExtensionConfig?: boolean; }): AppNodeSpec[] { const { builtinExtensions = [], parameters = [], forbidden = new Set(), features = [], + ignoreStaleExtensionConfig = false, } = options; const plugins = features.filter(OpaqueFrontendPlugin.isType); @@ -202,7 +204,7 @@ export function resolveAppNodeSpecs(options: { existing.params.disabled = Boolean(overrideParam.disabled); } order.set(extensionId, existing); - } else { + } else if (!ignoreStaleExtensionConfig) { throw new Error(`Extension ${extensionId} does not exist`); } } diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 29d6b7a0b7..011773a1df 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -219,8 +219,11 @@ export function createSpecializedApp(options?: { builtinExtensions: [ resolveExtensionDefinition(Root, { namespace: 'root' }), ], - parameters: readAppExtensionsConfig(config, features), + parameters: readAppExtensionsConfig(config), forbidden: new Set(['root']), + ignoreStaleExtensionConfig: config.getOptionalBoolean( + 'app.ignoreStaleExtensionConfig', + ), }), ); From 86c5c6a72c8ed91fe7a2219084cf1c3e9f0dff26 Mon Sep 17 00:00:00 2001 From: Musaab Elfaqih Date: Thu, 24 Apr 2025 17:35:32 +0200 Subject: [PATCH 019/143] Use local flag instead of static config Signed-off-by: Musaab Elfaqih --- packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts | 6 +++--- .../frontend-app-api/src/wiring/createSpecializedApp.tsx | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index cf28a80b6a..3da68dcb50 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -33,14 +33,14 @@ export function resolveAppNodeSpecs(options: { builtinExtensions?: Extension[]; parameters?: Array; forbidden?: Set; - ignoreStaleExtensionConfig?: boolean; + allowUnknownExtensionConfig?: boolean; }): AppNodeSpec[] { const { builtinExtensions = [], parameters = [], forbidden = new Set(), features = [], - ignoreStaleExtensionConfig = false, + allowUnknownExtensionConfig = false, } = options; const plugins = features.filter(OpaqueFrontendPlugin.isType); @@ -204,7 +204,7 @@ export function resolveAppNodeSpecs(options: { existing.params.disabled = Boolean(overrideParam.disabled); } order.set(extensionId, existing); - } else if (!ignoreStaleExtensionConfig) { + } else if (!allowUnknownExtensionConfig) { throw new Error(`Extension ${extensionId} does not exist`); } } diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 011773a1df..3d356e2a74 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -208,6 +208,7 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; + flags?: Record; }): { apis: ApiHolder; tree: AppTree } { const config = options?.config ?? new ConfigReader({}, 'empty-config'); const features = deduplicateFeatures(options?.features ?? []); @@ -221,9 +222,7 @@ export function createSpecializedApp(options?: { ], parameters: readAppExtensionsConfig(config), forbidden: new Set(['root']), - ignoreStaleExtensionConfig: config.getOptionalBoolean( - 'app.ignoreStaleExtensionConfig', - ), + allowUnknownExtensionConfig: options?.flags?.allowUnknownExtensionConfig, }), ); From 1f044910d3c518ae4de90d2f75f8ff1f278a4d7c Mon Sep 17 00:00:00 2001 From: Musaab Elfaqih Date: Thu, 24 Apr 2025 17:44:53 +0200 Subject: [PATCH 020/143] Clean up + changeset Signed-off-by: Musaab Elfaqih --- .changeset/polite-shoes-allow.md | 5 +++++ packages/frontend-app-api/report.api.md | 6 ++++++ .../frontend-app-api/src/wiring/createSpecializedApp.tsx | 4 ++-- packages/frontend-app-api/src/wiring/types.ts | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 .changeset/polite-shoes-allow.md diff --git a/.changeset/polite-shoes-allow.md b/.changeset/polite-shoes-allow.md new file mode 100644 index 0000000000..d3c5e34d7a --- /dev/null +++ b/.changeset/polite-shoes-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Added the ability to ignore unknown extension config. diff --git a/packages/frontend-app-api/report.api.md b/packages/frontend-app-api/report.api.md index f24d662df4..661da88210 100644 --- a/packages/frontend-app-api/report.api.md +++ b/packages/frontend-app-api/report.api.md @@ -34,6 +34,7 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; + flags?: SpecializedAppFlags; }): { apis: ApiHolder; tree: AppTree; @@ -41,4 +42,9 @@ export function createSpecializedApp(options?: { // @public @deprecated (undocumented) export type FrontendFeature = FrontendFeature_2; + +// @public (undocumented) +export type SpecializedAppFlags = { + allowUnknownExtensionConfig?: boolean; +}; ``` diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 3d356e2a74..e1b7f56227 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -74,7 +74,7 @@ import { ApiRegistry } from '../../../core-app-api/src/apis/system/ApiRegistry'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; import { BackstageRouteObject } from '../routing/types'; -import { FrontendFeature, RouteInfo } from './types'; +import { FrontendFeature, RouteInfo, SpecializedAppFlags } from './types'; import { matchRoutes } from 'react-router-dom'; function deduplicateFeatures( @@ -208,7 +208,7 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; - flags?: Record; + flags?: SpecializedAppFlags; }): { apis: ApiHolder; tree: AppTree } { const config = options?.config ?? new ConfigReader({}, 'empty-config'); const features = deduplicateFeatures(options?.features ?? []); diff --git a/packages/frontend-app-api/src/wiring/types.ts b/packages/frontend-app-api/src/wiring/types.ts index 2bf08f327f..d7af7bd528 100644 --- a/packages/frontend-app-api/src/wiring/types.ts +++ b/packages/frontend-app-api/src/wiring/types.ts @@ -28,3 +28,8 @@ export type RouteInfo = { routeParents: Map; routeObjects: BackstageRouteObject[]; }; + +/** @public */ +export type SpecializedAppFlags = { + allowUnknownExtensionConfig?: boolean; +}; From 1654d7288559b453f4eb2580e3fb83937c67b7df Mon Sep 17 00:00:00 2001 From: Musaab Elfaqih Date: Fri, 25 Apr 2025 14:52:51 +0200 Subject: [PATCH 021/143] Simplify types Signed-off-by: Musaab Elfaqih --- .changeset/polite-shoes-allow.md | 2 +- packages/frontend-app-api/report.api.md | 7 +------ .../frontend-app-api/src/wiring/createSpecializedApp.tsx | 4 ++-- packages/frontend-app-api/src/wiring/types.ts | 5 ----- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.changeset/polite-shoes-allow.md b/.changeset/polite-shoes-allow.md index d3c5e34d7a..b7e06bce6f 100644 --- a/.changeset/polite-shoes-allow.md +++ b/.changeset/polite-shoes-allow.md @@ -2,4 +2,4 @@ '@backstage/frontend-app-api': patch --- -Added the ability to ignore unknown extension config. +Added the ability to ignore unknown extension config by passing `{ flags: { allowUnknownExtensionConfig: true } }` to `createSpecializedApp`. diff --git a/packages/frontend-app-api/report.api.md b/packages/frontend-app-api/report.api.md index 661da88210..91a33d277d 100644 --- a/packages/frontend-app-api/report.api.md +++ b/packages/frontend-app-api/report.api.md @@ -34,7 +34,7 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; - flags?: SpecializedAppFlags; + flags?: Record; }): { apis: ApiHolder; tree: AppTree; @@ -42,9 +42,4 @@ export function createSpecializedApp(options?: { // @public @deprecated (undocumented) export type FrontendFeature = FrontendFeature_2; - -// @public (undocumented) -export type SpecializedAppFlags = { - allowUnknownExtensionConfig?: boolean; -}; ``` diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index e1b7f56227..3d356e2a74 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -74,7 +74,7 @@ import { ApiRegistry } from '../../../core-app-api/src/apis/system/ApiRegistry'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; import { BackstageRouteObject } from '../routing/types'; -import { FrontendFeature, RouteInfo, SpecializedAppFlags } from './types'; +import { FrontendFeature, RouteInfo } from './types'; import { matchRoutes } from 'react-router-dom'; function deduplicateFeatures( @@ -208,7 +208,7 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; - flags?: SpecializedAppFlags; + flags?: Record; }): { apis: ApiHolder; tree: AppTree } { const config = options?.config ?? new ConfigReader({}, 'empty-config'); const features = deduplicateFeatures(options?.features ?? []); diff --git a/packages/frontend-app-api/src/wiring/types.ts b/packages/frontend-app-api/src/wiring/types.ts index d7af7bd528..2bf08f327f 100644 --- a/packages/frontend-app-api/src/wiring/types.ts +++ b/packages/frontend-app-api/src/wiring/types.ts @@ -28,8 +28,3 @@ export type RouteInfo = { routeParents: Map; routeObjects: BackstageRouteObject[]; }; - -/** @public */ -export type SpecializedAppFlags = { - allowUnknownExtensionConfig?: boolean; -}; From d6d4b24e35715d69b2256125f692c1195febaaf6 Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Fri, 25 Apr 2025 11:19:03 -0700 Subject: [PATCH 022/143] remove unnecessary style removal Signed-off-by: Reyna Nikolayev --- .changeset/honest-teams-shave.md | 1 - plugins/home/src/homePageComponents/QuickStart/styles.ts | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.changeset/honest-teams-shave.md b/.changeset/honest-teams-shave.md index cf5c4b9987..931cfd2f63 100644 --- a/.changeset/honest-teams-shave.md +++ b/.changeset/honest-teams-shave.md @@ -7,4 +7,3 @@ Export ContentModal from `@backstage/plugin-home-react` so people can use this i Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. -Remove unused styles. diff --git a/plugins/home/src/homePageComponents/QuickStart/styles.ts b/plugins/home/src/homePageComponents/QuickStart/styles.ts index 8cc8c291c4..f6f93f7070 100644 --- a/plugins/home/src/homePageComponents/QuickStart/styles.ts +++ b/plugins/home/src/homePageComponents/QuickStart/styles.ts @@ -23,7 +23,8 @@ export type QuickStartCardClassKey = | 'contentModal' | 'imageSize' | 'link' - | 'linkText'; + | 'linkText' + | 'videoContainer'; export const useStyles = makeStyles( (theme: Theme) => ({ @@ -56,6 +57,12 @@ export const useStyles = makeStyles( linkText: { marginBottom: theme.spacing(1.5), }, + videoContainer: { + borderRadius: '10px', + width: '100%', + height: 'auto', + background: `${theme.palette.background.default}`, + }, }), { name: 'HomeQuickStartCard' }, ); From e69a79304307fd650dfba1f28bdd5788fb79a40e Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 25 Apr 2025 20:54:39 +0200 Subject: [PATCH 023/143] core-app-api: use PublishSubject in OAuthRequestManager Signed-off-by: Vincenzo Scamporlino --- .../OAuthRequestApi/OAuthRequestManager.test.ts | 6 +++--- .../implementations/OAuthRequestApi/OAuthRequestManager.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.test.ts b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.test.ts index 4dd6af715e..226ca5eb28 100644 --- a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.test.ts +++ b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.test.ts @@ -34,12 +34,12 @@ describe('OAuthRequestManager', () => { expect(reqSpy).toHaveBeenCalledTimes(0); await 'a tick'; - expect(reqSpy).toHaveBeenCalledTimes(2); + expect(reqSpy).toHaveBeenCalledTimes(1); expect(reqSpy).toHaveBeenLastCalledWith([]); const req = requester(new Set(['my-scope'])); - expect(reqSpy).toHaveBeenCalledTimes(3); + expect(reqSpy).toHaveBeenCalledTimes(2); expect(reqSpy).toHaveBeenLastCalledWith([ expect.objectContaining({ reject: expect.any(Function), @@ -51,7 +51,7 @@ describe('OAuthRequestManager', () => { 'not yet', ); - const [request] = reqSpy.mock.calls[2][0]; + const [request] = reqSpy.mock.calls[1][0]; request.trigger(); await expect(req).resolves.toBe('hello'); diff --git a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts index 5d467be7b4..0f7ad0f2c7 100644 --- a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts +++ b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts @@ -22,7 +22,7 @@ import { } from '@backstage/core-plugin-api'; import { Observable } from '@backstage/types'; import { OAuthPendingRequests, PendingRequest } from './OAuthPendingRequests'; -import { BehaviorSubject } from '../../../lib/subjects'; +import { PublishSubject } from '../../../lib/subjects'; /** * The OAuthRequestManager is an implementation of the OAuthRequestApi. @@ -34,7 +34,7 @@ import { BehaviorSubject } from '../../../lib/subjects'; * @public */ export class OAuthRequestManager implements OAuthRequestApi { - private readonly subject = new BehaviorSubject([]); + private readonly subject = new PublishSubject(); private currentRequests: PendingOAuthRequest[] = []; private handlerCount = 0; From cc119b2158e24ed7db6dabd8b27fa8a797f4a58d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 25 Apr 2025 20:54:55 +0200 Subject: [PATCH 024/143] core-app-api: changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/ninety-donkeys-shop.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/ninety-donkeys-shop.md diff --git a/.changeset/ninety-donkeys-shop.md b/.changeset/ninety-donkeys-shop.md new file mode 100644 index 0000000000..53e78afc6a --- /dev/null +++ b/.changeset/ninety-donkeys-shop.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Fixed an issue causing `OAuthRequestDialog` to re-render on mount. From b445cfd9ec22732420413824242ed67145fe483d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 28 Apr 2025 16:37:00 +0200 Subject: [PATCH 025/143] core-app-api: update MockOAuthApi subscribe Signed-off-by: Vincenzo Scamporlino --- .../OAuthRequestApi/MockOAuthApi.ts | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/MockOAuthApi.ts b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/MockOAuthApi.ts index 193c474361..b5261bd1e2 100644 --- a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/MockOAuthApi.ts +++ b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/MockOAuthApi.ts @@ -17,11 +17,19 @@ import { OAuthRequestApi, OAuthRequesterOptions, + PendingOAuthRequest, } from '@backstage/core-plugin-api'; import { OAuthRequestManager } from './OAuthRequestManager'; export default class MockOAuthApi implements OAuthRequestApi { private readonly real = new OAuthRequestManager(); + private requests: PendingOAuthRequest[] = []; + + constructor() { + this.authRequest$().subscribe(requests => { + this.requests = requests; + }); + } createAuthRequester(options: OAuthRequesterOptions) { return this.real.createAuthRequester(options); @@ -34,25 +42,12 @@ export default class MockOAuthApi implements OAuthRequestApi { async triggerAll() { await Promise.resolve(); // Wait a tick to allow new requests to get forwarded - return new Promise(resolve => { - const subscription = this.authRequest$().subscribe(requests => { - subscription.unsubscribe(); - Promise.all(requests.map(request => request.trigger())).then(() => - resolve(), - ); - }); - }); + return Promise.all(this.requests.map(request => request.trigger())); } async rejectAll() { await Promise.resolve(); // Wait a tick to allow new requests to get forwarded - return new Promise(resolve => { - const subscription = this.authRequest$().subscribe(requests => { - subscription.unsubscribe(); - requests.map(request => request.reject()); - resolve(); - }); - }); + this.requests.forEach(request => request.reject()); } } From c30d1a9963c33fb96b388563e4a10d553e1921d1 Mon Sep 17 00:00:00 2001 From: Jessica He Date: Wed, 5 Feb 2025 15:16:00 -0500 Subject: [PATCH 026/143] introduce dangerouslyAllowSignInWithoutUserInCatalog auth resolver config Signed-off-by: Jessica He --- .changeset/twenty-olives-impress.md | 23 +++++++ docs/auth/identity-resolver.md | 38 +++++++++++- .../config.d.ts | 11 +++- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 18 +++++- .../config.d.ts | 6 +- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 28 +++++++-- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 25 ++++++-- .../config.d.ts | 15 ++++- .../package.json | 3 +- .../report.api.md | 10 ++- .../src/resolvers.ts | 47 +++++++++++--- .../config.d.ts | 21 +++++++ .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 24 +++++-- .../config.d.ts | 6 +- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.test.ts | 11 +++- .../src/resolvers.ts | 24 +++++-- .../config.d.ts | 16 ++++- .../package.json | 3 +- .../report.api.md | 10 ++- .../src/resolvers.ts | 47 +++++++++++--- .../config.d.ts | 14 +++-- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 20 +++++- .../config.d.ts | 11 +++- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 20 +++++- .../config.d.ts | 11 +++- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 24 +++++-- .../config.d.ts | 16 ++++- .../package.json | 3 +- .../report.api.md | 10 ++- .../src/resolvers.ts | 47 +++++++++++--- .../config.d.ts | 11 +++- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 20 +++++- .../package.json | 3 +- .../report.api.md | 13 ++++ .../src/index.ts | 1 + .../src/resolvers.ts | 23 +++++-- .../config.d.ts | 10 ++- .../package.json | 3 +- .../report.api.md | 7 ++- .../src/module.ts | 2 - .../config.d.ts | 11 +++- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 24 +++++-- .../config.d.ts | 11 +++- .../package.json | 3 +- .../report.api.md | 5 +- .../src/resolvers.ts | 20 +++++- .../config.d.ts | 6 +- .../resolvers/CatalogAuthResolverContext.ts | 62 +++++++++++++++---- plugins/auth-node/report.api.md | 16 ++++- .../src/sign-in/commonSignInResolvers.ts | 38 +++++++++--- plugins/auth-node/src/types.ts | 14 +++++ yarn.lock | 16 +++++ 72 files changed, 795 insertions(+), 166 deletions(-) create mode 100644 .changeset/twenty-olives-impress.md diff --git a/.changeset/twenty-olives-impress.md b/.changeset/twenty-olives-impress.md new file mode 100644 index 0000000000..9051cf2e67 --- /dev/null +++ b/.changeset/twenty-olives-impress.md @@ -0,0 +1,23 @@ +--- +'@backstage/plugin-auth-backend-module-cloudflare-access-provider': minor +'@backstage/plugin-auth-backend-module-bitbucket-server-provider': minor +'@backstage/plugin-auth-backend-module-azure-easyauth-provider': minor +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': minor +'@backstage/plugin-auth-backend-module-vmware-cloud-provider': minor +'@backstage/plugin-auth-backend-module-atlassian-provider': minor +'@backstage/plugin-auth-backend-module-bitbucket-provider': minor +'@backstage/plugin-auth-backend-module-microsoft-provider': minor +'@backstage/plugin-auth-backend-module-onelogin-provider': minor +'@backstage/plugin-auth-backend-module-aws-alb-provider': minor +'@backstage/plugin-auth-backend-module-gcp-iap-provider': minor +'@backstage/plugin-auth-backend-module-github-provider': minor +'@backstage/plugin-auth-backend-module-gitlab-provider': minor +'@backstage/plugin-auth-backend-module-google-provider': minor +'@backstage/plugin-auth-backend-module-oauth2-provider': minor +'@backstage/plugin-auth-backend-module-oidc-provider': minor +'@backstage/plugin-auth-backend-module-okta-provider': minor +'@backstage/plugin-auth-backend': minor +'@backstage/plugin-auth-node': minor +--- + +introduce dangerouslyAllowSignInWithoutUserInCatalog auth resolver config diff --git a/docs/auth/identity-resolver.md b/docs/auth/identity-resolver.md index 6a59805b0b..0c9b44b51d 100644 --- a/docs/auth/identity-resolver.md +++ b/docs/auth/identity-resolver.md @@ -351,8 +351,12 @@ users to sign in, for example by checking email domains. While populating the catalog with organizational data unlocks more powerful ways to browse your software ecosystem, it might not always be a viable or prioritized option. However, even if you do not have user entities populated in your catalog, you -can still sign in users. As there are currently no built-in sign-in resolvers for -this scenario you will need to implement your own. +can still sign in users. + +##### Custom Sign-in Resolver to bypass user in catalog requirement + +As there are currently no built-in sign-in resolvers for +this scenario you may want to implement your own. Signing in a user that doesn't exist in the catalog is as simple as skipping the catalog lookup step from the above example. Rather than looking up the user, we @@ -446,6 +450,36 @@ return ctx.issueToken({ }); ``` +##### Using the `dangerouslyAllowSignInWithoutUserInCatalog` Option + +Another way to bypass this requirement is to enable the `dangerouslyAllowSignInWithoutUserInCatalog` option for resolvers. +Users will still be authenticated as usual but this config will bypass the check that ensures the user is present in the catalog. +If the user entity is not found in the catalog, a Backstage user token will still be issued based on the identifying information available at the resolver level. + +For example: + +```yaml title="Within the provider configuration" +auth: + providers: + github: + development: + ... + signIn: + resolvers: + - resolver: emailLocalPartMatchingUserEntityName + dangerouslyAllowSignInWithoutUserInCatalog: true +``` + +:::warning +Enabling this option in production poses security risks. +::: + +This option may grant access to unexpected users who haven’t been onboarded into +Backstage. Since there is no user entity to associate with the signed-in user, permissions +may not apply as expected and they will have the same permissions as a guest user. +Careful consideration should be given to the permissions assigned to such users, +particularly when using the permission system. + ## Profile Transforms Similar to a custom sign-in resolver, you can also write a custom profile transform diff --git a/plugins/auth-backend-module-atlassian-provider/config.d.ts b/plugins/auth-backend-module-atlassian-provider/config.d.ts index f6433c123e..2729ad31fd 100644 --- a/plugins/auth-backend-module-atlassian-provider/config.d.ts +++ b/plugins/auth-backend-module-atlassian-provider/config.d.ts @@ -32,12 +32,19 @@ export interface Config { additionalScopes?: string | string[]; signIn?: { resolvers: Array< - | { resolver: 'usernameMatchingUserEntityName' } + | { + resolver: 'usernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-atlassian-provider/package.json b/plugins/auth-backend-module-atlassian-provider/package.json index 888414bb9d..3d3ad1db41 100644 --- a/plugins/auth-backend-module-atlassian-provider/package.json +++ b/plugins/auth-backend-module-atlassian-provider/package.json @@ -38,7 +38,8 @@ "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", "passport": "^0.7.0", - "passport-atlassian-oauth2": "^2.1.0" + "passport-atlassian-oauth2": "^2.1.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-atlassian-provider/report.api.md b/plugins/auth-backend-module-atlassian-provider/report.api.md index 7abdf7ee70..c9e184aeac 100644 --- a/plugins/auth-backend-module-atlassian-provider/report.api.md +++ b/plugins/auth-backend-module-atlassian-provider/report.api.md @@ -20,7 +20,10 @@ export const atlassianAuthenticator: OAuthAuthenticator< export namespace atlassianSignInResolvers { const usernameMatchingUserEntityName: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } diff --git a/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts b/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts index 1f3090bfdd..cbd93e4b4f 100644 --- a/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Atlassian auth provider. @@ -31,7 +32,12 @@ export namespace atlassianSignInResolvers { * Looks up the user by matching their Atlassian username to the entity name. */ export const usernameMatchingUserEntityName = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -43,7 +49,15 @@ export namespace atlassianSignInResolvers { throw new Error(`Atlassian user profile does not contain a username`); } - return ctx.signInWithCatalogUser({ entityRef: { name: id } }); + return ctx.signInWithCatalogUser( + { entityRef: { name: id } }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-aws-alb-provider/config.d.ts b/plugins/auth-backend-module-aws-alb-provider/config.d.ts index 41c84872de..3a5d2d5eca 100644 --- a/plugins/auth-backend-module-aws-alb-provider/config.d.ts +++ b/plugins/auth-backend-module-aws-alb-provider/config.d.ts @@ -46,8 +46,12 @@ export interface Config { | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-aws-alb-provider/package.json b/plugins/auth-backend-module-aws-alb-provider/package.json index 55bff1e1d2..0c8c0b8a57 100644 --- a/plugins/auth-backend-module-aws-alb-provider/package.json +++ b/plugins/auth-backend-module-aws-alb-provider/package.json @@ -42,7 +42,8 @@ "@backstage/plugin-auth-backend": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "jose": "^5.0.0", - "node-cache": "^5.1.2" + "node-cache": "^5.1.2", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/plugins/auth-backend-module-aws-alb-provider/report.api.md b/plugins/auth-backend-module-aws-alb-provider/report.api.md index 567bff993c..ebb3e8e24a 100644 --- a/plugins/auth-backend-module-aws-alb-provider/report.api.md +++ b/plugins/auth-backend-module-aws-alb-provider/report.api.md @@ -41,7 +41,10 @@ export namespace awsAlbSignInResolvers { const // (undocumented) emailMatchingUserEntityProfileEmail: SignInResolverFactory< AwsAlbResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts b/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts index 990c447124..5d04de620f 100644 --- a/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts @@ -19,6 +19,8 @@ import { SignInInfo, } from '@backstage/plugin-auth-node'; import { AwsAlbResult } from './types'; +import { z } from 'zod'; + /** * Available sign-in resolvers for the AWS ALB auth provider. * @@ -27,19 +29,33 @@ import { AwsAlbResult } from './types'; export namespace awsAlbSignInResolvers { export const emailMatchingUserEntityProfileEmail = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info: SignInInfo, ctx) => { if (!info.result.fullProfile.emails) { throw new Error( 'Login failed, user profile does not contain an email', ); } - return ctx.signInWithCatalogUser({ - filter: { - kind: ['User'], - 'spec.profile.email': info.result.fullProfile.emails[0].value, + + return ctx.signInWithCatalogUser( + { + filter: { + kind: ['User'], + 'spec.profile.email': info.result.fullProfile.emails[0].value, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: info.result.fullProfile.emails[0].value } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-azure-easyauth-provider/package.json b/plugins/auth-backend-module-azure-easyauth-provider/package.json index 546542c116..9b678ce2c0 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/package.json +++ b/plugins/auth-backend-module-azure-easyauth-provider/package.json @@ -40,7 +40,8 @@ "@types/passport": "^1.0.16", "express": "^4.19.2", "jose": "^5.0.0", - "passport": "^0.7.0" + "passport": "^0.7.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/plugins/auth-backend-module-azure-easyauth-provider/report.api.md b/plugins/auth-backend-module-azure-easyauth-provider/report.api.md index 9d337e3f34..717864f422 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/report.api.md +++ b/plugins/auth-backend-module-azure-easyauth-provider/report.api.md @@ -32,7 +32,10 @@ export namespace azureEasyAuthSignInResolvers { const // (undocumented) idMatchingUserEntityAnnotation: SignInResolverFactory< AzureEasyAuthResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } diff --git a/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts b/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts index e9e35420d1..17463123c4 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts @@ -19,11 +19,17 @@ import { SignInInfo, } from '@backstage/plugin-auth-node'; import { AzureEasyAuthResult } from './types'; +import { z } from 'zod'; /** @public */ export namespace azureEasyAuthSignInResolvers { export const idMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info: SignInInfo, ctx) => { const { fullProfile: { id }, @@ -32,12 +38,19 @@ export namespace azureEasyAuthSignInResolvers { if (!id) { throw new Error('User profile contained no id'); } - - return await ctx.signInWithCatalogUser({ - annotations: { - 'graph.microsoft.com/user-id': id, + return ctx.signInWithCatalogUser( + { + annotations: { + 'graph.microsoft.com/user-id': id, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-bitbucket-provider/config.d.ts b/plugins/auth-backend-module-bitbucket-provider/config.d.ts index f3d82608bd..56303b5215 100644 --- a/plugins/auth-backend-module-bitbucket-provider/config.d.ts +++ b/plugins/auth-backend-module-bitbucket-provider/config.d.ts @@ -30,12 +30,23 @@ export interface Config { additionalScopes?: string | string[]; signIn?: { resolvers: Array< - | { resolver: 'userIdMatchingUserEntityAnnotation' } + | { + resolver: 'userIdMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'usernameMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-bitbucket-provider/package.json b/plugins/auth-backend-module-bitbucket-provider/package.json index 38f31b7473..2df7d654f7 100644 --- a/plugins/auth-backend-module-bitbucket-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-provider/package.json @@ -38,7 +38,8 @@ "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", "passport": "^0.7.0", - "passport-bitbucket-oauth2": "^0.1.2" + "passport-bitbucket-oauth2": "^0.1.2", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-bitbucket-provider/report.api.md b/plugins/auth-backend-module-bitbucket-provider/report.api.md index ceb4141fd9..86cff50a0f 100644 --- a/plugins/auth-backend-module-bitbucket-provider/report.api.md +++ b/plugins/auth-backend-module-bitbucket-provider/report.api.md @@ -24,11 +24,17 @@ export const bitbucketAuthenticator: OAuthAuthenticator< export namespace bitbucketSignInResolvers { const userIdMatchingUserEntityAnnotation: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; const usernameMatchingUserEntityAnnotation: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts b/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts index f9d834a3a7..1dd9783b98 100644 --- a/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Bitbucket auth provider. @@ -32,7 +33,12 @@ export namespace bitbucketSignInResolvers { */ export const userIdMatchingUserEntityAnnotation = createSignInResolverFactory( { - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -44,11 +50,19 @@ export namespace bitbucketSignInResolvers { throw new Error('Bitbucket user profile does not contain an ID'); } - return ctx.signInWithCatalogUser({ - annotations: { - 'bitbucket.org/user-id': id, + return ctx.signInWithCatalogUser( + { + annotations: { + 'bitbucket.org/user-id': id, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }, @@ -59,7 +73,12 @@ export namespace bitbucketSignInResolvers { */ export const usernameMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -73,11 +92,19 @@ export namespace bitbucketSignInResolvers { ); } - return ctx.signInWithCatalogUser({ - annotations: { - 'bitbucket.org/username': username, + return ctx.signInWithCatalogUser( + { + annotations: { + 'bitbucket.org/username': username, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: username } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-bitbucket-server-provider/config.d.ts b/plugins/auth-backend-module-bitbucket-server-provider/config.d.ts index 8e63581625..26afb46f09 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/config.d.ts +++ b/plugins/auth-backend-module-bitbucket-server-provider/config.d.ts @@ -29,6 +29,27 @@ export interface Config { clientSecret: string; host: string; callbackUrl?: string; + signIn?: { + resolvers: Array< + | { + resolver: 'userIdMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'usernameMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailLocalPartMatchingUserEntityName'; + allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + >; + }; sessionDuration?: HumanDuration | string; }; }; diff --git a/plugins/auth-backend-module-bitbucket-server-provider/package.json b/plugins/auth-backend-module-bitbucket-server-provider/package.json index 2d5eca7a89..b57937cb6a 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-server-provider/package.json @@ -37,7 +37,8 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "passport": "^0.7.0", - "passport-oauth2": "^1.6.1" + "passport-oauth2": "^1.6.1", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-bitbucket-server-provider/report.api.md b/plugins/auth-backend-module-bitbucket-server-provider/report.api.md index d5c484f6e3..d9409bd36d 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/report.api.md +++ b/plugins/auth-backend-module-bitbucket-server-provider/report.api.md @@ -27,7 +27,10 @@ export const bitbucketServerAuthenticator: OAuthAuthenticator< export namespace bitbucketServerSignInResolvers { const emailMatchingUserEntityProfileEmail: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts b/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts index dc2ceef7e9..cf6970a6df 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts @@ -19,6 +19,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Bitbucket Server auth provider. @@ -31,7 +32,12 @@ export namespace bitbucketServerSignInResolvers { */ export const emailMatchingUserEntityProfileEmail = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -44,11 +50,19 @@ export namespace bitbucketServerSignInResolvers { ); } - return ctx.signInWithCatalogUser({ - filter: { - 'spec.profile.email': profile.email, + return ctx.signInWithCatalogUser( + { + filter: { + 'spec.profile.email': profile.email, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: profile.email } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-cloudflare-access-provider/config.d.ts b/plugins/auth-backend-module-cloudflare-access-provider/config.d.ts index 39a4ca3eb6..c4ea052db3 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/config.d.ts +++ b/plugins/auth-backend-module-cloudflare-access-provider/config.d.ts @@ -34,8 +34,12 @@ export interface Config { | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; }; diff --git a/plugins/auth-backend-module-cloudflare-access-provider/package.json b/plugins/auth-backend-module-cloudflare-access-provider/package.json index 9f70fe9dbe..5ca22b0465 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/package.json +++ b/plugins/auth-backend-module-cloudflare-access-provider/package.json @@ -39,7 +39,8 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", - "jose": "^5.0.0" + "jose": "^5.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-cloudflare-access-provider/report.api.md b/plugins/auth-backend-module-cloudflare-access-provider/report.api.md index 1547190d39..98c55e80bf 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/report.api.md +++ b/plugins/auth-backend-module-cloudflare-access-provider/report.api.md @@ -52,7 +52,10 @@ export type CloudflareAccessResult = { export namespace cloudflareAccessSignInResolvers { const emailMatchingUserEntityProfileEmail: SignInResolverFactory< CloudflareAccessResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } diff --git a/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.test.ts b/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.test.ts index 27cdfa001c..2ab49c313a 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.test.ts +++ b/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.test.ts @@ -37,8 +37,13 @@ describe('resolvers', () => { } satisfies Partial; await resolver(info, context as any); - expect(context.signInWithCatalogUser).toHaveBeenCalledWith({ - filter: { 'spec.profile.email': 'hello@example.com' }, - }); + expect(context.signInWithCatalogUser).toHaveBeenCalledWith( + { + filter: { 'spec.profile.email': 'hello@example.com' }, + }, + { + dangerousEntityRefFallback: undefined, + }, + ); }); }); diff --git a/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts b/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts index ad0b512a65..6ac9fba958 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts @@ -19,6 +19,7 @@ import { SignInInfo, } from '@backstage/plugin-auth-node'; import { CloudflareAccessResult } from './types'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Cloudflare Access auth provider. @@ -31,7 +32,12 @@ export namespace cloudflareAccessSignInResolvers { */ export const emailMatchingUserEntityProfileEmail = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info: SignInInfo, ctx) => { const { profile } = info; @@ -41,11 +47,19 @@ export namespace cloudflareAccessSignInResolvers { ); } - return ctx.signInWithCatalogUser({ - filter: { - 'spec.profile.email': profile.email, + return ctx.signInWithCatalogUser( + { + filter: { + 'spec.profile.email': profile.email, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: profile.email } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-gcp-iap-provider/config.d.ts b/plugins/auth-backend-module-gcp-iap-provider/config.d.ts index d99d890b50..572afdb0e6 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/config.d.ts +++ b/plugins/auth-backend-module-gcp-iap-provider/config.d.ts @@ -36,13 +36,23 @@ export interface Config { signIn?: { resolvers: Array< - | { resolver: 'emailMatchingUserEntityAnnotation' } - | { resolver: 'idMatchingUserEntityAnnotation' } + | { + resolver: 'emailMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'idMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 27fd8fb47d..2d89dbb9fe 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -42,7 +42,8 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", - "google-auth-library": "^9.0.0" + "google-auth-library": "^9.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/plugins/auth-backend-module-gcp-iap-provider/report.api.md b/plugins/auth-backend-module-gcp-iap-provider/report.api.md index 1476694f99..5cad28ac87 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/report.api.md +++ b/plugins/auth-backend-module-gcp-iap-provider/report.api.md @@ -35,11 +35,17 @@ export type GcpIapResult = { export namespace gcpIapSignInResolvers { const emailMatchingUserEntityAnnotation: SignInResolverFactory< GcpIapResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; const idMatchingUserEntityAnnotation: SignInResolverFactory< GcpIapResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } diff --git a/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts b/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts index 557ee8fdfe..383d32cc57 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts @@ -19,6 +19,7 @@ import { SignInInfo, } from '@backstage/plugin-auth-node'; import { GcpIapResult } from './types'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Google auth provider. @@ -30,7 +31,12 @@ export namespace gcpIapSignInResolvers { * Looks up the user by matching their email to the `google.com/email` annotation. */ export const emailMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info: SignInInfo, ctx) => { const email = info.result.iapToken.email; @@ -38,11 +44,19 @@ export namespace gcpIapSignInResolvers { throw new Error('Google IAP sign-in result is missing email'); } - return ctx.signInWithCatalogUser({ - annotations: { - 'google.com/email': email, + return ctx.signInWithCatalogUser( + { + annotations: { + 'google.com/email': email, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: email } + : undefined, + }, + ); }; }, }); @@ -51,15 +65,28 @@ export namespace gcpIapSignInResolvers { * Looks up the user by matching their user ID to the `google.com/user-id` annotation. */ export const idMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info: SignInInfo, ctx) => { const userId = info.result.iapToken.sub.split(':')[1]; - return ctx.signInWithCatalogUser({ - annotations: { - 'google.com/user-id': userId, + return ctx.signInWithCatalogUser( + { + annotations: { + 'google.com/user-id': userId, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: userId } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-github-provider/config.d.ts b/plugins/auth-backend-module-github-provider/config.d.ts index 69abfa0d12..15ed412a6f 100644 --- a/plugins/auth-backend-module-github-provider/config.d.ts +++ b/plugins/auth-backend-module-github-provider/config.d.ts @@ -32,12 +32,18 @@ export interface Config { additionalScopes?: string | string[]; signIn?: { resolvers: Array< - | { resolver: 'usernameMatchingUserEntityName' } | { - resolver: 'emailLocalPartMatchingUserEntityName'; - allowedDomains?: string[]; + resolver: 'usernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'preferredUsernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index 2088c400ad..88a4cca547 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -36,7 +36,8 @@ "dependencies": { "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", - "passport-github2": "^0.1.12" + "passport-github2": "^0.1.12", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-github-provider/report.api.md b/plugins/auth-backend-module-github-provider/report.api.md index 222305adfd..6bad840d00 100644 --- a/plugins/auth-backend-module-github-provider/report.api.md +++ b/plugins/auth-backend-module-github-provider/report.api.md @@ -24,7 +24,10 @@ export const githubAuthenticator: OAuthAuthenticator< export namespace githubSignInResolvers { const usernameMatchingUserEntityName: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-github-provider/src/resolvers.ts b/plugins/auth-backend-module-github-provider/src/resolvers.ts index 496080a33c..cc1950e9dd 100644 --- a/plugins/auth-backend-module-github-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-github-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the GitHub auth provider. @@ -31,7 +32,12 @@ export namespace githubSignInResolvers { * Looks up the user by matching their GitHub username to the entity name. */ export const usernameMatchingUserEntityName = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -43,7 +49,17 @@ export namespace githubSignInResolvers { throw new Error(`GitHub user profile does not contain a username`); } - return ctx.signInWithCatalogUser({ entityRef: { name: userId } }); + return ctx.signInWithCatalogUser( + { + entityRef: { name: userId }, + }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: userId } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-gitlab-provider/config.d.ts b/plugins/auth-backend-module-gitlab-provider/config.d.ts index 8d47421255..8cbb253e2c 100644 --- a/plugins/auth-backend-module-gitlab-provider/config.d.ts +++ b/plugins/auth-backend-module-gitlab-provider/config.d.ts @@ -32,12 +32,19 @@ export interface Config { additionalScopes?: string | string[]; signIn?: { resolvers: Array< - | { resolver: 'usernameMatchingUserEntityName' } + | { + resolver: 'usernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index 552cfd726a..b0f11e1e04 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -38,7 +38,8 @@ "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", "passport": "^0.7.0", - "passport-gitlab2": "^5.0.0" + "passport-gitlab2": "^5.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-gitlab-provider/report.api.md b/plugins/auth-backend-module-gitlab-provider/report.api.md index 44c5ffb214..cb914deeea 100644 --- a/plugins/auth-backend-module-gitlab-provider/report.api.md +++ b/plugins/auth-backend-module-gitlab-provider/report.api.md @@ -24,7 +24,10 @@ export const gitlabAuthenticator: OAuthAuthenticator< export namespace gitlabSignInResolvers { const usernameMatchingUserEntityName: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts b/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts index 755ed08aa0..b235f7b4bb 100644 --- a/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the GitLab auth provider. @@ -31,7 +32,12 @@ export namespace gitlabSignInResolvers { * Looks up the user by matching their GitLab username to the entity name. */ export const usernameMatchingUserEntityName = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -43,7 +49,17 @@ export namespace gitlabSignInResolvers { throw new Error(`GitLab user profile does not contain a username`); } - return ctx.signInWithCatalogUser({ entityRef: { name: id } }); + return ctx.signInWithCatalogUser( + { + entityRef: { name: id }, + }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-google-provider/config.d.ts b/plugins/auth-backend-module-google-provider/config.d.ts index ec3cd92b31..842635480c 100644 --- a/plugins/auth-backend-module-google-provider/config.d.ts +++ b/plugins/auth-backend-module-google-provider/config.d.ts @@ -32,12 +32,19 @@ export interface Config { additionalScopes?: string | string[]; signIn?: { resolvers: Array< - | { resolver: 'emailMatchingUserEntityAnnotation' } + | { + resolver: 'emailMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index 5f974bb9fe..447230cc51 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -41,7 +41,8 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "google-auth-library": "^9.0.0", - "passport-google-oauth20": "^2.0.0" + "passport-google-oauth20": "^2.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/plugins/auth-backend-module-google-provider/report.api.md b/plugins/auth-backend-module-google-provider/report.api.md index eeefb8e837..f06a3c3355 100644 --- a/plugins/auth-backend-module-google-provider/report.api.md +++ b/plugins/auth-backend-module-google-provider/report.api.md @@ -24,7 +24,10 @@ export const googleAuthenticator: OAuthAuthenticator< export namespace googleSignInResolvers { const emailMatchingUserEntityAnnotation: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } diff --git a/plugins/auth-backend-module-google-provider/src/resolvers.ts b/plugins/auth-backend-module-google-provider/src/resolvers.ts index b19fc4d49f..c9ba884cfb 100644 --- a/plugins/auth-backend-module-google-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-google-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Google auth provider. @@ -31,7 +32,12 @@ export namespace googleSignInResolvers { * Looks up the user by matching their email to the `google.com/email` annotation. */ export const emailMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -42,11 +48,19 @@ export namespace googleSignInResolvers { throw new Error('Google profile contained no email'); } - return ctx.signInWithCatalogUser({ - annotations: { - 'google.com/email': profile.email, + return ctx.signInWithCatalogUser( + { + annotations: { + 'google.com/email': profile.email, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: profile.email } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-microsoft-provider/config.d.ts b/plugins/auth-backend-module-microsoft-provider/config.d.ts index 3cfcd45a2a..8ea62ddd86 100644 --- a/plugins/auth-backend-module-microsoft-provider/config.d.ts +++ b/plugins/auth-backend-module-microsoft-provider/config.d.ts @@ -34,13 +34,23 @@ export interface Config { skipUserProfile?: boolean; signIn?: { resolvers: Array< - | { resolver: 'emailMatchingUserEntityAnnotation' } + | { + resolver: 'emailMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'userIdMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } - | { resolver: 'userIdMatchingUserEntityAnnotation' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index a6666690cc..b744d9199a 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -38,7 +38,8 @@ "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", "jose": "^5.0.0", - "passport-microsoft": "^1.0.0" + "passport-microsoft": "^1.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-microsoft-provider/report.api.md b/plugins/auth-backend-module-microsoft-provider/report.api.md index 6aef395d7c..9e37eee771 100644 --- a/plugins/auth-backend-module-microsoft-provider/report.api.md +++ b/plugins/auth-backend-module-microsoft-provider/report.api.md @@ -30,11 +30,17 @@ export const microsoftAuthenticator: OAuthAuthenticator< export namespace microsoftSignInResolvers { const emailMatchingUserEntityAnnotation: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; const userIdMatchingUserEntityAnnotation: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts b/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts index db7aa4f7f3..5090e26c5a 100644 --- a/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Microsoft auth provider. @@ -31,7 +32,12 @@ export namespace microsoftSignInResolvers { * Looks up the user by matching their Microsoft email to the email entity annotation. */ export const emailMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -42,11 +48,19 @@ export namespace microsoftSignInResolvers { throw new Error('Microsoft profile contained no email'); } - return ctx.signInWithCatalogUser({ - annotations: { - 'microsoft.com/email': profile.email, + return ctx.signInWithCatalogUser( + { + annotations: { + 'microsoft.com/email': profile.email, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: profile.email } + : undefined, + }, + ); }; }, }); @@ -55,7 +69,12 @@ export namespace microsoftSignInResolvers { */ export const userIdMatchingUserEntityAnnotation = createSignInResolverFactory( { - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -68,11 +87,19 @@ export namespace microsoftSignInResolvers { throw new Error('Microsoft profile contained no id'); } - return ctx.signInWithCatalogUser({ - annotations: { - 'graph.microsoft.com/user-id': id, + return ctx.signInWithCatalogUser( + { + annotations: { + 'graph.microsoft.com/user-id': id, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }, diff --git a/plugins/auth-backend-module-oauth2-provider/config.d.ts b/plugins/auth-backend-module-oauth2-provider/config.d.ts index ba047e3340..8818211318 100644 --- a/plugins/auth-backend-module-oauth2-provider/config.d.ts +++ b/plugins/auth-backend-module-oauth2-provider/config.d.ts @@ -36,12 +36,19 @@ export interface Config { includeBasicAuth?: boolean; signIn?: { resolvers: Array< - | { resolver: 'usernameMatchingUserEntityName' } + | { + resolver: 'usernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index 73c5bb2943..1d1b9acf41 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -37,7 +37,8 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "passport": "^0.7.0", - "passport-oauth2": "^1.6.1" + "passport-oauth2": "^1.6.1", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-oauth2-provider/report.api.md b/plugins/auth-backend-module-oauth2-provider/report.api.md index 632591ec04..b4b7d6d465 100644 --- a/plugins/auth-backend-module-oauth2-provider/report.api.md +++ b/plugins/auth-backend-module-oauth2-provider/report.api.md @@ -24,7 +24,10 @@ export const oauth2Authenticator: OAuthAuthenticator< export namespace oauth2SignInResolvers { const usernameMatchingUserEntityName: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts b/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts index c77f5afa03..7bf098a308 100644 --- a/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the oauth2 auth provider. @@ -31,7 +32,12 @@ export namespace oauth2SignInResolvers { * Looks up the user by matching their oauth2 username to the entity name. */ export const usernameMatchingUserEntityName = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -43,7 +49,17 @@ export namespace oauth2SignInResolvers { throw new Error(`Oauth2 user profile does not contain a username`); } - return ctx.signInWithCatalogUser({ entityRef: { name: id } }); + return ctx.signInWithCatalogUser( + { + entityRef: { name: id }, + }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/package.json b/plugins/auth-backend-module-oauth2-proxy-provider/package.json index e48c4dd547..bd2362af1a 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/package.json +++ b/plugins/auth-backend-module-oauth2-proxy-provider/package.json @@ -36,7 +36,8 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", - "jose": "^5.0.0" + "jose": "^5.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/report.api.md b/plugins/auth-backend-module-oauth2-proxy-provider/report.api.md index aa360bc9c5..2efdc52635 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/report.api.md +++ b/plugins/auth-backend-module-oauth2-proxy-provider/report.api.md @@ -6,6 +6,7 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { IncomingHttpHeaders } from 'http'; import { ProxyAuthenticator } from '@backstage/plugin-auth-node'; +import { SignInResolverFactory } from '@backstage/plugin-auth-node'; // @public (undocumented) const authModuleOauth2ProxyProvider: BackendFeature; @@ -30,4 +31,16 @@ export type OAuth2ProxyResult = { headers: IncomingHttpHeaders; getHeader(name: string): string | undefined; }; + +// @public (undocumented) +export namespace oauth2ProxySignInResolvers { + const // (undocumented) + forwardedUserMatchingUserEntityName: SignInResolverFactory< + OAuth2ProxyResult, + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined + >; +} ``` diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts index b804f666c7..34617d4325 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts @@ -20,6 +20,7 @@ * @packageDocumentation */ export { authModuleOauth2ProxyProvider as default } from './module'; +export { oauth2ProxySignInResolvers } from './resolvers'; export { oauth2ProxyAuthenticator, OAUTH2_PROXY_JWT_HEADER, diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts index 99ca8bc156..a31e1958dc 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts @@ -19,6 +19,7 @@ import { SignInInfo, } from '@backstage/plugin-auth-node'; import { OAuth2ProxyResult } from './types'; +import { z } from 'zod'; /** * @public @@ -26,15 +27,29 @@ import { OAuth2ProxyResult } from './types'; export namespace oauth2ProxySignInResolvers { export const forwardedUserMatchingUserEntityName = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info: SignInInfo, ctx) => { const name = info.result.getHeader('x-forwarded-user'); if (!name) { throw new Error('Request did not contain a user'); } - return ctx.signInWithCatalogUser({ - entityRef: { name }, - }); + + return ctx.signInWithCatalogUser( + { + entityRef: { name }, + }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-oidc-provider/config.d.ts b/plugins/auth-backend-module-oidc-provider/config.d.ts index 8a1df804e6..c11b9319ec 100644 --- a/plugins/auth-backend-module-oidc-provider/config.d.ts +++ b/plugins/auth-backend-module-oidc-provider/config.d.ts @@ -38,8 +38,16 @@ export interface Config { | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'preferredUsernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-oidc-provider/package.json b/plugins/auth-backend-module-oidc-provider/package.json index f8fb443093..76e726a474 100644 --- a/plugins/auth-backend-module-oidc-provider/package.json +++ b/plugins/auth-backend-module-oidc-provider/package.json @@ -41,7 +41,8 @@ "@backstage/types": "workspace:^", "express": "^4.18.2", "openid-client": "^5.5.0", - "passport": "^0.7.0" + "passport": "^0.7.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-oidc-provider/report.api.md b/plugins/auth-backend-module-oidc-provider/report.api.md index 93c000c2ee..11cde22db1 100644 --- a/plugins/auth-backend-module-oidc-provider/report.api.md +++ b/plugins/auth-backend-module-oidc-provider/report.api.md @@ -41,12 +41,17 @@ export namespace oidcSignInResolvers { unknown, | { allowedDomains?: string[] | undefined; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; } | undefined >; const emailMatchingUserEntityProfileEmail: SignInResolverFactory< unknown, - unknown + | { + allowedDomains?: string[] | undefined; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-oidc-provider/src/module.ts b/plugins/auth-backend-module-oidc-provider/src/module.ts index 5680cd8603..5e4daf20c3 100644 --- a/plugins/auth-backend-module-oidc-provider/src/module.ts +++ b/plugins/auth-backend-module-oidc-provider/src/module.ts @@ -16,7 +16,6 @@ import { createBackendModule } from '@backstage/backend-plugin-api'; import { authProvidersExtensionPoint, - commonSignInResolvers, createOAuthProviderFactory, } from '@backstage/plugin-auth-node'; import { oidcAuthenticator } from './authenticator'; @@ -38,7 +37,6 @@ export const authModuleOidcProvider = createBackendModule({ authenticator: oidcAuthenticator, signInResolverFactories: { ...oidcSignInResolvers, - ...commonSignInResolvers, }, }), }); diff --git a/plugins/auth-backend-module-okta-provider/config.d.ts b/plugins/auth-backend-module-okta-provider/config.d.ts index 3f27e805ec..f475a1d693 100644 --- a/plugins/auth-backend-module-okta-provider/config.d.ts +++ b/plugins/auth-backend-module-okta-provider/config.d.ts @@ -34,12 +34,19 @@ export interface Config { additionalScopes?: string | string[]; signIn?: { resolvers: Array< - | { resolver: 'emailMatchingUserEntityAnnotation' } + | { + resolver: 'emailMatchingUserEntityAnnotation'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-okta-provider/package.json b/plugins/auth-backend-module-okta-provider/package.json index a46671d1a1..963ef180a6 100644 --- a/plugins/auth-backend-module-okta-provider/package.json +++ b/plugins/auth-backend-module-okta-provider/package.json @@ -38,7 +38,8 @@ "@backstage/plugin-auth-node": "workspace:^", "@davidzemon/passport-okta-oauth": "^0.0.5", "express": "^4.18.2", - "passport": "^0.7.0" + "passport": "^0.7.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-okta-provider/report.api.md b/plugins/auth-backend-module-okta-provider/report.api.md index a142265100..796e0f20a6 100644 --- a/plugins/auth-backend-module-okta-provider/report.api.md +++ b/plugins/auth-backend-module-okta-provider/report.api.md @@ -24,7 +24,10 @@ export const oktaAuthenticator: OAuthAuthenticator< export namespace oktaSignInResolvers { const emailMatchingUserEntityAnnotation: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-okta-provider/src/resolvers.ts b/plugins/auth-backend-module-okta-provider/src/resolvers.ts index 8bc3f38f17..b3b2a33493 100644 --- a/plugins/auth-backend-module-okta-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-okta-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the Okta auth provider. @@ -32,7 +33,12 @@ export namespace oktaSignInResolvers { */ export const emailMatchingUserEntityAnnotation = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -43,11 +49,19 @@ export namespace oktaSignInResolvers { throw new Error('Okta profile contained no email'); } - return ctx.signInWithCatalogUser({ - annotations: { - 'okta.com/email': profile.email, + return ctx.signInWithCatalogUser( + { + annotations: { + 'okta.com/email': profile.email, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: profile.email } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-onelogin-provider/config.d.ts b/plugins/auth-backend-module-onelogin-provider/config.d.ts index 58f471bafb..e8fd6f6749 100644 --- a/plugins/auth-backend-module-onelogin-provider/config.d.ts +++ b/plugins/auth-backend-module-onelogin-provider/config.d.ts @@ -31,12 +31,19 @@ export interface Config { callbackUrl?: string; signIn?: { resolvers: Array< - | { resolver: 'usernameMatchingUserEntityName' } + | { + resolver: 'usernameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend-module-onelogin-provider/package.json b/plugins/auth-backend-module-onelogin-provider/package.json index 64c5768c3e..ecc1c03825 100644 --- a/plugins/auth-backend-module-onelogin-provider/package.json +++ b/plugins/auth-backend-module-onelogin-provider/package.json @@ -38,7 +38,8 @@ "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", "passport": "^0.7.0", - "passport-onelogin-oauth": "^0.0.1" + "passport-onelogin-oauth": "^0.0.1", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", diff --git a/plugins/auth-backend-module-onelogin-provider/report.api.md b/plugins/auth-backend-module-onelogin-provider/report.api.md index 1991f00e0b..df3345f5ed 100644 --- a/plugins/auth-backend-module-onelogin-provider/report.api.md +++ b/plugins/auth-backend-module-onelogin-provider/report.api.md @@ -24,7 +24,10 @@ export const oneLoginAuthenticator: OAuthAuthenticator< export namespace oneLoginSignInResolvers { const usernameMatchingUserEntityName: SignInResolverFactory< OAuthAuthenticatorResult, - unknown + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; } ``` diff --git a/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts b/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts index 93bfd758cb..4a617589da 100644 --- a/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts @@ -20,6 +20,7 @@ import { PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; +import { z } from 'zod'; /** * Available sign-in resolvers for the OneLogin auth provider. @@ -31,7 +32,12 @@ export namespace oneLoginSignInResolvers { * Looks up the user by matching their OneLogin username to the entity name. */ export const usernameMatchingUserEntityName = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async ( info: SignInInfo>, ctx, @@ -43,7 +49,17 @@ export namespace oneLoginSignInResolvers { throw new Error(`OneLogin user profile does not contain a username`); } - return ctx.signInWithCatalogUser({ entityRef: { name: id } }); + return ctx.signInWithCatalogUser( + { + entityRef: { name: id }, + }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: id } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts b/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts index 9886d69a41..235d2ab0f1 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts +++ b/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts @@ -32,8 +32,12 @@ export interface Config { | { resolver: 'emailLocalPartMatchingUserEntityName'; allowedDomains?: string[]; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + } + | { + resolver: 'emailMatchingUserEntityProfileEmail'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; } - | { resolver: 'emailMatchingUserEntityProfileEmail' } >; }; sessionDuration?: HumanDuration | string; diff --git a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts index 5268833d14..e4deaaef33 100644 --- a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts +++ b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts @@ -139,19 +139,59 @@ export class CatalogAuthResolverContext implements AuthResolverContext { return { entity: result }; } - async signInWithCatalogUser(query: AuthResolverCatalogUserQuery) { - const { entity } = await this.findCatalogUser(query); + async signInWithCatalogUser( + query: AuthResolverCatalogUserQuery, + options?: { + dangerousEntityRefFallback?: + | string + | { + kind?: string; + namespace?: string; + name: string; + }; + }, + ) { + try { + const { entity } = await this.findCatalogUser(query); - const { ownershipEntityRefs } = await this.resolveOwnershipEntityRefs( - entity, - ); + const { ownershipEntityRefs } = await this.resolveOwnershipEntityRefs( + entity, + ); - return await this.tokenIssuer.issueToken({ - claims: { - sub: stringifyEntityRef(entity), - ent: ownershipEntityRefs, - }, - }); + return await this.tokenIssuer.issueToken({ + claims: { + sub: stringifyEntityRef(entity), + ent: ownershipEntityRefs, + }, + }); + } catch (error) { + if (error?.name !== 'NotFoundError') { + throw error; + } + if (!options?.dangerousEntityRefFallback) { + this.logger.error( + 'Failed to sign-in, unable to resolve user identity. For non-production environments, manually provision the user or disable the user provisioning requirement by setting the dangerouslyAllowSignInWithoutUserInCatalog option.', + ); + + throw new Error( + 'Failed to sign-in, unable to resolve user identity. Please verify that your catalog contains the expected User entities that would match your configured sign-in resolver.', + ); + } + + const userEntityRef = stringifyEntityRef( + parseEntityRef(options.dangerousEntityRefFallback, { + defaultKind: 'User', + defaultNamespace: DEFAULT_NAMESPACE, + }), + ); + + return await this.tokenIssuer.issueToken({ + claims: { + sub: userEntityRef, + ent: [userEntityRef], + }, + }); + } } async resolveOwnershipEntityRefs( diff --git a/plugins/auth-node/report.api.md b/plugins/auth-node/report.api.md index ad0d85030c..64716dfe5c 100644 --- a/plugins/auth-node/report.api.md +++ b/plugins/auth-node/report.api.md @@ -110,6 +110,15 @@ export type AuthResolverContext = { }>; signInWithCatalogUser( query: AuthResolverCatalogUserQuery, + options?: { + dangerousEntityRefFallback?: + | string + | { + kind?: string; + namespace?: string; + name: string; + }; + }, ): Promise; resolveOwnershipEntityRefs(entity: Entity): Promise<{ ownershipEntityRefs: string[]; @@ -146,12 +155,17 @@ export type ClientAuthResponse = { export namespace commonSignInResolvers { const emailMatchingUserEntityProfileEmail: SignInResolverFactory< unknown, - unknown + | { + allowedDomains?: string[] | undefined; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined >; const emailLocalPartMatchingUserEntityName: SignInResolverFactory< unknown, | { allowedDomains?: string[] | undefined; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; } | undefined >; diff --git a/plugins/auth-node/src/sign-in/commonSignInResolvers.ts b/plugins/auth-node/src/sign-in/commonSignInResolvers.ts index 6f0fc7fdb2..307ebbfef5 100644 --- a/plugins/auth-node/src/sign-in/commonSignInResolvers.ts +++ b/plugins/auth-node/src/sign-in/commonSignInResolvers.ts @@ -35,7 +35,13 @@ export namespace commonSignInResolvers { */ export const emailMatchingUserEntityProfileEmail = createSignInResolverFactory({ - create() { + optionsSchema: z + .object({ + allowedDomains: z.array(z.string()).optional(), + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { return async (info, ctx) => { const { profile } = info; @@ -59,11 +65,19 @@ export namespace commonSignInResolvers { const [_, name, _plus, domain] = m; const noPlusEmail = `${name}${domain}`; - return ctx.signInWithCatalogUser({ - filter: { - 'spec.profile.email': noPlusEmail, + return ctx.signInWithCatalogUser( + { + filter: { + 'spec.profile.email': noPlusEmail, + }, }, - }); + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: noPlusEmail } + : undefined, + }, + ); } } // Email had no plus addressing or is missing in the catalog, forward failure @@ -82,6 +96,7 @@ export namespace commonSignInResolvers { optionsSchema: z .object({ allowedDomains: z.array(z.string()).optional(), + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), }) .optional(), create(options = {}) { @@ -102,10 +117,15 @@ export namespace commonSignInResolvers { 'Sign-in user email is not from an allowed domain', ); } - - return ctx.signInWithCatalogUser({ - entityRef: { name: localPart }, - }); + return ctx.signInWithCatalogUser( + { entityRef: { name: localPart } }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { name: localPart } + : undefined, + }, + ); }; }, }); diff --git a/plugins/auth-node/src/types.ts b/plugins/auth-node/src/types.ts index a7202d7748..b628313a4f 100644 --- a/plugins/auth-node/src/types.ts +++ b/plugins/auth-node/src/types.ts @@ -162,10 +162,24 @@ export type AuthResolverContext = { * Finds a single user in the catalog using the provided query, and then * issues an identity for that user using default ownership resolution. * + * If the user is not found, an optional `dangerousEntityRefFallback` + * entity ref can be provided to allow sign-in to proceed by issuing an + * identity based on the given ref. This bypasses the requirement for the + * user to exist in the catalog and should be used with caution. + * * See {@link AuthResolverCatalogUserQuery} for details. */ signInWithCatalogUser( query: AuthResolverCatalogUserQuery, + options?: { + dangerousEntityRefFallback?: + | string + | { + kind?: string; + namespace?: string; + name: string; + }; + }, ): Promise; /** diff --git a/yarn.lock b/yarn.lock index a8f9207723..92b7cb5e8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5108,6 +5108,7 @@ __metadata: passport: "npm:^0.7.0" passport-atlassian-oauth2: "npm:^2.1.0" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5147,6 +5148,7 @@ __metadata: jose: "npm:^5.0.0" msw: "npm:^2.0.8" node-cache: "npm:^5.1.2" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5165,6 +5167,7 @@ __metadata: express: "npm:^4.19.2" jose: "npm:^5.0.0" passport: "npm:^0.7.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5183,6 +5186,7 @@ __metadata: passport: "npm:^0.7.0" passport-bitbucket-oauth2: "npm:^0.1.2" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5201,6 +5205,7 @@ __metadata: passport: "npm:^0.7.0" passport-oauth2: "npm:^1.6.1" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5222,6 +5227,7 @@ __metadata: msw: "npm:^2.0.0" node-mocks-http: "npm:^1.0.0" uuid: "npm:^11.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5237,6 +5243,7 @@ __metadata: "@backstage/types": "workspace:^" express: "npm:^4.18.2" google-auth-library: "npm:^9.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5254,6 +5261,7 @@ __metadata: "@types/passport-github2": "npm:^1.2.4" passport-github2: "npm:^0.1.12" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5272,6 +5280,7 @@ __metadata: passport: "npm:^0.7.0" passport-gitlab2: "npm:^5.0.0" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5289,6 +5298,7 @@ __metadata: google-auth-library: "npm:^9.0.0" passport-google-oauth20: "npm:^2.0.0" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5326,6 +5336,7 @@ __metadata: msw: "npm:^1.0.0" passport-microsoft: "npm:^1.0.0" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5343,6 +5354,7 @@ __metadata: passport: "npm:^0.7.0" passport-oauth2: "npm:^1.6.1" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5356,6 +5368,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" jose: "npm:^5.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5380,6 +5393,7 @@ __metadata: openid-client: "npm:^5.5.0" passport: "npm:^0.7.0" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5398,6 +5412,7 @@ __metadata: express: "npm:^4.18.2" passport: "npm:^0.7.0" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5416,6 +5431,7 @@ __metadata: passport: "npm:^0.7.0" passport-onelogin-oauth: "npm:^0.0.1" supertest: "npm:^7.0.0" + zod: "npm:^3.22.4" languageName: unknown linkType: soft From 00b324388c404b3f260e6fc8d66305db344c19c7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 12:35:13 +0000 Subject: [PATCH 027/143] fix(deps): update swc monorepo Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- microsite/yarn.lock | 86 +++++++++++++++++++++--------------------- yarn.lock | 92 ++++++++++++++++++++++----------------------- 2 files changed, 89 insertions(+), 89 deletions(-) diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 618b716f4d..536df7761f 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -2961,90 +2961,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-darwin-arm64@npm:1.11.21" +"@swc/core-darwin-arm64@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-darwin-arm64@npm:1.11.24" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-darwin-x64@npm:1.11.21" +"@swc/core-darwin-x64@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-darwin-x64@npm:1.11.24" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.11.21" +"@swc/core-linux-arm-gnueabihf@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.11.24" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-arm64-gnu@npm:1.11.21" +"@swc/core-linux-arm64-gnu@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-arm64-gnu@npm:1.11.24" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-arm64-musl@npm:1.11.21" +"@swc/core-linux-arm64-musl@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-arm64-musl@npm:1.11.24" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-x64-gnu@npm:1.11.21" +"@swc/core-linux-x64-gnu@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-x64-gnu@npm:1.11.24" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-x64-musl@npm:1.11.21" +"@swc/core-linux-x64-musl@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-x64-musl@npm:1.11.24" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-win32-arm64-msvc@npm:1.11.21" +"@swc/core-win32-arm64-msvc@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-win32-arm64-msvc@npm:1.11.24" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-win32-ia32-msvc@npm:1.11.21" +"@swc/core-win32-ia32-msvc@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-win32-ia32-msvc@npm:1.11.24" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-win32-x64-msvc@npm:1.11.21" +"@swc/core-win32-x64-msvc@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-win32-x64-msvc@npm:1.11.24" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.11.21 - resolution: "@swc/core@npm:1.11.21" + version: 1.11.24 + resolution: "@swc/core@npm:1.11.24" dependencies: - "@swc/core-darwin-arm64": "npm:1.11.21" - "@swc/core-darwin-x64": "npm:1.11.21" - "@swc/core-linux-arm-gnueabihf": "npm:1.11.21" - "@swc/core-linux-arm64-gnu": "npm:1.11.21" - "@swc/core-linux-arm64-musl": "npm:1.11.21" - "@swc/core-linux-x64-gnu": "npm:1.11.21" - "@swc/core-linux-x64-musl": "npm:1.11.21" - "@swc/core-win32-arm64-msvc": "npm:1.11.21" - "@swc/core-win32-ia32-msvc": "npm:1.11.21" - "@swc/core-win32-x64-msvc": "npm:1.11.21" + "@swc/core-darwin-arm64": "npm:1.11.24" + "@swc/core-darwin-x64": "npm:1.11.24" + "@swc/core-linux-arm-gnueabihf": "npm:1.11.24" + "@swc/core-linux-arm64-gnu": "npm:1.11.24" + "@swc/core-linux-arm64-musl": "npm:1.11.24" + "@swc/core-linux-x64-gnu": "npm:1.11.24" + "@swc/core-linux-x64-musl": "npm:1.11.24" + "@swc/core-win32-arm64-msvc": "npm:1.11.24" + "@swc/core-win32-ia32-msvc": "npm:1.11.24" + "@swc/core-win32-x64-msvc": "npm:1.11.24" "@swc/counter": "npm:^0.1.3" "@swc/types": "npm:^0.1.21" peerDependencies: @@ -3073,7 +3073,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/98a0f201a0a4aa026b0b07c61c8da49d94d4ac3b059b466416c90b9b2cb4f457d836ae55ccfe90b0a89c7bdde36526ba5b7747c4e616c0d556c733e3728e9dd4 + checksum: 10/0b3e883f8a5652a7ab221a777386ccc8a65fc5b53d533bad15b703b22984eb3b449efd907b1872263f1a9990a9a50612f3c6deb619894a43f03cd974ec9bd1b7 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 6d4aa9e768..9d140c53c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19323,90 +19323,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-darwin-arm64@npm:1.11.21" +"@swc/core-darwin-arm64@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-darwin-arm64@npm:1.11.24" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-darwin-x64@npm:1.11.21" +"@swc/core-darwin-x64@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-darwin-x64@npm:1.11.24" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.11.21" +"@swc/core-linux-arm-gnueabihf@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.11.24" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-arm64-gnu@npm:1.11.21" +"@swc/core-linux-arm64-gnu@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-arm64-gnu@npm:1.11.24" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-arm64-musl@npm:1.11.21" +"@swc/core-linux-arm64-musl@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-arm64-musl@npm:1.11.24" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-x64-gnu@npm:1.11.21" +"@swc/core-linux-x64-gnu@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-x64-gnu@npm:1.11.24" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-linux-x64-musl@npm:1.11.21" +"@swc/core-linux-x64-musl@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-linux-x64-musl@npm:1.11.24" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-win32-arm64-msvc@npm:1.11.21" +"@swc/core-win32-arm64-msvc@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-win32-arm64-msvc@npm:1.11.24" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-win32-ia32-msvc@npm:1.11.21" +"@swc/core-win32-ia32-msvc@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-win32-ia32-msvc@npm:1.11.24" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.11.21": - version: 1.11.21 - resolution: "@swc/core-win32-x64-msvc@npm:1.11.21" +"@swc/core-win32-x64-msvc@npm:1.11.24": + version: 1.11.24 + resolution: "@swc/core-win32-x64-msvc@npm:1.11.24" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.10.8, @swc/core@npm:^1.3.46": - version: 1.11.21 - resolution: "@swc/core@npm:1.11.21" + version: 1.11.24 + resolution: "@swc/core@npm:1.11.24" dependencies: - "@swc/core-darwin-arm64": "npm:1.11.21" - "@swc/core-darwin-x64": "npm:1.11.21" - "@swc/core-linux-arm-gnueabihf": "npm:1.11.21" - "@swc/core-linux-arm64-gnu": "npm:1.11.21" - "@swc/core-linux-arm64-musl": "npm:1.11.21" - "@swc/core-linux-x64-gnu": "npm:1.11.21" - "@swc/core-linux-x64-musl": "npm:1.11.21" - "@swc/core-win32-arm64-msvc": "npm:1.11.21" - "@swc/core-win32-ia32-msvc": "npm:1.11.21" - "@swc/core-win32-x64-msvc": "npm:1.11.21" + "@swc/core-darwin-arm64": "npm:1.11.24" + "@swc/core-darwin-x64": "npm:1.11.24" + "@swc/core-linux-arm-gnueabihf": "npm:1.11.24" + "@swc/core-linux-arm64-gnu": "npm:1.11.24" + "@swc/core-linux-arm64-musl": "npm:1.11.24" + "@swc/core-linux-x64-gnu": "npm:1.11.24" + "@swc/core-linux-x64-musl": "npm:1.11.24" + "@swc/core-win32-arm64-msvc": "npm:1.11.24" + "@swc/core-win32-ia32-msvc": "npm:1.11.24" + "@swc/core-win32-x64-msvc": "npm:1.11.24" "@swc/counter": "npm:^0.1.3" "@swc/types": "npm:^0.1.21" peerDependencies: @@ -19435,7 +19435,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/98a0f201a0a4aa026b0b07c61c8da49d94d4ac3b059b466416c90b9b2cb4f457d836ae55ccfe90b0a89c7bdde36526ba5b7747c4e616c0d556c733e3728e9dd4 + checksum: 10/0b3e883f8a5652a7ab221a777386ccc8a65fc5b53d533bad15b703b22984eb3b449efd907b1872263f1a9990a9a50612f3c6deb619894a43f03cd974ec9bd1b7 languageName: node linkType: hard @@ -19456,15 +19456,15 @@ __metadata: linkType: hard "@swc/jest@npm:^0.2.22": - version: 0.2.37 - resolution: "@swc/jest@npm:0.2.37" + version: 0.2.38 + resolution: "@swc/jest@npm:0.2.38" dependencies: "@jest/create-cache-key-function": "npm:^29.7.0" "@swc/counter": "npm:^0.1.3" jsonc-parser: "npm:^3.2.0" peerDependencies: "@swc/core": "*" - checksum: 10/bbec37079b4f5c1ff1c95aeec07d08277c646a0c5e16e057ea3a8fe5c6e2bd59bbfc4312e53ddd05d25fa4de20a03607be274f560f28bb5e229dd08124780e16 + checksum: 10/3aaf557425e806890ebefea35334b7795e9f8ddf6f82d634d865ef917333cca4208190af1a9610c134c0e3b7a6a1aea4ec77a659e3ca5965be7aace65ce80c97 languageName: node linkType: hard From e0cc70195679595d7f023ad1ab7c06fe908feda5 Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Wed, 30 Apr 2025 10:54:00 -0700 Subject: [PATCH 028/143] review suggestion Signed-off-by: Reyna Nikolayev --- .../home/src/homePageComponents/QuickStart/Content.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx index 2047a158a6..b923970888 100644 --- a/plugins/home/src/homePageComponents/QuickStart/Content.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -33,7 +33,9 @@ export type QuickStartCardProps = { docsLinkTitle?: string | JSX.Element; /** The link to docs */ docsLink?: string; - /** The video to play on the card */ + /** The video to play on the card + * @deprecated This will be removed in the future, please use `additionalContent` instead + */ video?: JSX.Element; /** Additional card content */ additionalContent?: JSX.Element; @@ -80,8 +82,8 @@ export const Content = (props: QuickStartCardProps): JSX.Element => { - {props.video && props.video} - {props.additionalContent && props.additionalContent} + {(props.additionalContent && props.additionalContent) || + (props.video && props.video)} ); }; From aed026bd06b25af7bac3b038be899bc436caa4e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:23:29 +0000 Subject: [PATCH 029/143] chore(deps): update dependency shx to ^0.4.0 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 15036733a7..41caae91c9 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,7 @@ "node-gyp": "^10.0.0", "prettier": "^2.2.1", "semver": "^7.5.3", - "shx": "^0.3.2", + "shx": "^0.4.0", "sloc": "^0.3.1", "sort-package-json": "^2.8.0", "typedoc": "^0.27.6", diff --git a/yarn.lock b/yarn.lock index f1758b7775..755a4dc689 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31396,7 +31396,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7": +"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -43837,7 +43837,7 @@ __metadata: node-gyp: "npm:^10.0.0" prettier: "npm:^2.2.1" semver: "npm:^7.5.3" - shx: "npm:^0.3.2" + shx: "npm:^0.4.0" sloc: "npm:^0.3.1" sort-package-json: "npm:^2.8.0" typedoc: "npm:^0.27.6" @@ -44459,16 +44459,17 @@ __metadata: languageName: node linkType: hard -"shelljs@npm:^0.8.5": - version: 0.8.5 - resolution: "shelljs@npm:0.8.5" +"shelljs@npm:^0.9.2": + version: 0.9.2 + resolution: "shelljs@npm:0.9.2" dependencies: - glob: "npm:^7.0.0" + execa: "npm:^1.0.0" + fast-glob: "npm:^3.3.2" interpret: "npm:^1.0.0" rechoir: "npm:^0.6.2" bin: shjs: bin/shjs - checksum: 10/f2178274b97b44332bbe9ddb78161137054f55ecf701c7a99db9552cb5478fe279ad5f5131d8a7c2f0730e01ccf0c629d01094143f0541962ce1a3d0243d23f7 + checksum: 10/d264239d4b5f2cb075270a8de5f6c8f8ace1c8320efc8fa05b9a0c94bd9cb8aabb296f4942772b2c225d32431ead0b45a40861b2be5ace9f0d09b50d6a5261cd languageName: node linkType: hard @@ -44489,15 +44490,15 @@ __metadata: languageName: node linkType: hard -"shx@npm:^0.3.2": - version: 0.3.4 - resolution: "shx@npm:0.3.4" +"shx@npm:^0.4.0": + version: 0.4.0 + resolution: "shx@npm:0.4.0" dependencies: - minimist: "npm:^1.2.3" - shelljs: "npm:^0.8.5" + minimist: "npm:^1.2.8" + shelljs: "npm:^0.9.2" bin: shx: lib/cli.js - checksum: 10/5271b60f7e322540799102ad6935121f10c857a995a1321357a7bffd1628674a4758a602153dc5cc126d8dc94d3489586587d3dee54dc3cac0222ca08a78e33a + checksum: 10/8df78b1f2e099de11d4ed44846878cb811cee02b40a08232302d59a8cb130e7be8ef71698e70e0984c345202bab39c35d5e0202cc0f0d0ea7b0d0501fb81ac00 languageName: node linkType: hard From 2a292db5b22b99079fafdf8ea7526d42067927fb Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Thu, 1 May 2025 11:42:10 -0400 Subject: [PATCH 030/143] add filter support for EntityContextMenuItemBlueprint Signed-off-by: Mark Dunphy --- .../alpha/blueprints/EntityContextMenuItemBlueprint.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx index f43dd6a6d9..cf3a640e37 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx @@ -24,7 +24,8 @@ import MenuItem from '@material-ui/core/MenuItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import { useEntityContextMenu } from '../../hooks/useEntityContextMenu'; - +import type { Entity } from '@backstage/catalog-model'; +import { useEntity } from '../../hooks/useEntity'; /** @alpha */ export type UseProps = () => | { @@ -42,6 +43,7 @@ export type UseProps = () => export type EntityContextMenuItemParams = { useProps: UseProps; icon: JSX.Element; + filter?: (entity: Entity) => boolean; }; /** @alpha */ @@ -53,6 +55,7 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ const loader = async () => { const Component = () => { const { onMenuClose } = useEntityContextMenu(); + const { entity } = useEntity(); const { title, ...menuItemProps } = params.useProps(); let handleClick = undefined; @@ -67,6 +70,10 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ }; } + if (entity && params.filter && !params.filter(entity)) { + return null; + } + return ( {params.icon} From b04f874aba3c0111792635e7c66ce18e19dd610a Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Thu, 1 May 2025 12:10:09 -0400 Subject: [PATCH 031/143] add tests for filtering Signed-off-by: Mark Dunphy --- .../EntityContextMenuItemBlueprint.test.tsx | 72 +++++++++++++++++++ .../EntityContextMenuItemBlueprint.tsx | 1 + 2 files changed, 73 insertions(+) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 3bdfc00db7..b6e0f6d8ef 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -13,7 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { + createExtensionTester, + renderInTestApp, + TestApiProvider, +} from '@backstage/frontend-test-utils'; import { EntityContextMenuItemBlueprint } from './EntityContextMenuItemBlueprint'; +import { screen, waitFor } from '@testing-library/react'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; + +jest.mock('../../hooks/useEntityContextMenu', () => ({ + useEntityContextMenu: () => ({ + onMenuClose: jest.fn(), + }), +})); describe('EntityContextMenuItemBlueprint', () => { const data = [ @@ -64,4 +77,63 @@ describe('EntityContextMenuItemBlueprint', () => { } `); }); + + it('should filter items based on the filter function', async () => { + const extension = EntityContextMenuItemBlueprint.make({ + name: 'test', + params: { + icon: Icon, + filter: e => e.kind.toLowerCase() === 'component', + useProps: () => ({ + title: 'Test', + onClick: () => {}, + }), + }, + }); + + renderInTestApp( + +
    {createExtensionTester(extension).reactElement()}
+
, + ); + + await waitFor(() => { + expect(screen.queryByText('Test')).not.toBeInTheDocument(); + }); + }); + + it('should render a menu item', async () => { + const extension = EntityContextMenuItemBlueprint.make({ + name: 'test', + params: { + icon: Icon, + useProps: () => ({ + title: 'Test', + onClick: () => {}, + }), + }, + }); + + renderInTestApp( + +
    {createExtensionTester(extension).reactElement()}
+
, + ); + + await waitFor(() => { + expect(screen.getByText('Test')).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx index cf3a640e37..d2ce2b3cce 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx @@ -26,6 +26,7 @@ import ListItemText from '@material-ui/core/ListItemText'; import { useEntityContextMenu } from '../../hooks/useEntityContextMenu'; import type { Entity } from '@backstage/catalog-model'; import { useEntity } from '../../hooks/useEntity'; + /** @alpha */ export type UseProps = () => | { From b1edfe2d60070631e2c9e3539cb1ae62c7f48162 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Thu, 1 May 2025 13:33:58 -0400 Subject: [PATCH 032/143] add api reports Signed-off-by: Mark Dunphy --- plugins/catalog-react/report-alpha.api.md | 1 + .../src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index d5f85b7836..f69bbe476d 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -343,6 +343,7 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ export type EntityContextMenuItemParams = { useProps: UseProps; icon: JSX_2.Element; + filter?: (entity: Entity) => boolean; }; // @alpha (undocumented) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index b6e0f6d8ef..5a272c33ca 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -16,7 +16,6 @@ import { createExtensionTester, renderInTestApp, - TestApiProvider, } from '@backstage/frontend-test-utils'; import { EntityContextMenuItemBlueprint } from './EntityContextMenuItemBlueprint'; import { screen, waitFor } from '@testing-library/react'; From 2ddbc50dbc26dd10fa361bb76746d85b8d8b83a2 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Thu, 1 May 2025 13:36:21 -0400 Subject: [PATCH 033/143] add changeset Signed-off-by: Mark Dunphy --- .changeset/orange-women-fry.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/orange-women-fry.md diff --git a/.changeset/orange-women-fry.md b/.changeset/orange-women-fry.md new file mode 100644 index 0000000000..14474fd23e --- /dev/null +++ b/.changeset/orange-women-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +A new `filter` param has been added to the EntityContextMenuItemBlueprint to make it easier to determine if a menu item should appear for a given entity. The `filter` param is a function which accepts an entity and returns a boolean. From 2768e8a8e36b62b2f4a6af4fe215dd38e8efd80c Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Thu, 1 May 2025 13:37:17 -0400 Subject: [PATCH 034/143] changeset update Signed-off-by: Mark Dunphy --- .changeset/orange-women-fry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/orange-women-fry.md b/.changeset/orange-women-fry.md index 14474fd23e..681d75c875 100644 --- a/.changeset/orange-women-fry.md +++ b/.changeset/orange-women-fry.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-react': patch --- -A new `filter` param has been added to the EntityContextMenuItemBlueprint to make it easier to determine if a menu item should appear for a given entity. The `filter` param is a function which accepts an entity and returns a boolean. +A new `filter` parameter has been added to `EntityContextMenuItemBlueprint` to make it easier to configure which entities a menu item should appear for. The `filter` parameter is a function which accepts an entity and returns a boolean. From af9f453c5f9b7456d45ca23f8234e8616581fcf4 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Thu, 1 May 2025 13:48:54 -0400 Subject: [PATCH 035/143] add extra test case Signed-off-by: Mark Dunphy --- .../EntityContextMenuItemBlueprint.test.tsx | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 5a272c33ca..81272de8b4 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -77,7 +77,7 @@ describe('EntityContextMenuItemBlueprint', () => { `); }); - it('should filter items based on the filter function', async () => { + it('should exclude items based on the filter function', async () => { const extension = EntityContextMenuItemBlueprint.make({ name: 'test', params: { @@ -107,6 +107,36 @@ describe('EntityContextMenuItemBlueprint', () => { }); }); + it('should include items based on the filter function', async () => { + const extension = EntityContextMenuItemBlueprint.make({ + name: 'test', + params: { + icon: Icon, + filter: e => e.kind.toLowerCase() === 'component', + useProps: () => ({ + title: 'Test', + onClick: () => {}, + }), + }, + }); + + renderInTestApp( + +
    {createExtensionTester(extension).reactElement()}
+
, + ); + + await waitFor(() => { + expect(screen.getByText('Test')).toBeInTheDocument(); + }); + }); + it('should render a menu item', async () => { const extension = EntityContextMenuItemBlueprint.make({ name: 'test', From af0ab1cb788287cf645a5874796e2b375ace6b9d Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Fri, 2 May 2025 10:32:24 -0400 Subject: [PATCH 036/143] relocate buildFilterFn and FilterWrapper to catalog-react from catalog Signed-off-by: Mark Dunphy --- .../src/alpha/filter/FilterWrapper.tsx | 10 +++++++--- .../src/alpha/filter/matchers/createHasMatcher.test.ts | 0 .../src/alpha/filter/matchers/createHasMatcher.ts | 0 .../src/alpha/filter/matchers/createIsMatcher.test.ts | 0 .../src/alpha/filter/matchers/createIsMatcher.ts | 0 .../alpha/filter/matchers/createKindMatcher.test.ts | 0 .../src/alpha/filter/matchers/createKindMatcher.ts | 0 .../alpha/filter/matchers/createTypeMatcher.test.ts | 0 .../src/alpha/filter/matchers/createTypeMatcher.ts | 0 .../src/alpha/filter/matchers/types.ts | 0 .../src/alpha/filter/parseFilterExpression.test.ts | 0 .../src/alpha/filter/parseFilterExpression.ts | 0 plugins/catalog-react/src/alpha/index.ts | 1 + plugins/catalog/src/alpha/entityContents.tsx | 2 +- plugins/catalog/src/alpha/pages.tsx | 2 +- 15 files changed, 10 insertions(+), 5 deletions(-) rename plugins/{catalog => catalog-react}/src/alpha/filter/FilterWrapper.tsx (94%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createHasMatcher.test.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createHasMatcher.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createIsMatcher.test.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createIsMatcher.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createKindMatcher.test.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createKindMatcher.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createTypeMatcher.test.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/createTypeMatcher.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/matchers/types.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/parseFilterExpression.test.ts (100%) rename plugins/{catalog => catalog-react}/src/alpha/filter/parseFilterExpression.ts (100%) diff --git a/plugins/catalog/src/alpha/filter/FilterWrapper.tsx b/plugins/catalog-react/src/alpha/filter/FilterWrapper.tsx similarity index 94% rename from plugins/catalog/src/alpha/filter/FilterWrapper.tsx rename to plugins/catalog-react/src/alpha/filter/FilterWrapper.tsx index 33af9c2c3f..76ee69b087 100644 --- a/plugins/catalog/src/alpha/filter/FilterWrapper.tsx +++ b/plugins/catalog-react/src/alpha/filter/FilterWrapper.tsx @@ -24,9 +24,13 @@ import { parseFilterExpression } from './parseFilterExpression'; const seenParseErrorExpressionStrings = new Set(); const seenDuplicateExpressionStrings = new Set(); -// Given an optional filter function and an optional filter expression, make -// sure that at most one of them was given, and return a filter function that -// does the right thing. +/** + * Given an optional filter function and an optional filter expression, make + * sure that at most one of them was given, and return a filter function that + * does the right thing. + * + * @alpha + */ export function buildFilterFn( filterFunction?: (entity: Entity) => boolean, filterExpression?: string, diff --git a/plugins/catalog/src/alpha/filter/matchers/createHasMatcher.test.ts b/plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.test.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createHasMatcher.test.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.test.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createHasMatcher.ts b/plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createHasMatcher.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createIsMatcher.test.ts b/plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.test.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createIsMatcher.test.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.test.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createIsMatcher.ts b/plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createIsMatcher.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createKindMatcher.test.ts b/plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.test.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createKindMatcher.test.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.test.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createKindMatcher.ts b/plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createKindMatcher.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.test.ts b/plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.test.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.test.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.test.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.ts b/plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.ts rename to plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.ts diff --git a/plugins/catalog/src/alpha/filter/matchers/types.ts b/plugins/catalog-react/src/alpha/filter/matchers/types.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/matchers/types.ts rename to plugins/catalog-react/src/alpha/filter/matchers/types.ts diff --git a/plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts b/plugins/catalog-react/src/alpha/filter/parseFilterExpression.test.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts rename to plugins/catalog-react/src/alpha/filter/parseFilterExpression.test.ts diff --git a/plugins/catalog/src/alpha/filter/parseFilterExpression.ts b/plugins/catalog-react/src/alpha/filter/parseFilterExpression.ts similarity index 100% rename from plugins/catalog/src/alpha/filter/parseFilterExpression.ts rename to plugins/catalog-react/src/alpha/filter/parseFilterExpression.ts diff --git a/plugins/catalog-react/src/alpha/index.ts b/plugins/catalog-react/src/alpha/index.ts index 4ff4dbf0dd..f1b8b05c62 100644 --- a/plugins/catalog-react/src/alpha/index.ts +++ b/plugins/catalog-react/src/alpha/index.ts @@ -20,3 +20,4 @@ export * from './predicates'; export { catalogReactTranslationRef } from '../translation'; export { isOwnerOf } from '../utils/isOwnerOf'; export { useEntityPermission } from '../hooks/useEntityPermission'; +export { buildFilterFn } from './filter/FilterWrapper'; diff --git a/plugins/catalog/src/alpha/entityContents.tsx b/plugins/catalog/src/alpha/entityContents.tsx index 165ed33e04..224557519e 100644 --- a/plugins/catalog/src/alpha/entityContents.tsx +++ b/plugins/catalog/src/alpha/entityContents.tsx @@ -26,7 +26,7 @@ import { EntityContentLayoutBlueprint, EntityContentLayoutProps, } from '@backstage/plugin-catalog-react/alpha'; -import { buildFilterFn } from './filter/FilterWrapper'; +import { buildFilterFn } from '@backstage/plugin-catalog-react/alpha'; import { useEntity } from '@backstage/plugin-catalog-react'; export const catalogOverviewEntityContent = diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index b39fe510e6..f822cb0fed 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -31,10 +31,10 @@ import { EntityHeaderBlueprint, EntityContentBlueprint, defaultEntityContentGroups, + buildFilterFn, } from '@backstage/plugin-catalog-react/alpha'; import { rootRouteRef } from '../routes'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; -import { buildFilterFn } from './filter/FilterWrapper'; import { EntityHeader } from './components/EntityHeader'; export const catalogPage = PageBlueprint.makeWithOverrides({ From f001924d8487cbeb0186f396f5e19faa731b73e4 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Fri, 2 May 2025 12:11:12 -0400 Subject: [PATCH 037/143] filter menu items by entity predicate, filter string, or function Signed-off-by: Mark Dunphy --- .../EntityContextMenuItemBlueprint.test.tsx | 267 ++++++++++++++---- .../EntityContextMenuItemBlueprint.tsx | 41 ++- 2 files changed, 249 insertions(+), 59 deletions(-) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 81272de8b4..694e79bb8c 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -20,6 +20,7 @@ import { import { EntityContextMenuItemBlueprint } from './EntityContextMenuItemBlueprint'; import { screen, waitFor } from '@testing-library/react'; import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { Entity } from '@backstage/catalog-model'; jest.mock('../../hooks/useEntityContextMenu', () => ({ useEntityContextMenu: () => ({ @@ -47,6 +48,25 @@ describe('EntityContextMenuItemBlueprint', () => { }, ]; + const filterTestCases = [ + { + params: { filter: 'kind:component' }, + config: undefined, + }, + { + params: { filter: (e: Entity) => e.kind.toLowerCase() === 'component' }, + config: undefined, + }, + { + params: {}, + config: { filter: 'kind:component' }, + }, + { + params: {}, + config: { filter: { kind: 'component' } }, + }, + ]; + it.each(data)('should return an extension with sane defaults', params => { const extension = EntityContextMenuItemBlueprint.make({ name: 'test', @@ -61,7 +81,138 @@ describe('EntityContextMenuItemBlueprint', () => { "id": "page:catalog/entity", "input": "contextMenuItems", }, - "configSchema": undefined, + "configSchema": { + "parse": [Function], + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "filter": { + "anyOf": [ + { + "type": "string", + }, + { + "anyOf": [ + { + "anyOf": [ + { + "type": [ + "string", + "number", + "boolean", + ], + }, + { + "items": { + "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", + }, + "type": "array", + }, + ], + }, + { + "additionalProperties": false, + "properties": { + "$all": { + "items": { + "$ref": "#/properties/filter/anyOf/1", + }, + "type": "array", + }, + }, + "required": [ + "$all", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$any": { + "items": { + "$ref": "#/properties/filter/anyOf/1", + }, + "type": "array", + }, + }, + "required": [ + "$any", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$not": { + "$ref": "#/properties/filter/anyOf/1", + }, + }, + "required": [ + "$not", + ], + "type": "object", + }, + { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/properties/filter/anyOf/1/anyOf/0", + }, + { + "additionalProperties": false, + "properties": { + "$exists": { + "type": "boolean", + }, + }, + "required": [ + "$exists", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$in": { + "items": { + "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", + }, + "type": "array", + }, + }, + "required": [ + "$in", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$contains": { + "$ref": "#/properties/filter/anyOf/1", + }, + }, + "required": [ + "$contains", + ], + "type": "object", + }, + ], + }, + "propertyNames": { + "pattern": "^(?!\\$).*$", + }, + "type": "object", + }, + ], + }, + ], + }, + }, + "type": "object", + }, + }, "disabled": false, "factory": [Function], "inputs": {}, @@ -77,65 +228,71 @@ describe('EntityContextMenuItemBlueprint', () => { `); }); - it('should exclude items based on the filter function', async () => { - const extension = EntityContextMenuItemBlueprint.make({ - name: 'test', - params: { - icon: Icon, - filter: e => e.kind.toLowerCase() === 'component', - useProps: () => ({ - title: 'Test', - onClick: () => {}, - }), - }, - }); + it.each(filterTestCases)( + 'should exclude items based on the filter', + async ({ params, config }) => { + const extension = EntityContextMenuItemBlueprint.make({ + name: 'test', + params: { + icon: Icon, + ...params, + useProps: () => ({ + title: 'Test', + onClick: () => {}, + }), + }, + }); - renderInTestApp( - -
    {createExtensionTester(extension).reactElement()}
-
, - ); + renderInTestApp( + +
    {createExtensionTester(extension, { config }).reactElement()}
+
, + ); - await waitFor(() => { - expect(screen.queryByText('Test')).not.toBeInTheDocument(); - }); - }); + await waitFor(() => { + expect(screen.queryByText('Test')).not.toBeInTheDocument(); + }); + }, + ); - it('should include items based on the filter function', async () => { - const extension = EntityContextMenuItemBlueprint.make({ - name: 'test', - params: { - icon: Icon, - filter: e => e.kind.toLowerCase() === 'component', - useProps: () => ({ - title: 'Test', - onClick: () => {}, - }), - }, - }); + it.each(filterTestCases)( + 'should include items based on the filter', + async ({ params, config }) => { + const extension = EntityContextMenuItemBlueprint.make({ + name: 'test', + params: { + icon: Icon, + ...params, + useProps: () => ({ + title: 'Test', + onClick: () => {}, + }), + }, + }); - renderInTestApp( - -
    {createExtensionTester(extension).reactElement()}
-
, - ); + renderInTestApp( + +
    {createExtensionTester(extension, { config }).reactElement()}
+
, + ); - await waitFor(() => { - expect(screen.getByText('Test')).toBeInTheDocument(); - }); - }); + await waitFor(() => { + expect(screen.getByText('Test')).toBeInTheDocument(); + }); + }, + ); it('should render a menu item', async () => { const extension = EntityContextMenuItemBlueprint.make({ diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx index d2ce2b3cce..acc3ddbc48 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx @@ -24,9 +24,16 @@ import MenuItem from '@material-ui/core/MenuItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import { useEntityContextMenu } from '../../hooks/useEntityContextMenu'; +import { EntityPredicate } from '../predicates'; import type { Entity } from '@backstage/catalog-model'; import { useEntity } from '../../hooks/useEntity'; - +import { + entityFilterExpressionDataRef, + entityFilterFunctionDataRef, +} from './extensionData'; +import { createEntityPredicateSchema } from '../predicates/createEntityPredicateSchema'; +import { resolveEntityFilterData } from './resolveEntityFilterData'; +import { buildFilterFn } from '../filter/FilterWrapper'; /** @alpha */ export type UseProps = () => | { @@ -44,7 +51,7 @@ export type UseProps = () => export type EntityContextMenuItemParams = { useProps: UseProps; icon: JSX.Element; - filter?: (entity: Entity) => boolean; + filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; /** @alpha */ @@ -52,7 +59,33 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ kind: 'entity-context-menu-item', attachTo: { id: 'page:catalog/entity', input: 'contextMenuItems' }, output: [coreExtensionData.reactElement], - *factory(params: EntityContextMenuItemParams, { node }) { + config: { + schema: { + filter: z => + z.union([z.string(), createEntityPredicateSchema(z)]).optional(), + }, + }, + *factory(params: EntityContextMenuItemParams, { node, config }) { + const resolvedFilterData = []; + + for (const resolved of resolveEntityFilterData( + params.filter, + config, + node, + )) { + resolvedFilterData.push(resolved); + } + + const resolvedFilter = resolvedFilterData.pop(); + const filter = buildFilterFn( + resolvedFilter?.id === entityFilterFunctionDataRef.id + ? resolvedFilter.value + : undefined, + resolvedFilter?.id === entityFilterExpressionDataRef.id + ? resolvedFilter.value + : undefined, + ); + const loader = async () => { const Component = () => { const { onMenuClose } = useEntityContextMenu(); @@ -71,7 +104,7 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ }; } - if (entity && params.filter && !params.filter(entity)) { + if (entity && !filter(entity)) { return null; } From 5fe55c90d3c724c9f6edd27abed3194fe76877a7 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Fri, 2 May 2025 12:27:35 -0400 Subject: [PATCH 038/143] api reports + changeset Signed-off-by: Mark Dunphy --- .changeset/orange-women-fry.md | 1 + plugins/catalog-react/report-alpha.api.md | 16 ++++++++++++--- plugins/catalog/report-alpha.api.md | 24 +++++++++++++++++------ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/.changeset/orange-women-fry.md b/.changeset/orange-women-fry.md index 681d75c875..493a1aed57 100644 --- a/.changeset/orange-women-fry.md +++ b/.changeset/orange-women-fry.md @@ -1,5 +1,6 @@ --- '@backstage/plugin-catalog-react': patch +'@backstage/plugin-catalog': patch --- A new `filter` parameter has been added to `EntityContextMenuItemBlueprint` to make it easier to configure which entities a menu item should appear for. The `filter` parameter is a function which accepts an entity and returns a boolean. diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index f69bbe476d..595741ab67 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -16,6 +16,12 @@ import { ResourcePermission } from '@backstage/plugin-permission-common'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; +// @alpha +export function buildFilterFn( + filterFunction?: (entity: Entity) => boolean, + filterExpression?: string, +): (entity: Entity) => boolean; + // @alpha export const CatalogFilterBlueprint: ExtensionBlueprint<{ kind: 'catalog-filter'; @@ -334,8 +340,12 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ params: EntityContextMenuItemParams; output: ConfigurableExtensionDataRef; inputs: {}; - config: {}; - configInput: {}; + config: { + filter: EntityPredicate | undefined; + }; + configInput: { + filter?: EntityPredicate | undefined; + }; dataRefs: never; }>; @@ -343,7 +353,7 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ export type EntityContextMenuItemParams = { useProps: UseProps; icon: JSX_2.Element; - filter?: (entity: Entity) => boolean; + filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; // @alpha (undocumented) diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index 54d4187536..246c7929f0 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -863,8 +863,12 @@ const _default: FrontendPlugin< 'entity-context-menu-item:catalog/copy-entity-url': ExtensionDefinition<{ kind: 'entity-context-menu-item'; name: 'copy-entity-url'; - config: {}; - configInput: {}; + config: { + filter: EntityPredicate | undefined; + }; + configInput: { + filter?: EntityPredicate | undefined; + }; output: ConfigurableExtensionDataRef< JSX_2.Element, 'core.reactElement', @@ -876,8 +880,12 @@ const _default: FrontendPlugin< 'entity-context-menu-item:catalog/inspect-entity': ExtensionDefinition<{ kind: 'entity-context-menu-item'; name: 'inspect-entity'; - config: {}; - configInput: {}; + config: { + filter: EntityPredicate | undefined; + }; + configInput: { + filter?: EntityPredicate | undefined; + }; output: ConfigurableExtensionDataRef< JSX_2.Element, 'core.reactElement', @@ -889,8 +897,12 @@ const _default: FrontendPlugin< 'entity-context-menu-item:catalog/unregister-entity': ExtensionDefinition<{ kind: 'entity-context-menu-item'; name: 'unregister-entity'; - config: {}; - configInput: {}; + config: { + filter: EntityPredicate | undefined; + }; + configInput: { + filter?: EntityPredicate | undefined; + }; output: ConfigurableExtensionDataRef< JSX_2.Element, 'core.reactElement', From eddd96c62b5c93e8763fb60f74348b68ae0b26d0 Mon Sep 17 00:00:00 2001 From: gerson Date: Sun, 4 May 2025 10:44:30 +0200 Subject: [PATCH 039/143] Adding title prop to customHomePage Signed-off-by: gerson --- .changeset/honest-states-repeat.md | 6 + packages/app/src/App.tsx | 21 ++- .../components/home/CustomizableHomePage.tsx | 94 ++++++++++++ packages/app/src/components/home/HomePage.tsx | 135 ++++++++++-------- packages/app/src/components/home/shared.tsx | 59 ++++++++ plugins/home/README.md | 3 + plugins/home/report.api.md | 1 + .../CustomHomepage/CustomHomepageGrid.tsx | 2 +- .../src/components/CustomHomepage/types.ts | 4 + 9 files changed, 257 insertions(+), 68 deletions(-) create mode 100644 .changeset/honest-states-repeat.md create mode 100644 packages/app/src/components/home/CustomizableHomePage.tsx create mode 100644 packages/app/src/components/home/shared.tsx diff --git a/.changeset/honest-states-repeat.md b/.changeset/honest-states-repeat.md new file mode 100644 index 0000000000..99d094b4c1 --- /dev/null +++ b/.changeset/honest-states-repeat.md @@ -0,0 +1,6 @@ +--- +'example-app': minor +'@backstage/plugin-home': minor +--- + +Added optional title prop to customHomePageGrid and improved the example app homepage to add the custom one diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 3927992fd4..5ac9052d2a 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -27,7 +27,7 @@ import { RELATION_PROVIDES_API, } from '@backstage/catalog-model'; import { createApp } from '@backstage/app-defaults'; -import { AppRouter, FlatRoutes } from '@backstage/core-app-api'; +import { AppRouter, FeatureFlagged, FlatRoutes } from '@backstage/core-app-api'; import { AlertDisplay, OAuthRequestDialog, @@ -66,7 +66,6 @@ import AlarmIcon from '@material-ui/icons/Alarm'; import { Navigate, Route } from 'react-router-dom'; import { apis } from './apis'; import { entityPage } from './components/catalog/EntityPage'; -import { homePage } from './components/home/HomePage'; import { Root } from './components/Root'; import { DelayingComponentFieldExtension } from './components/scaffolder/customScaffolderExtensions'; import { defaultPreviewTemplate } from './components/scaffolder/defaultPreviewTemplate'; @@ -84,6 +83,8 @@ import { NotificationsPage, UserNotificationSettingsCard, } from '@backstage/plugin-notifications'; +import { CustomizableHomePage } from './components/home/CustomizableHomePage'; +import { HomePage } from './components/home/HomePage'; const app = createApp({ apis, @@ -115,10 +116,20 @@ const app = createApp({ const routes = ( } /> + {/* TODO(rubenl): Move this to / once its more mature and components exist */} - }> - {homePage} - + + + }> + + + + + }> + + + + } diff --git a/packages/app/src/components/home/CustomizableHomePage.tsx b/packages/app/src/components/home/CustomizableHomePage.tsx new file mode 100644 index 0000000000..8998538e54 --- /dev/null +++ b/packages/app/src/components/home/CustomizableHomePage.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Page, Content } from '@backstage/core-components'; +import { + HomePageCompanyLogo, + TemplateBackstageLogo, + HomePageStarredEntities, + HomePageToolkit, + CustomHomepageGrid, + HomePageRandomJoke, + HomePageTopVisited, + HomePageRecentlyVisited, +} from '@backstage/plugin-home'; +import { HomePageSearchBar } from '@backstage/plugin-search'; +import Grid from '@material-ui/core/Grid'; + +import { tools, useLogoStyles } from './shared'; + +const defaultConfig = [ + { + component: 'HomePageSearchBar', + x: 0, + y: 0, + width: 24, + height: 2, + }, + { + component: 'HomePageRecentlyVisited', + x: 0, + y: 1, + width: 5, + height: 4, + }, + { + component: 'HomePageTopVisited', + x: 5, + y: 1, + width: 5, + height: 4, + }, + { + component: 'HomePageStarredEntities', + x: 0, + y: 2, + width: 6, + height: 4, + }, + { + component: 'HomePageToolkit', + x: 6, + y: 6, + width: 4, + height: 4, + }, +]; + +export const CustomizableHomePage = () => { + const { svg, path, container } = useLogoStyles(); + + return ( + + + + } + /> + + + + + + + + + + + + + ); +}; diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index f0f49ab34e..ca555280dd 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -14,21 +14,37 @@ * limitations under the License. */ +import { Page, Content, Header } from '@backstage/core-components'; import { - ClockConfig, - CustomHomepageGrid, - HeaderWorldClock, HomePageCompanyLogo, - HomePageRandomJoke, + TemplateBackstageLogo, HomePageStarredEntities, HomePageToolkit, HomePageTopVisited, HomePageRecentlyVisited, WelcomeTitle, + HeaderWorldClock, + ClockConfig, } from '@backstage/plugin-home'; -import { Content, Header, Page } from '@backstage/core-components'; import { HomePageSearchBar } from '@backstage/plugin-search'; -import HomeIcon from '@material-ui/icons/Home'; +import { SearchContextProvider } from '@backstage/plugin-search-react'; +import Grid from '@material-ui/core/Grid'; +import { makeStyles } from '@material-ui/core/styles'; + +import { tools, useLogoStyles } from './shared'; + +const useStyles = makeStyles(theme => ({ + searchBarInput: { + maxWidth: '60vw', + margin: 'auto', + backgroundColor: theme.palette.background.paper, + borderRadius: '50px', + boxShadow: theme.shadows[1], + }, + searchBarOutline: { + borderStyle: 'none', + }, +})); const clockConfigs: ClockConfig[] = [ { @@ -55,60 +71,55 @@ const timeFormat: Intl.DateTimeFormatOptions = { hour12: false, }; -const defaultConfig = [ - { - component: 'CompanyLogo', - x: 0, - y: 0, - width: 12, - height: 1, - movable: false, - resizable: false, - deletable: false, - }, - { - component: 'WelcomeTitle', - x: 0, - y: 1, - width: 12, - height: 1, - }, - { - component: 'HomePageSearchBar', - x: 0, - y: 2, - width: 12, - height: 2, - }, -]; +export const HomePage = () => { + const classes = useStyles(); + const { svg, path, container } = useLogoStyles(); -export const homePage = ( - -
} pageTitleOverride="Home"> - -
- - - - - - - - , - }, - ]} - /> - - - - -
-); + return ( + + +
} pageTitleOverride="Home"> + +
+ + + } + /> + + + + + + + + + + + + + + + + + + + + + +
+
+ ); +}; diff --git a/packages/app/src/components/home/shared.tsx b/packages/app/src/components/home/shared.tsx new file mode 100644 index 0000000000..c8b9764c83 --- /dev/null +++ b/packages/app/src/components/home/shared.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TemplateBackstageLogoIcon } from '@backstage/plugin-home'; +import { makeStyles } from '@material-ui/core/styles'; + +export const useLogoStyles = makeStyles(theme => ({ + container: { + margin: theme.spacing(5, 0), + }, + svg: { + width: 'auto', + height: 100, + }, + path: { + fill: '#7df3e1', + }, +})); + +export const tools = [ + { + url: 'https://backstage.io/docs', + label: 'Docs', + icon: , + }, + { + url: 'https://github.com/backstage/backstage', + label: 'GitHub', + icon: , + }, + { + url: 'https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md', + label: 'Contributing', + icon: , + }, + { + url: 'https://backstage.io/plugins', + label: 'Plugins Directory', + icon: , + }, + { + url: 'https://github.com/backstage/backstage/issues/new/choose', + label: 'Submit New Issue', + icon: , + }, +]; diff --git a/plugins/home/README.md b/plugins/home/README.md index 50b422a3dc..3498d6700f 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -107,6 +107,9 @@ export const homePage = ( ); ``` +> [!NOTE] +> You can provide a title to the grid by passing it as a prop: ``. This will be displayed as a header above the grid layout. + ### Creating Customizable Components The custom home page can use the default components created by using the default `createCardExtension` method but if you diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 7c7f55fd47..07e54757e6 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -89,6 +89,7 @@ export const CustomHomepageGrid: ( export type CustomHomepageGridProps = { children?: ReactNode; config?: LayoutConfiguration[]; + title?: string; rowHeight?: number; breakpoints?: Record; cols?: Record; diff --git a/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx b/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx index da55ccc5f4..675e17357e 100644 --- a/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx +++ b/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx @@ -321,7 +321,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => { return ( <> - + Date: Sun, 4 May 2025 10:59:52 +0200 Subject: [PATCH 040/143] changeset fix Signed-off-by: gerson --- .changeset/honest-states-repeat.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/honest-states-repeat.md b/.changeset/honest-states-repeat.md index 99d094b4c1..ed9523fa41 100644 --- a/.changeset/honest-states-repeat.md +++ b/.changeset/honest-states-repeat.md @@ -1,5 +1,4 @@ --- -'example-app': minor '@backstage/plugin-home': minor --- From 3f15d22e99fdc1656b3b04a1492cb594cf965e8f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 08:03:19 +0000 Subject: [PATCH 041/143] chore(deps): update dependency node-mocks-http to v1.17.2 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 c7f8e452f0..93e0e92fd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38692,8 +38692,8 @@ __metadata: linkType: hard "node-mocks-http@npm:^1.0.0": - version: 1.17.0 - resolution: "node-mocks-http@npm:1.17.0" + version: 1.17.2 + resolution: "node-mocks-http@npm:1.17.2" dependencies: accepts: "npm:^1.3.7" content-disposition: "npm:^0.5.3" @@ -38713,7 +38713,7 @@ __metadata: optional: true "@types/node": optional: true - checksum: 10/7b8e0db30df8dacc957b352e4553635ed9c212a0e307ed486b5cb93cb7653c82a8b5bbe6a99ba016e1f390b3a2f5ef9388831b6cf1a4e43f014c0070c3292df3 + checksum: 10/3ab97b5a7b2dba0032fc5090983e4ca4be0597f1c645b34dff99d465feb17ef1ee7ea4829a9b4303495399c1ac0f12f8964b878e0dda43cda798bb97254ad571 languageName: node linkType: hard From bd60e8dc313336f154a033a441eb99e3e6607e4b Mon Sep 17 00:00:00 2001 From: Gerson Date: Mon, 5 May 2025 13:08:39 +0200 Subject: [PATCH 042/143] Update .changeset/honest-states-repeat.md Co-authored-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Signed-off-by: Gerson --- .changeset/honest-states-repeat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/honest-states-repeat.md b/.changeset/honest-states-repeat.md index ed9523fa41..128952c4e2 100644 --- a/.changeset/honest-states-repeat.md +++ b/.changeset/honest-states-repeat.md @@ -2,4 +2,4 @@ '@backstage/plugin-home': minor --- -Added optional title prop to customHomePageGrid and improved the example app homepage to add the custom one +Added optional title prop to `customHomePageGrid` From cc0b16f98cb43c98abbcd363754f2321c316a43f Mon Sep 17 00:00:00 2001 From: Gerson Date: Mon, 5 May 2025 13:08:56 +0200 Subject: [PATCH 043/143] Update .changeset/honest-states-repeat.md Co-authored-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Signed-off-by: Gerson --- .changeset/honest-states-repeat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/honest-states-repeat.md b/.changeset/honest-states-repeat.md index 128952c4e2..06b459b673 100644 --- a/.changeset/honest-states-repeat.md +++ b/.changeset/honest-states-repeat.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-home': minor +'@backstage/plugin-home': patch --- Added optional title prop to `customHomePageGrid` From e4de912847a7ca1557b46a36d4abc72158c53db2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 09:21:26 +0000 Subject: [PATCH 044/143] chore(deps): update react monorepo to v18.3.21 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- canon-docs/yarn.lock | 12 ++++++------ storybook/yarn.lock | 12 ++++++------ yarn.lock | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/canon-docs/yarn.lock b/canon-docs/yarn.lock index d4049730ff..57048c9e63 100644 --- a/canon-docs/yarn.lock +++ b/canon-docs/yarn.lock @@ -932,21 +932,21 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0": - version: 18.3.6 - resolution: "@types/react-dom@npm:18.3.6" + version: 18.3.7 + resolution: "@types/react-dom@npm:18.3.7" peerDependencies: "@types/react": ^18.0.0 - checksum: 10/ae179355401c64423d39946eda22c5f7f74c94ce61c21505024d4d82c33853ec40bc9b370f75e4a7750b0524aba4d95a43fcc328d8d14684dc2abb41ba529de8 + checksum: 10/317569219366d487a3103ba1e5e47154e95a002915fdcf73a44162c48fe49c3a57fcf7f57fc6979e70d447112681e6b13c6c3c1df289db8b544df4aab2d318f3 languageName: node linkType: hard "@types/react@npm:^18.0.0": - version: 18.3.20 - resolution: "@types/react@npm:18.3.20" + version: 18.3.21 + resolution: "@types/react@npm:18.3.21" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/020c51e63b60862e6d772f0cdea0b9441182eedab6289dabd8add0708ded62003834c4e7c6f23a1ccd3ca9486b46296057c3f881c34261a0483765351f8d0bc3 + checksum: 10/89adc2fe391fd63b620db0aaa10b2be89fad338039415fd748e60c962e47bf2b0f1897cb5226f181eda963f37a1c8ac1bf0b3b29a0e35313bacd0355e5d6c736 languageName: node linkType: hard diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 09cd7357fa..26caf2e441 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -1525,21 +1525,21 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0": - version: 18.3.6 - resolution: "@types/react-dom@npm:18.3.6" + version: 18.3.7 + resolution: "@types/react-dom@npm:18.3.7" peerDependencies: "@types/react": ^18.0.0 - checksum: 10/ae179355401c64423d39946eda22c5f7f74c94ce61c21505024d4d82c33853ec40bc9b370f75e4a7750b0524aba4d95a43fcc328d8d14684dc2abb41ba529de8 + checksum: 10/317569219366d487a3103ba1e5e47154e95a002915fdcf73a44162c48fe49c3a57fcf7f57fc6979e70d447112681e6b13c6c3c1df289db8b544df4aab2d318f3 languageName: node linkType: hard "@types/react@npm:^18.0.0": - version: 18.3.20 - resolution: "@types/react@npm:18.3.20" + version: 18.3.21 + resolution: "@types/react@npm:18.3.21" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/020c51e63b60862e6d772f0cdea0b9441182eedab6289dabd8add0708ded62003834c4e7c6f23a1ccd3ca9486b46296057c3f881c34261a0483765351f8d0bc3 + checksum: 10/89adc2fe391fd63b620db0aaa10b2be89fad338039415fd748e60c962e47bf2b0f1897cb5226f181eda963f37a1c8ac1bf0b3b29a0e35313bacd0355e5d6c736 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index c7f8e452f0..9a0996f615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21036,11 +21036,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0": - version: 18.3.6 - resolution: "@types/react-dom@npm:18.3.6" + version: 18.3.7 + resolution: "@types/react-dom@npm:18.3.7" peerDependencies: "@types/react": ^18.0.0 - checksum: 10/ae179355401c64423d39946eda22c5f7f74c94ce61c21505024d4d82c33853ec40bc9b370f75e4a7750b0524aba4d95a43fcc328d8d14684dc2abb41ba529de8 + checksum: 10/317569219366d487a3103ba1e5e47154e95a002915fdcf73a44162c48fe49c3a57fcf7f57fc6979e70d447112681e6b13c6c3c1df289db8b544df4aab2d318f3 languageName: node linkType: hard @@ -21138,12 +21138,12 @@ __metadata: linkType: hard "@types/react@npm:^18.0.0": - version: 18.3.20 - resolution: "@types/react@npm:18.3.20" + version: 18.3.21 + resolution: "@types/react@npm:18.3.21" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/020c51e63b60862e6d772f0cdea0b9441182eedab6289dabd8add0708ded62003834c4e7c6f23a1ccd3ca9486b46296057c3f881c34261a0483765351f8d0bc3 + checksum: 10/89adc2fe391fd63b620db0aaa10b2be89fad338039415fd748e60c962e47bf2b0f1897cb5226f181eda963f37a1c8ac1bf0b3b29a0e35313bacd0355e5d6c736 languageName: node linkType: hard From fc5b4c9aab047daa99053e5c34a8190244a379d3 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 6 May 2025 12:53:06 +0100 Subject: [PATCH 045/143] Export root route for home page Signed-off-by: Daniel --- plugins/home/src/alpha.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/home/src/alpha.tsx b/plugins/home/src/alpha.tsx index 74f96a2195..04d612ef1c 100644 --- a/plugins/home/src/alpha.tsx +++ b/plugins/home/src/alpha.tsx @@ -69,4 +69,7 @@ const homePage = PageBlueprint.makeWithOverrides({ export default createFrontendPlugin({ pluginId: 'home', extensions: [homePage], + routes: { + root: rootRouteRef, + }, }); From 195323fdde4505565e95a54930c145aecf9aae35 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 6 May 2025 13:01:47 +0100 Subject: [PATCH 046/143] Add changeset Signed-off-by: Daniel --- .changeset/puny-rice-sneeze.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/puny-rice-sneeze.md diff --git a/.changeset/puny-rice-sneeze.md b/.changeset/puny-rice-sneeze.md new file mode 100644 index 0000000000..1967b68dab --- /dev/null +++ b/.changeset/puny-rice-sneeze.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Export root page route from the home plugin to enable adding links/nav to it from outside the plugin From 3556551f3d3230911c2e2051995312e6622617a5 Mon Sep 17 00:00:00 2001 From: Mohit Nain Date: Tue, 6 May 2025 20:04:43 +0530 Subject: [PATCH 047/143] Update architecture-overview.md Signed-off-by: Mohit Nain --- docs/overview/architecture-overview.md | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index d1be2bb2fc..a3c15aa480 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -6,20 +6,11 @@ description: Documentation on Architecture overview ## Terminology -Backstage is constructed out of three parts. We separate Backstage in this way -because we see three groups of contributors that work with Backstage in three -different ways. +Backstage is organized into three main components, each catering to different groups of contributors who interact with Backstage in distinct ways. -- Core - Base functionality built by core developers in the open source project. -- App - The app is an instance of a Backstage app that is deployed and tweaked. - The app ties together core functionality with additional plugins. The app is - built and maintained by app developers, usually a productivity team within a - company. -- Plugins - Additional functionality to make your Backstage app useful for your - company. Plugins can be specific to a company or open sourced and reusable. At - Spotify we have over 100 plugins built by over 50 different teams. It has been - very powerful to get contributions from various infrastructure teams added - into a single unified developer experience. +- Core - This includes the base functionality developed by core developers within the open-source project. +- App - The app represents a deployed instance of a Backstage application, customized and maintained by app developers, typically a productivity team within an organization. It integrates core functionalities with additional plugins. +- Plugins - These provide additional functionalities to enhance the usefulness of your Backstage app. Plugins can be company-specific or open-sourced and reusable. At Spotify, we have over 100 plugins created by more than 50 different teams, significantly enriching the unified developer experience by incorporating contributions from various infrastructure teams. ## Overview From 100edef7c01e5088b67c2f28b1f4460df4a15240 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 02:31:06 +0000 Subject: [PATCH 048/143] fix(deps): update dependency ws to v8.18.2 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 a7bb149ca2..ac2ac39914 100644 --- a/yarn.lock +++ b/yarn.lock @@ -48918,8 +48918,8 @@ __metadata: linkType: hard "ws@npm:*, ws@npm:^8.11.0, ws@npm:^8.12.0, ws@npm:^8.13.0, ws@npm:^8.17.1, ws@npm:^8.18.0, ws@npm:^8.2.3, ws@npm:^8.8.0": - version: 8.18.1 - resolution: "ws@npm:8.18.1" + version: 8.18.2 + resolution: "ws@npm:8.18.2" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -48928,7 +48928,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/3f38e9594f2af5b6324138e86b74df7d77bbb8e310bf8188679dd80bac0d1f47e51536a1923ac3365f31f3d8b25ea0b03e4ade466aa8292a86cd5defca64b19b + checksum: 10/018e04ec95561d88248d53a2eaf094b4ae131e9b062f2679e6e8a62f04649bc543448f1e038125225ac6bbb25f54c1e65d7a2cc9dbc1e28b43e5e6b7162ad88e languageName: node linkType: hard From 14ce237d235d17627fbb9c153f817626471f8b6f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 03:29:30 +0000 Subject: [PATCH 049/143] chore(deps): update dependency eslint to v9.26.0 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- storybook/yarn.lock | 683 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 637 insertions(+), 46 deletions(-) diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 09cd7357fa..60b6efc3b0 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -632,10 +632,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.25.1": - version: 9.25.1 - resolution: "@eslint/js@npm:9.25.1" - checksum: 10/ad5812889598de32d674ef60c0e61468ac5c7f3b6ecf98b0e29d1e88d7af8ba3aab255b8c0a46bbaf654047bbd2ee5aa033db9b53e330f97615093fcccde4cbb +"@eslint/js@npm:9.26.0": + version: 9.26.0 + resolution: "@eslint/js@npm:9.26.0" + checksum: 10/863d35df8f6675250bb5a917037e0f6833965437eba4c4649633fd0b55a93e8d727bcd36e9b5cc82047898ee9348cb40363e196f333914ae3a6bb36159495212 languageName: node linkType: hard @@ -779,6 +779,24 @@ __metadata: languageName: node linkType: hard +"@modelcontextprotocol/sdk@npm:^1.8.0": + version: 1.11.0 + resolution: "@modelcontextprotocol/sdk@npm:1.11.0" + dependencies: + content-type: "npm:^1.0.5" + cors: "npm:^2.8.5" + cross-spawn: "npm:^7.0.3" + eventsource: "npm:^3.0.2" + express: "npm:^5.0.1" + express-rate-limit: "npm:^7.5.0" + pkce-challenge: "npm:^5.0.0" + raw-body: "npm:^3.0.0" + zod: "npm:^3.23.8" + zod-to-json-schema: "npm:^3.24.1" + checksum: 10/527413fd2b18f75e031cda7f73a662098f3c5f1224b9c6b0b903d5a1f79e23e23a4f4b8e6971bac7eb46a74ed65ae05e8e548f7b7a3f7f6d179c3f6d10825fbc + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -1866,6 +1884,16 @@ __metadata: languageName: node linkType: hard +"accepts@npm:^2.0.0": + version: 2.0.0 + resolution: "accepts@npm:2.0.0" + dependencies: + mime-types: "npm:^3.0.0" + negotiator: "npm:^1.0.0" + checksum: 10/ea1343992b40b2bfb3a3113fa9c3c2f918ba0f9197ae565c48d3f84d44b174f6b1d5cd9989decd7655963eb03a272abc36968cc439c2907f999bd5ef8653d5a7 + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -2064,6 +2092,23 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:^2.2.0": + version: 2.2.0 + resolution: "body-parser@npm:2.2.0" + dependencies: + bytes: "npm:^3.1.2" + content-type: "npm:^1.0.5" + debug: "npm:^4.4.0" + http-errors: "npm:^2.0.0" + iconv-lite: "npm:^0.6.3" + on-finished: "npm:^2.4.1" + qs: "npm:^6.14.0" + raw-body: "npm:^3.0.0" + type-is: "npm:^2.0.0" + checksum: 10/e9d844b036bd15970df00a16f373c7ed28e1ef870974a0a1d4d6ef60d70e01087cc20a0dbb2081c49a88e3c08ce1d87caf1e2898c615dffa193f63e8faa8a84e + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -2113,6 +2158,13 @@ __metadata: languageName: node linkType: hard +"bytes@npm:3.1.2, bytes@npm:^3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: 10/a10abf2ba70c784471d6b4f58778c0beeb2b5d405148e66affa91f23a9f13d07603d0a0354667310ae1d6dc141474ffd44e2a074be0f6e2254edb8fc21445388 + languageName: node + linkType: hard + "cacache@npm:^18.0.0": version: 18.0.4 resolution: "cacache@npm:18.0.4" @@ -2133,6 +2185,16 @@ __metadata: languageName: node linkType: hard +"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + checksum: 10/00482c1f6aa7cfb30fb1dbeb13873edf81cfac7c29ed67a5957d60635a56b2a4a480f1016ddbdb3395cc37900d46037fb965043a51c5c789ffeab4fc535d18b5 + languageName: node + linkType: hard + "call-bind@npm:^1.0.2, call-bind@npm:^1.0.7": version: 1.0.7 resolution: "call-bind@npm:1.0.7" @@ -2146,6 +2208,16 @@ __metadata: languageName: node linkType: hard +"call-bound@npm:^1.0.2": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10/ef2b96e126ec0e58a7ff694db43f4d0d44f80e641370c21549ed911fecbdbc2df3ebc9bddad918d6bbdefeafb60bb3337902006d5176d72bcd2da74820991af7 + languageName: node + linkType: hard + "callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -2283,6 +2355,22 @@ __metadata: languageName: node linkType: hard +"content-disposition@npm:^1.0.0": + version: 1.0.0 + resolution: "content-disposition@npm:1.0.0" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: 10/0dcc1a2d7874526b0072df3011b134857b49d97a3bc135bb464a299525d4972de6f5f464fd64da6c4d8406d26a1ffb976f62afaffef7723b1021a44498d10e08 + languageName: node + linkType: hard + +"content-type@npm:^1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10/585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662 + languageName: node + linkType: hard + "convert-source-map@npm:^2.0.0": version: 2.0.0 resolution: "convert-source-map@npm:2.0.0" @@ -2290,7 +2378,31 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.6": +"cookie-signature@npm:^1.2.1": + version: 1.2.2 + resolution: "cookie-signature@npm:1.2.2" + checksum: 10/be44a3c9a56f3771aea3a8bd8ad8f0a8e2679bcb967478267f41a510b4eb5ec55085386ba79c706c4ac21605ca76f4251973444b90283e0eb3eeafe8a92c7708 + languageName: node + linkType: hard + +"cookie@npm:^0.7.1": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10/24b286c556420d4ba4e9bc09120c9d3db7d28ace2bd0f8ccee82422ce42322f73c8312441271e5eefafbead725980e5996cc02766dbb89a90ac7f5636ede608f + languageName: node + linkType: hard + +"cors@npm:^2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 10/66e88e08edee7cbce9d92b4d28a2028c88772a4c73e02f143ed8ca76789f9b59444eed6b1c167139e76fa662998c151322720093ba229f9941365ada5a6fc2c6 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -2315,15 +2427,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": - version: 4.3.7 - resolution: "debug@npm:4.3.7" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.4.0": + version: 4.4.0 + resolution: "debug@npm:4.4.0" dependencies: ms: "npm:^2.1.3" peerDependenciesMeta: supports-color: optional: true - checksum: 10/71168908b9a78227ab29d5d25fe03c5867750e31ce24bf2c44a86efc5af041758bb56569b0a3d48a9b5344c00a24a777e6f4100ed6dfd9534a42c1dde285125a + checksum: 10/1847944c2e3c2c732514b93d11886575625686056cd765336212dc15de2d2b29612b6cd80e1afba767bb8e1803b778caf9973e98169ef1a24a7a7009e1820367 languageName: node linkType: hard @@ -2359,6 +2471,13 @@ __metadata: languageName: node linkType: hard +"depd@npm:2.0.0, depd@npm:^2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10/c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca + languageName: node + linkType: hard + "dequal@npm:^2.0.2, dequal@npm:^2.0.3": version: 2.0.3 resolution: "dequal@npm:2.0.3" @@ -2398,6 +2517,17 @@ __metadata: languageName: node linkType: hard +"dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.2.0" + checksum: 10/5add88a3d68d42d6e6130a0cac450b7c2edbe73364bbd2fc334564418569bea97c6943a8fcd70e27130bf32afc236f30982fc4905039b703f23e9e0433c29934 + languageName: node + linkType: hard + "eastasianwidth@npm:^0.2.0": version: 0.2.0 resolution: "eastasianwidth@npm:0.2.0" @@ -2405,6 +2535,13 @@ __metadata: languageName: node linkType: hard +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10/1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + "electron-to-chromium@npm:^1.5.28": version: 1.5.41 resolution: "electron-to-chromium@npm:1.5.41" @@ -2426,6 +2563,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:^2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10/abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -2449,12 +2593,10 @@ __metadata: languageName: node linkType: hard -"es-define-property@npm:^1.0.0": - version: 1.0.0 - resolution: "es-define-property@npm:1.0.0" - dependencies: - get-intrinsic: "npm:^1.2.4" - checksum: 10/f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 +"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 10/f8dc9e660d90919f11084db0a893128f3592b781ce967e4fccfb8f3106cb83e400a4032c559184ec52ee1dbd4b01e7776c7cd0b3327b1961b1a4a7008920fe78 languageName: node linkType: hard @@ -2465,6 +2607,15 @@ __metadata: languageName: node linkType: hard +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10/54fe77de288451dae51c37bfbfe3ec86732dc3778f98f3eb3bdb4bf48063b2c0b8f9c93542656986149d08aa5be3204286e2276053d19582b76753f1a2728867 + languageName: node + linkType: hard + "es-toolkit@npm:^1.22.0": version: 1.26.1 resolution: "es-toolkit@npm:1.26.1" @@ -2661,6 +2812,13 @@ __metadata: languageName: node linkType: hard +"escape-html@npm:^1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10/6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -2724,8 +2882,8 @@ __metadata: linkType: hard "eslint@npm:^9.11.1": - version: 9.25.1 - resolution: "eslint@npm:9.25.1" + version: 9.26.0 + resolution: "eslint@npm:9.26.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.12.1" @@ -2733,11 +2891,12 @@ __metadata: "@eslint/config-helpers": "npm:^0.2.1" "@eslint/core": "npm:^0.13.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.25.1" + "@eslint/js": "npm:9.26.0" "@eslint/plugin-kit": "npm:^0.2.8" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.4.2" + "@modelcontextprotocol/sdk": "npm:^1.8.0" "@types/estree": "npm:^1.0.6" "@types/json-schema": "npm:^7.0.15" ajv: "npm:^6.12.4" @@ -2762,6 +2921,7 @@ __metadata: minimatch: "npm:^3.1.2" natural-compare: "npm:^1.4.0" optionator: "npm:^0.9.3" + zod: "npm:^3.24.2" peerDependencies: jiti: "*" peerDependenciesMeta: @@ -2769,7 +2929,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10/037bbdc5cba6f72199976dcdce115b1b479b9425ee1116c08bcaf25e0de4a74a0ffe696d48610ade79c91b04ef3e707a7215a42dfba9c7d3a0b85747d5902e67 + checksum: 10/b87092cb7e87f1d0963475c1a1e15e551842ea122925cf13231e742fae565bf3582029a5b0b4aecf793f25c26ee0be3ee1f32190bc361e0c3f3633b9cbace948 languageName: node linkType: hard @@ -2849,6 +3009,29 @@ __metadata: languageName: node linkType: hard +"etag@npm:^1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10/571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff + languageName: node + linkType: hard + +"eventsource-parser@npm:^3.0.1": + version: 3.0.1 + resolution: "eventsource-parser@npm:3.0.1" + checksum: 10/2730c54c3cb47d55d2967f2ece843f9fc95d8a11c2fef6fece8d17d9080193cbe3cd9ac7b04a325977f63cbf8c1664fdd0512dec1aec601666a5c5bd8564b61f + languageName: node + linkType: hard + +"eventsource@npm:^3.0.2": + version: 3.0.6 + resolution: "eventsource@npm:3.0.6" + dependencies: + eventsource-parser: "npm:^3.0.1" + checksum: 10/ac08c7d1b21e454c7685693fe4ace53fc0b84f3cf752699a556876f2a7f33b7a12972ae33d1c407fb920d6d4aed10de52fdf0dd01902ccdf45cd5da8d55e7f88 + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.1 resolution: "exponential-backoff@npm:3.1.1" @@ -2856,6 +3039,50 @@ __metadata: languageName: node linkType: hard +"express-rate-limit@npm:^7.5.0": + version: 7.5.0 + resolution: "express-rate-limit@npm:7.5.0" + peerDependencies: + express: ^4.11 || 5 || ^5.0.0-beta.1 + checksum: 10/eff34c83bf586789933a332a339b66649e2cca95c8e977d193aa8bead577d3182ac9f0e9c26f39389287539b8038890ff023f910b54ebb506a26a2ce135b92ca + languageName: node + linkType: hard + +"express@npm:^5.0.1": + version: 5.1.0 + resolution: "express@npm:5.1.0" + dependencies: + accepts: "npm:^2.0.0" + body-parser: "npm:^2.2.0" + content-disposition: "npm:^1.0.0" + content-type: "npm:^1.0.5" + cookie: "npm:^0.7.1" + cookie-signature: "npm:^1.2.1" + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + finalhandler: "npm:^2.1.0" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.0" + merge-descriptors: "npm:^2.0.0" + mime-types: "npm:^3.0.0" + on-finished: "npm:^2.4.1" + once: "npm:^1.4.0" + parseurl: "npm:^1.3.3" + proxy-addr: "npm:^2.0.7" + qs: "npm:^6.14.0" + range-parser: "npm:^1.2.1" + router: "npm:^2.2.0" + send: "npm:^1.1.0" + serve-static: "npm:^2.2.0" + statuses: "npm:^2.0.1" + type-is: "npm:^2.0.1" + vary: "npm:^1.1.2" + checksum: 10/6dba00bbdf308f43a84ed3f07a7e9870d5208f2a0b8f60f39459dda089750379747819863fad250849d3c9163833f33f94ce69d73938df31e0c5a430800d7e56 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -2924,6 +3151,20 @@ __metadata: languageName: node linkType: hard +"finalhandler@npm:^2.1.0": + version: 2.1.0 + resolution: "finalhandler@npm:2.1.0" + dependencies: + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + on-finished: "npm:^2.4.1" + parseurl: "npm:^1.3.3" + statuses: "npm:^2.0.1" + checksum: 10/b2bd68c310e2c463df0ab747ab05f8defbc540b8c3f2442f86e7d084ac8acbc31f8cae079931b7f5a406521501941e3395e963de848a0aaf45dd414adeb5ff4e + languageName: node + linkType: hard + "find-up@npm:^5.0.0": version: 5.0.0 resolution: "find-up@npm:5.0.0" @@ -2970,6 +3211,20 @@ __metadata: languageName: node linkType: hard +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10/29ba9fd347117144e97cbb8852baae5e8b2acb7d1b591ef85695ed96f5b933b1804a7fac4a15dd09ca7ac7d0cdc104410e8102aae2dd3faa570a797ba07adb81 + languageName: node + linkType: hard + +"fresh@npm:^2.0.0": + version: 2.0.0 + resolution: "fresh@npm:2.0.0" + checksum: 10/44e1468488363074641991c1340d2a10c5a6f6d7c353d89fd161c49d120c58ebf9890720f7584f509058385836e3ce50ddb60e9f017315a4ba8c6c3461813bfc + languageName: node + linkType: hard + "fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -3021,16 +3276,31 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.4": - version: 1.2.4 - resolution: "get-intrinsic@npm:1.2.4" +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.3.0": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" function-bind: "npm:^1.1.2" - has-proto: "npm:^1.0.1" - has-symbols: "npm:^1.0.3" - hasown: "npm:^2.0.0" - checksum: 10/85bbf4b234c3940edf8a41f4ecbd4e25ce78e5e6ad4e24ca2f77037d983b9ef943fd72f00f3ee97a49ec622a506b67db49c36246150377efcda1c9eb03e5f06d + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10/6e9dd920ff054147b6f44cb98104330e87caafae051b6d37b13384a45ba15e71af33c3baeac7cb630a0aaa23142718dcf25b45cfdd86c184c5dcb4e56d953a10 + languageName: node + linkType: hard + +"get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: "npm:^1.0.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/4fc96afdb58ced9a67558698b91433e6b037aaa6f1493af77498d7c85b141382cf223c0e5946f334fb328ee85dfe6edd06d218eaf09556f4bc4ec6005d7f5f7b languageName: node linkType: hard @@ -3103,12 +3373,10 @@ __metadata: languageName: node linkType: hard -"gopd@npm:^1.0.1": - version: 1.0.1 - resolution: "gopd@npm:1.0.1" - dependencies: - get-intrinsic: "npm:^1.1.3" - checksum: 10/5fbc7ad57b368ae4cd2f41214bd947b045c1a4be2f194a7be1778d71f8af9dbf4004221f3b6f23e30820eb0d052b4f819fe6ebe8221e2a3c6f0ee4ef173421ca +"gopd@npm:^1.0.1, gopd@npm:^1.2.0": + version: 1.2.0 + resolution: "gopd@npm:1.2.0" + checksum: 10/94e296d69f92dc1c0768fcfeecfb3855582ab59a7c75e969d5f96ce50c3d201fd86d5a2857c22565764d5bb8a816c7b1e58f133ec318cd56274da36c5e3fb1a1 languageName: node linkType: hard @@ -3149,17 +3417,10 @@ __metadata: languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.3 - resolution: "has-proto@npm:1.0.3" - checksum: 10/0b67c2c94e3bea37db3e412e3c41f79d59259875e636ba471e94c009cdfb1fa82bf045deeffafc7dbb9c148e36cae6b467055aaa5d9fad4316e11b41e3ba551a - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: 10/464f97a8202a7690dadd026e6d73b1ceeddd60fe6acfd06151106f050303eaa75855aaa94969df8015c11ff7c505f196114d22f7386b4a471038da5874cf5e9b +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard @@ -3172,7 +3433,7 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.2": +"hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" dependencies: @@ -3188,6 +3449,19 @@ __metadata: languageName: node linkType: hard +"http-errors@npm:2.0.0, http-errors@npm:^2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 10/0e7f76ee8ff8a33e58a3281a469815b893c41357378f408be8f6d4aa7d1efafb0da064625518e7078381b6a92325949b119dc38fcb30bdbc4e3a35f78c44c439 + languageName: node + linkType: hard + "http-proxy-agent@npm:^7.0.0": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" @@ -3208,7 +3482,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -3248,7 +3522,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:^2.0.3": +"inherits@npm:2.0.4, inherits@npm:^2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10/cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 @@ -3265,6 +3539,13 @@ __metadata: languageName: node linkType: hard +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10/864d0cced0c0832700e9621913a6429ccdc67f37c1bd78fb8c6789fff35c9d167cb329134acad2290497a53336813ab4798d2794fd675d5eb33b5fdf0982b9ca + languageName: node + linkType: hard + "is-arguments@npm:^1.0.4": version: 1.1.1 resolution: "is-arguments@npm:1.1.1" @@ -3346,6 +3627,13 @@ __metadata: languageName: node linkType: hard +"is-promise@npm:^4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 10/0b46517ad47b00b6358fd6553c83ec1f6ba9acd7ffb3d30a0bf519c5c69e7147c132430452351b8a9fc198f8dd6c4f76f8e6f5a7f100f8c77d57d9e0f4261a8a + languageName: node + linkType: hard + "is-typed-array@npm:^1.1.3": version: 1.1.13 resolution: "is-typed-array@npm:1.1.13" @@ -3605,6 +3893,20 @@ __metadata: languageName: node linkType: hard +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 10/11df2eda46d092a6035479632e1ec865b8134bdfc4bd9e571a656f4191525404f13a283a515938c3a8de934dbfd9c09674d9da9fa831e6eb7e22b50b197d2edd + languageName: node + linkType: hard + +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: 10/a58dd60804df73c672942a7253ccc06815612326dc1c0827984b1a21704466d7cde351394f47649e56cf7415e6ee2e26e000e81b51b3eebb5a93540e8bf93cbd + languageName: node + linkType: hard + "memoizerific@npm:^1.11.3": version: 1.11.3 resolution: "memoizerific@npm:1.11.3" @@ -3614,6 +3916,13 @@ __metadata: languageName: node linkType: hard +"merge-descriptors@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-descriptors@npm:2.0.0" + checksum: 10/e383332e700a94682d0125a36c8be761142a1320fc9feeb18e6e36647c9edf064271645f5669b2c21cf352116e561914fd8aa831b651f34db15ef4038c86696a + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -3631,6 +3940,22 @@ __metadata: languageName: node linkType: hard +"mime-db@npm:^1.54.0": + version: 1.54.0 + resolution: "mime-db@npm:1.54.0" + checksum: 10/9e7834be3d66ae7f10eaa69215732c6d389692b194f876198dca79b2b90cbf96688d9d5d05ef7987b20f749b769b11c01766564264ea5f919c88b32a29011311 + languageName: node + linkType: hard + +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.1": + version: 3.0.1 + resolution: "mime-types@npm:3.0.1" + dependencies: + mime-db: "npm:^1.54.0" + checksum: 10/fa1d3a928363723a8046c346d87bf85d35014dae4285ad70a3ff92bd35957992b3094f8417973cfe677330916c6ef30885109624f1fb3b1e61a78af509dba120 + languageName: node + linkType: hard + "min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -3793,6 +4118,13 @@ __metadata: languageName: node linkType: hard +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 + languageName: node + linkType: hard + "node-gyp@npm:latest": version: 10.2.0 resolution: "node-gyp@npm:10.2.0" @@ -3831,6 +4163,38 @@ __metadata: languageName: node linkType: hard +"object-assign@npm:^4": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: 10/fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.3": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb + languageName: node + linkType: hard + +"on-finished@npm:^2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10/8e81472c5028125c8c39044ac4ab8ba51a7cdc19a9fbd4710f5d524a74c6d8c9ded4dd0eed83f28d3d33ac1d7a6a439ba948ccb765ac6ce87f30450a26bfe2ea + languageName: node + linkType: hard + +"once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10/cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + "open@npm:^8.0.4": version: 8.4.2 resolution: "open@npm:8.4.2" @@ -3899,6 +4263,13 @@ __metadata: languageName: node linkType: hard +"parseurl@npm:^1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10/407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -3930,6 +4301,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^8.0.0": + version: 8.2.0 + resolution: "path-to-regexp@npm:8.2.0" + checksum: 10/23378276a172b8ba5f5fb824475d1818ca5ccee7bbdb4674701616470f23a14e536c1db11da9c9e6d82b82c556a817bbf4eee6e41b9ed20090ef9427cbb38e13 + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -3958,6 +4336,13 @@ __metadata: languageName: node linkType: hard +"pkce-challenge@npm:^5.0.0": + version: 5.0.0 + resolution: "pkce-challenge@npm:5.0.0" + checksum: 10/e60c06a0e0481cb82f80072053d5c479a7490758541c4226460450285dd5d72a995c44b3c553731ca7c2f64cc34b35f1d2e5f9de08d276b59899298f9efe1ddf + languageName: node + linkType: hard + "polished@npm:^4.2.2": version: 4.3.1 resolution: "polished@npm:4.3.1" @@ -4036,6 +4421,16 @@ __metadata: languageName: node linkType: hard +"proxy-addr@npm:^2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10/f24a0c80af0e75d31e3451398670d73406ec642914da11a2965b80b1898ca6f66a0e3e091a11a4327079b2b268795f6fa06691923fef91887215c3d0e8ea3f68 + languageName: node + linkType: hard + "punycode@npm:^2.1.0": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -4043,6 +4438,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.14.0": + version: 6.14.0 + resolution: "qs@npm:6.14.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10/a60e49bbd51c935a8a4759e7505677b122e23bf392d6535b8fc31c1e447acba2c901235ecb192764013cd2781723dc1f61978b5fdd93cc31d7043d31cdc01974 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -4050,6 +4454,25 @@ __metadata: languageName: node linkType: hard +"range-parser@npm:^1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10/ce21ef2a2dd40506893157970dc76e835c78cf56437e26e19189c48d5291e7279314477b06ac38abd6a401b661a6840f7b03bd0b1249da9b691deeaa15872c26 + languageName: node + linkType: hard + +"raw-body@npm:^3.0.0": + version: 3.0.0 + resolution: "raw-body@npm:3.0.0" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.6.3" + unpipe: "npm:1.0.0" + checksum: 10/2443429bbb2f9ae5c50d3d2a6c342533dfbde6b3173740b70fa0302b30914ff400c6d31a46b3ceacbe7d0925dc07d4413928278b494b04a65736fc17ca33e30c + languageName: node + linkType: hard + "react-confetti@npm:^6.1.0": version: 6.1.0 resolution: "react-confetti@npm:6.1.0" @@ -4298,6 +4721,19 @@ __metadata: languageName: node linkType: hard +"router@npm:^2.2.0": + version: 2.2.0 + resolution: "router@npm:2.2.0" + dependencies: + debug: "npm:^4.4.0" + depd: "npm:^2.0.0" + is-promise: "npm:^4.0.0" + parseurl: "npm:^1.3.3" + path-to-regexp: "npm:^8.0.0" + checksum: 10/8949bd1d3da5403cc024e2989fee58d7fda0f3ffe9f2dc5b8a192f295f400b3cde307b0b554f7d44851077640f36962ca469a766b3d57410d7d96245a7ba6c91 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -4307,6 +4743,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:5.2.1": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 + languageName: node + linkType: hard + "safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -4348,6 +4791,37 @@ __metadata: languageName: node linkType: hard +"send@npm:^1.1.0, send@npm:^1.2.0": + version: 1.2.0 + resolution: "send@npm:1.2.0" + dependencies: + debug: "npm:^4.3.5" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.0" + mime-types: "npm:^3.0.1" + ms: "npm:^2.1.3" + on-finished: "npm:^2.4.1" + range-parser: "npm:^1.2.1" + statuses: "npm:^2.0.1" + checksum: 10/9fa3b1a3b9a06b7b4ab00c25e8228326d9665a9745753a34d1ffab8ac63c7c206727331d1dc5be73647f1b658d259a1aa8e275b0e0eee51349370af02e9da506 + languageName: node + linkType: hard + +"serve-static@npm:^2.2.0": + version: 2.2.0 + resolution: "serve-static@npm:2.2.0" + dependencies: + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + parseurl: "npm:^1.3.3" + send: "npm:^1.2.0" + checksum: 10/9f1a900738c5bb02258275ce3bd1273379c4c3072b622e15d44e8f47d89a1ba2d639ec2d63b11c263ca936096b40758acb7a0d989cd6989018a65a12f9433ada + languageName: node + linkType: hard + "set-function-length@npm:^1.2.1": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -4362,6 +4836,13 @@ __metadata: languageName: node linkType: hard +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10/fde1630422502fbbc19e6844346778f99d449986b2f9cdcceb8326730d2f3d9964dbcb03c02aaadaefffecd0f2c063315ebea8b3ad895914bf1afc1747fc172e + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -4378,6 +4859,54 @@ __metadata: languageName: node linkType: hard +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + checksum: 10/603b928997abd21c5a5f02ae6b9cc36b72e3176ad6827fab0417ead74580cc4fb4d5c7d0a8a2ff4ead34d0f9e35701ed7a41853dac8a6d1a664fcce1a044f86f + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10/5771861f77feefe44f6195ed077a9e4f389acc188f895f570d56445e251b861754b547ea9ef73ecee4e01fdada6568bfe9020d2ec2dfc5571e9fa1bbc4a10615 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10/a815c89bc78c5723c714ea1a77c938377ea710af20d4fb886d362b0d1f8ac73a17816a5f6640f354017d7e292a43da9c5e876c22145bac00b76cfb3468001736 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10/7d53b9db292c6262f326b6ff3bc1611db84ece36c2c7dc0e937954c13c73185b0406c56589e2bb8d071d6fee468e14c39fb5d203ee39be66b7b8174f179afaba + languageName: node + linkType: hard + "signal-exit@npm:^4.0.1": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" @@ -4450,6 +4979,13 @@ __metadata: languageName: node linkType: hard +"statuses@npm:2.0.1, statuses@npm:^2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 10/18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + "storybook@npm:^8.3.5": version: 8.6.12 resolution: "storybook@npm:8.6.12" @@ -4616,6 +5152,13 @@ __metadata: languageName: node linkType: hard +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10/952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + "ts-api-utils@npm:^2.0.1": version: 2.0.1 resolution: "ts-api-utils@npm:2.0.1" @@ -4691,6 +5234,17 @@ __metadata: languageName: node linkType: hard +"type-is@npm:^2.0.0, type-is@npm:^2.0.1": + version: 2.0.1 + resolution: "type-is@npm:2.0.1" + dependencies: + content-type: "npm:^1.0.5" + media-typer: "npm:^1.1.0" + mime-types: "npm:^3.0.0" + checksum: 10/bacdb23c872dacb7bd40fbd9095e6b2fca2895eedbb689160c05534d7d4810a7f4b3fd1ae87e96133c505958f6d602967a68db5ff577b85dd6be76eaa75d58af + languageName: node + linkType: hard + "typescript-eslint@npm:^8.7.0": version: 8.26.0 resolution: "typescript-eslint@npm:8.26.0" @@ -4750,6 +5304,13 @@ __metadata: languageName: node linkType: hard +"unpipe@npm:1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10/4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + "unplugin@npm:^1.3.1": version: 1.14.1 resolution: "unplugin@npm:1.14.1" @@ -4810,6 +5371,13 @@ __metadata: languageName: node linkType: hard +"vary@npm:^1, vary@npm:^1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 10/31389debef15a480849b8331b220782230b9815a8e0dbb7b9a8369559aed2e9a7800cd904d4371ea74f4c3527db456dc8e7ac5befce5f0d289014dbdf47b2242 + languageName: node + linkType: hard + "vite@npm:^5.4.8": version: 5.4.19 resolution: "vite@npm:5.4.19" @@ -4924,6 +5492,13 @@ __metadata: languageName: node linkType: hard +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10/159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 + languageName: node + linkType: hard + "ws@npm:^8.2.3": version: 8.18.0 resolution: "ws@npm:8.18.0" @@ -4959,3 +5534,19 @@ __metadata: checksum: 10/f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 languageName: node linkType: hard + +"zod-to-json-schema@npm:^3.24.1": + version: 3.24.5 + resolution: "zod-to-json-schema@npm:3.24.5" + peerDependencies: + zod: ^3.24.1 + checksum: 10/1af291b4c429945c9568c2e924bdb7c66ab8d139cbeb9a99b6e9fc9e1b02863f85d07759b9303714f07ceda3993dcaf0ebcb80d2c18bb2aaf5502b2c1016affd + languageName: node + linkType: hard + +"zod@npm:^3.23.8, zod@npm:^3.24.2": + version: 3.24.4 + resolution: "zod@npm:3.24.4" + checksum: 10/3d545792fa54bb27ee5dbc34a5709e81f603185fcc94c8204b5d95c20dc4c81d870ff9c51f3884a30ef05cdc601449f4c4df254ac4783f0827b1faed7c1cdb48 + languageName: node + linkType: hard From 659f2ce8407782d4f68f23ae4083c2b75a4cd9a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 03:30:03 +0000 Subject: [PATCH 050/143] chore(deps): update dependency typedoc to ^0.28.0 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .changeset/renovate-29506de.md | 5 ++ package.json | 2 +- packages/repo-tools/package.json | 4 +- yarn.lock | 84 ++++++++++++++++++++------------ 4 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 .changeset/renovate-29506de.md diff --git a/.changeset/renovate-29506de.md b/.changeset/renovate-29506de.md new file mode 100644 index 0000000000..1260f3b453 --- /dev/null +++ b/.changeset/renovate-29506de.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Updated dependency `typedoc` to `^0.28.0`. diff --git a/package.json b/package.json index b5d88d947b..4e1cf77fff 100644 --- a/package.json +++ b/package.json @@ -150,7 +150,7 @@ "shx": "^0.3.2", "sloc": "^0.3.1", "sort-package-json": "^2.8.0", - "typedoc": "^0.27.6", + "typedoc": "^0.28.0", "typescript": "~5.6.0" }, "packageManager": "yarn@4.8.1", diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 1ec1d1a48f..77783ff1dc 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -90,7 +90,7 @@ "@types/is-glob": "^4.0.2", "@types/node": "^20.16.0", "@types/prettier": "^2.0.0", - "typedoc": "^0.27.6" + "typedoc": "^0.28.0" }, "peerDependencies": { "@microsoft/api-extractor-model": "*", @@ -98,7 +98,7 @@ "@microsoft/tsdoc-config": "*", "@useoptic/optic": "^1.0.0", "prettier": "^2.8.1", - "typedoc": "^0.27.0", + "typedoc": "^0.28.0", "typescript": "> 3.0.0" }, "peerDependenciesMeta": { diff --git a/yarn.lock b/yarn.lock index 98518c53d6..9caa909c47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8943,7 +8943,7 @@ __metadata: portfinder: "npm:^1.0.32" tar: "npm:^6.1.12" ts-morph: "npm:^24.0.0" - typedoc: "npm:^0.27.6" + typedoc: "npm:^0.28.0" yaml-diff-patch: "npm:^2.0.0" peerDependencies: "@microsoft/api-extractor-model": "*" @@ -8951,7 +8951,7 @@ __metadata: "@microsoft/tsdoc-config": "*" "@useoptic/optic": ^1.0.0 prettier: ^2.8.1 - typedoc: ^0.27.0 + typedoc: ^0.28.0 typescript: "> 3.0.0" peerDependenciesMeta: prettier: @@ -10329,14 +10329,16 @@ __metadata: languageName: node linkType: hard -"@gerrit0/mini-shiki@npm:^1.24.0": - version: 1.27.2 - resolution: "@gerrit0/mini-shiki@npm:1.27.2" +"@gerrit0/mini-shiki@npm:^3.2.2": + version: 3.4.0 + resolution: "@gerrit0/mini-shiki@npm:3.4.0" dependencies: - "@shikijs/engine-oniguruma": "npm:^1.27.2" - "@shikijs/types": "npm:^1.27.2" - "@shikijs/vscode-textmate": "npm:^10.0.1" - checksum: 10/ee4c80d94da587bd0dfe262f92ce81be0a1aa86dd0ef88e708839751af552451dd113f139b556be4f18747bf883d81ee85a119e535852114a71efda1cb3c5be5 + "@shikijs/engine-oniguruma": "npm:^3.4.0" + "@shikijs/langs": "npm:^3.4.0" + "@shikijs/themes": "npm:^3.4.0" + "@shikijs/types": "npm:^3.4.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10/2e116b8a6cb4d63db0fc8d96ba696befb4b4d66d4eaf4673c2585e798ae871e7e7cc581252cdc08169e5c19ae1aa496d93286da7626a36f7b0d298c660178855 languageName: node linkType: hard @@ -16895,30 +16897,48 @@ __metadata: languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:^1.27.2": - version: 1.29.2 - resolution: "@shikijs/engine-oniguruma@npm:1.29.2" +"@shikijs/engine-oniguruma@npm:^3.4.0": + version: 3.4.0 + resolution: "@shikijs/engine-oniguruma@npm:3.4.0" dependencies: - "@shikijs/types": "npm:1.29.2" - "@shikijs/vscode-textmate": "npm:^10.0.1" - checksum: 10/bb3e2c01da84d573251ebc289b1ecf815261024dea5bddb93ad56c3504a71cde3630db070be401ed3bbcd23a8a839ec78984a82317f9c9d0bba58daed935b781 + "@shikijs/types": "npm:3.4.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10/3f6c33a1f49e6a8235b79029e3e95f0bc95398f299e53b96a23942ceb4648be51071f48b8632e2f244b2b2477d152035fd18bc4b7e34abe885d84e94698f7e94 languageName: node linkType: hard -"@shikijs/types@npm:1.29.2, @shikijs/types@npm:^1.27.2": - version: 1.29.2 - resolution: "@shikijs/types@npm:1.29.2" +"@shikijs/langs@npm:^3.4.0": + version: 3.4.0 + resolution: "@shikijs/langs@npm:3.4.0" dependencies: - "@shikijs/vscode-textmate": "npm:^10.0.1" + "@shikijs/types": "npm:3.4.0" + checksum: 10/355065accab578a8a017ee238f13ee0b6adf007b514f78d7ea126f07ee89cd682f1f377f49d923688c6787b474b5b3a640aa3b083ac11ea11ea4edd7e8c50ac7 + languageName: node + linkType: hard + +"@shikijs/themes@npm:^3.4.0": + version: 3.4.0 + resolution: "@shikijs/themes@npm:3.4.0" + dependencies: + "@shikijs/types": "npm:3.4.0" + checksum: 10/74e5911548d77a63375125575db77dd62b44c40afd39f168bc3fc4d7fefb4d2922f49cf76d21139d850a02a5e207659a247a417be27b438d3d5ea80abe450e52 + languageName: node + linkType: hard + +"@shikijs/types@npm:3.4.0, @shikijs/types@npm:^3.4.0": + version: 3.4.0 + resolution: "@shikijs/types@npm:3.4.0" + dependencies: + "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10/579e64b6e8cb83023232b8060b08f51cff3909b199d0d1a0c58ed500c898dd34b74bf0457336fa2e6bee1005889e198d7d924347ad616eee30c6ae4c89a67ab8 + checksum: 10/bca759ac0972f9ab673b199d44fb4655eb75a1af68b024f05126ff6ef0ce1fd7d316ca16da8eb7c383de8b058f358f90e6172be3783a1f04a3871f518fb0fd72 languageName: node linkType: hard -"@shikijs/vscode-textmate@npm:^10.0.1": - version: 10.0.1 - resolution: "@shikijs/vscode-textmate@npm:10.0.1" - checksum: 10/8bb005efbf472a9cac19bb5fb0bb1a2b612e128122e5a9d7b2bb2af674c29912db0e59c547ec458e5333f8f7ac7a8f054a24cb653f11dc20951e299933b416e4 +"@shikijs/vscode-textmate@npm:^10.0.2": + version: 10.0.2 + resolution: "@shikijs/vscode-textmate@npm:10.0.2" + checksum: 10/d924cba8a01cd9ca12f56ba097d628fdb81455abb85884c8d8a5ae85b628a37dd5907e7691019b97107bd6608c866adf91ba04a1c3bba391281c88e386c044ea languageName: node linkType: hard @@ -43913,7 +43933,7 @@ __metadata: shx: "npm:^0.3.2" sloc: "npm:^0.3.1" sort-package-json: "npm:^2.8.0" - typedoc: "npm:^0.27.6" + typedoc: "npm:^0.28.0" typescript: "npm:~5.6.0" yaml: "npm:^2.7.0" languageName: unknown @@ -47219,20 +47239,20 @@ __metadata: languageName: node linkType: hard -"typedoc@npm:^0.27.6": - version: 0.27.9 - resolution: "typedoc@npm:0.27.9" +"typedoc@npm:^0.28.0": + version: 0.28.4 + resolution: "typedoc@npm:0.28.4" dependencies: - "@gerrit0/mini-shiki": "npm:^1.24.0" + "@gerrit0/mini-shiki": "npm:^3.2.2" lunr: "npm:^2.3.9" markdown-it: "npm:^14.1.0" minimatch: "npm:^9.0.5" - yaml: "npm:^2.6.1" + yaml: "npm:^2.7.1" peerDependencies: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x bin: typedoc: bin/typedoc - checksum: 10/fb1e4b54849cad1628543fb24863358320b737aabba83194562360cfbcaac8684b2b18824fd623bb27a9e8dbbc0e01c0b88fedd9a642d78e7a3c108387e44d25 + checksum: 10/0ccab46519e4be1aa9bd4defd55e920cbefe8825e0ba7ca93b8d6fd3867300e8b60260d2182033b46121f9040251366f6a496a3500da458c3031b224d7bdadd7 languageName: node linkType: hard @@ -49102,7 +49122,7 @@ __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, yaml@npm:^2.7.0": +"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, yaml@npm:^2.7.1": version: 2.7.1 resolution: "yaml@npm:2.7.1" bin: From 5cc1f7f3eddce661d30fdf0f8f3bdfd3b1a95c11 Mon Sep 17 00:00:00 2001 From: Jessica He Date: Wed, 7 May 2025 15:19:49 +0900 Subject: [PATCH 051/143] Address feedback Signed-off-by: Jessica He --- .changeset/tall-suits-share.md | 23 +++++++++++++ .changeset/twenty-olives-impress.md | 23 ------------- .../config/vocabularies/Backstage/accept.txt | 1 + .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 6 +++- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 4 +-- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 4 +-- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 4 +-- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 2 +- .../src/resolvers.ts | 2 +- .../resolvers/CatalogAuthResolverContext.ts | 33 ++++++++----------- plugins/auth-node/report.api.md | 16 +++++---- .../src/sign-in/commonSignInResolvers.ts | 4 +-- plugins/auth-node/src/types.ts | 16 +++++---- 22 files changed, 80 insertions(+), 76 deletions(-) create mode 100644 .changeset/tall-suits-share.md delete mode 100644 .changeset/twenty-olives-impress.md diff --git a/.changeset/tall-suits-share.md b/.changeset/tall-suits-share.md new file mode 100644 index 0000000000..b7c5d1ccfe --- /dev/null +++ b/.changeset/tall-suits-share.md @@ -0,0 +1,23 @@ +--- +'@backstage/plugin-auth-backend-module-cloudflare-access-provider': patch +'@backstage/plugin-auth-backend-module-bitbucket-server-provider': patch +'@backstage/plugin-auth-backend-module-azure-easyauth-provider': patch +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': patch +'@backstage/plugin-auth-backend-module-vmware-cloud-provider': patch +'@backstage/plugin-auth-backend-module-atlassian-provider': patch +'@backstage/plugin-auth-backend-module-bitbucket-provider': patch +'@backstage/plugin-auth-backend-module-microsoft-provider': patch +'@backstage/plugin-auth-backend-module-onelogin-provider': patch +'@backstage/plugin-auth-backend-module-aws-alb-provider': patch +'@backstage/plugin-auth-backend-module-gcp-iap-provider': patch +'@backstage/plugin-auth-backend-module-github-provider': patch +'@backstage/plugin-auth-backend-module-gitlab-provider': patch +'@backstage/plugin-auth-backend-module-google-provider': patch +'@backstage/plugin-auth-backend-module-oauth2-provider': patch +'@backstage/plugin-auth-backend-module-oidc-provider': patch +'@backstage/plugin-auth-backend-module-okta-provider': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-auth-node': patch +--- + +introduce dangerouslyAllowSignInWithoutUserInCatalog auth resolver config diff --git a/.changeset/twenty-olives-impress.md b/.changeset/twenty-olives-impress.md deleted file mode 100644 index 9051cf2e67..0000000000 --- a/.changeset/twenty-olives-impress.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-cloudflare-access-provider': minor -'@backstage/plugin-auth-backend-module-bitbucket-server-provider': minor -'@backstage/plugin-auth-backend-module-azure-easyauth-provider': minor -'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': minor -'@backstage/plugin-auth-backend-module-vmware-cloud-provider': minor -'@backstage/plugin-auth-backend-module-atlassian-provider': minor -'@backstage/plugin-auth-backend-module-bitbucket-provider': minor -'@backstage/plugin-auth-backend-module-microsoft-provider': minor -'@backstage/plugin-auth-backend-module-onelogin-provider': minor -'@backstage/plugin-auth-backend-module-aws-alb-provider': minor -'@backstage/plugin-auth-backend-module-gcp-iap-provider': minor -'@backstage/plugin-auth-backend-module-github-provider': minor -'@backstage/plugin-auth-backend-module-gitlab-provider': minor -'@backstage/plugin-auth-backend-module-google-provider': minor -'@backstage/plugin-auth-backend-module-oauth2-provider': minor -'@backstage/plugin-auth-backend-module-oidc-provider': minor -'@backstage/plugin-auth-backend-module-okta-provider': minor -'@backstage/plugin-auth-backend': minor -'@backstage/plugin-auth-node': minor ---- - -introduce dangerouslyAllowSignInWithoutUserInCatalog auth resolver config diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index f5defc22f2..67ccf26c28 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -302,6 +302,7 @@ oidc Okta Olausson Oldsberg +onboarded onboarding Onboarding onelogin diff --git a/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts b/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts index cbd93e4b4f..949f25db9c 100644 --- a/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts @@ -54,7 +54,7 @@ export namespace atlassianSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); diff --git a/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts b/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts index 5d04de620f..38b4b60f27 100644 --- a/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-aws-alb-provider/src/resolvers.ts @@ -52,7 +52,11 @@ export namespace awsAlbSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: info.result.fullProfile.emails[0].value } + ? { + entityRef: { + name: info.result.fullProfile.emails[0].value, + }, + } : undefined, }, ); diff --git a/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts b/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts index 17463123c4..94afa90c5f 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-azure-easyauth-provider/src/resolvers.ts @@ -47,7 +47,7 @@ export namespace azureEasyAuthSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); diff --git a/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts b/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts index 1dd9783b98..6691806e63 100644 --- a/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-bitbucket-provider/src/resolvers.ts @@ -59,7 +59,7 @@ export namespace bitbucketSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); @@ -101,7 +101,7 @@ export namespace bitbucketSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: username } + ? { entityRef: { name: username } } : undefined, }, ); diff --git a/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts b/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts index cf6970a6df..2e92d8c6ad 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-bitbucket-server-provider/src/resolvers.ts @@ -59,7 +59,7 @@ export namespace bitbucketServerSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: profile.email } + ? { entityRef: { name: profile.email } } : undefined, }, ); diff --git a/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts b/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts index 6ac9fba958..21cb124be4 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-cloudflare-access-provider/src/resolvers.ts @@ -56,7 +56,7 @@ export namespace cloudflareAccessSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: profile.email } + ? { entityRef: { name: profile.email } } : undefined, }, ); diff --git a/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts b/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts index 383d32cc57..77dc7b1062 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-gcp-iap-provider/src/resolvers.ts @@ -53,7 +53,7 @@ export namespace gcpIapSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: email } + ? { entityRef: { name: email } } : undefined, }, ); @@ -83,7 +83,7 @@ export namespace gcpIapSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: userId } + ? { entityRef: { name: userId } } : undefined, }, ); diff --git a/plugins/auth-backend-module-github-provider/src/resolvers.ts b/plugins/auth-backend-module-github-provider/src/resolvers.ts index cc1950e9dd..5a6934439f 100644 --- a/plugins/auth-backend-module-github-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-github-provider/src/resolvers.ts @@ -56,7 +56,7 @@ export namespace githubSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: userId } + ? { entityRef: { name: userId } } : undefined, }, ); diff --git a/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts b/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts index b235f7b4bb..d5715f7e91 100644 --- a/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-gitlab-provider/src/resolvers.ts @@ -56,7 +56,7 @@ export namespace gitlabSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); diff --git a/plugins/auth-backend-module-google-provider/src/resolvers.ts b/plugins/auth-backend-module-google-provider/src/resolvers.ts index c9ba884cfb..297ac0da6e 100644 --- a/plugins/auth-backend-module-google-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-google-provider/src/resolvers.ts @@ -57,7 +57,7 @@ export namespace googleSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: profile.email } + ? { entityRef: { name: profile.email } } : undefined, }, ); diff --git a/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts b/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts index 5090e26c5a..0ce276522e 100644 --- a/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts @@ -57,7 +57,7 @@ export namespace microsoftSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: profile.email } + ? { entityRef: { name: profile.email } } : undefined, }, ); @@ -96,7 +96,7 @@ export namespace microsoftSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); diff --git a/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts b/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts index 7bf098a308..bad3f015c8 100644 --- a/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-oauth2-provider/src/resolvers.ts @@ -56,7 +56,7 @@ export namespace oauth2SignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts index a31e1958dc..8ac639b3c0 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts @@ -46,7 +46,7 @@ export namespace oauth2ProxySignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name } + ? { entityRef: { name } } : undefined, }, ); diff --git a/plugins/auth-backend-module-okta-provider/src/resolvers.ts b/plugins/auth-backend-module-okta-provider/src/resolvers.ts index b3b2a33493..cdb37dbaae 100644 --- a/plugins/auth-backend-module-okta-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-okta-provider/src/resolvers.ts @@ -58,7 +58,7 @@ export namespace oktaSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: profile.email } + ? { entityRef: { name: profile.email } } : undefined, }, ); diff --git a/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts b/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts index 4a617589da..56710472be 100644 --- a/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-onelogin-provider/src/resolvers.ts @@ -56,7 +56,7 @@ export namespace oneLoginSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: id } + ? { entityRef: { name: id } } : undefined, }, ); diff --git a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts index e4deaaef33..4f9b33d021 100644 --- a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts +++ b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts @@ -142,13 +142,15 @@ export class CatalogAuthResolverContext implements AuthResolverContext { async signInWithCatalogUser( query: AuthResolverCatalogUserQuery, options?: { - dangerousEntityRefFallback?: - | string - | { - kind?: string; - namespace?: string; - name: string; - }; + dangerousEntityRefFallback?: { + entityRef: + | string + | { + kind?: string; + namespace?: string; + name: string; + }; + }; }, ) { try { @@ -165,21 +167,14 @@ export class CatalogAuthResolverContext implements AuthResolverContext { }, }); } catch (error) { - if (error?.name !== 'NotFoundError') { + if ( + error?.name !== 'NotFoundError' || + !options?.dangerousEntityRefFallback + ) { throw error; } - if (!options?.dangerousEntityRefFallback) { - this.logger.error( - 'Failed to sign-in, unable to resolve user identity. For non-production environments, manually provision the user or disable the user provisioning requirement by setting the dangerouslyAllowSignInWithoutUserInCatalog option.', - ); - - throw new Error( - 'Failed to sign-in, unable to resolve user identity. Please verify that your catalog contains the expected User entities that would match your configured sign-in resolver.', - ); - } - const userEntityRef = stringifyEntityRef( - parseEntityRef(options.dangerousEntityRefFallback, { + parseEntityRef(options.dangerousEntityRefFallback.entityRef, { defaultKind: 'User', defaultNamespace: DEFAULT_NAMESPACE, }), diff --git a/plugins/auth-node/report.api.md b/plugins/auth-node/report.api.md index 64716dfe5c..090f981636 100644 --- a/plugins/auth-node/report.api.md +++ b/plugins/auth-node/report.api.md @@ -111,13 +111,15 @@ export type AuthResolverContext = { signInWithCatalogUser( query: AuthResolverCatalogUserQuery, options?: { - dangerousEntityRefFallback?: - | string - | { - kind?: string; - namespace?: string; - name: string; - }; + dangerousEntityRefFallback?: { + entityRef: + | string + | { + kind?: string; + namespace?: string; + name: string; + }; + }; }, ): Promise; resolveOwnershipEntityRefs(entity: Entity): Promise<{ diff --git a/plugins/auth-node/src/sign-in/commonSignInResolvers.ts b/plugins/auth-node/src/sign-in/commonSignInResolvers.ts index 307ebbfef5..2b7442f746 100644 --- a/plugins/auth-node/src/sign-in/commonSignInResolvers.ts +++ b/plugins/auth-node/src/sign-in/commonSignInResolvers.ts @@ -74,7 +74,7 @@ export namespace commonSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: noPlusEmail } + ? { entityRef: { name: noPlusEmail } } : undefined, }, ); @@ -122,7 +122,7 @@ export namespace commonSignInResolvers { { dangerousEntityRefFallback: options?.dangerouslyAllowSignInWithoutUserInCatalog - ? { name: localPart } + ? { entityRef: { name: localPart } } : undefined, }, ); diff --git a/plugins/auth-node/src/types.ts b/plugins/auth-node/src/types.ts index b628313a4f..8d6b8f34fb 100644 --- a/plugins/auth-node/src/types.ts +++ b/plugins/auth-node/src/types.ts @@ -172,13 +172,15 @@ export type AuthResolverContext = { signInWithCatalogUser( query: AuthResolverCatalogUserQuery, options?: { - dangerousEntityRefFallback?: - | string - | { - kind?: string; - namespace?: string; - name: string; - }; + dangerousEntityRefFallback?: { + entityRef: + | string + | { + kind?: string; + namespace?: string; + name: string; + }; + }; }, ): Promise; From 9754e48e6603fcea4438ad8e9eb763831f46b9c2 Mon Sep 17 00:00:00 2001 From: Mohit Nain Date: Wed, 7 May 2025 11:49:59 +0530 Subject: [PATCH 052/143] Update architecture-overview.md Signed-off-by: Mohit Nain --- docs/overview/architecture-overview.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index a3c15aa480..035be95769 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -267,14 +267,14 @@ require a database to work with. The Backstage backend and its built-in plugins are based on the [Knex](http://knexjs.org/) library, and set up a separate logical database per plugin. This gives great isolation and lets them perform migrations and evolve -separate from each other. +separately from each other. -The Knex library supports a multitude of databases, but Backstage is at the time -of writing tested primarily against two of them: SQLite, which is mainly used as +The Knex library supports a multitude of databases, but Backstage at this time +of writing is tested primarily against two of them: SQLite, which is mainly used as an in-memory mock/test database, and PostgreSQL, which is the preferred production database. Other databases such as the MySQL variants are reported to work but -[aren't tested as fully](https://github.com/backstage/backstage/issues/2460) +[aren't fully tested](https://github.com/backstage/backstage/issues/2460) yet. ## Cache From f7ca0fee7a2d0fd2fed495e27ee5427a81e7ebe1 Mon Sep 17 00:00:00 2001 From: Benjamin Janssens Date: Wed, 7 May 2025 15:25:18 +0200 Subject: [PATCH 053/143] feat(home): add entity presentation api to home page widgets Signed-off-by: Benjamin Janssens --- .changeset/dry-shirts-film.md | 5 +++++ plugins/home/src/components/VisitList/ItemName.tsx | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .changeset/dry-shirts-film.md diff --git a/.changeset/dry-shirts-film.md b/.changeset/dry-shirts-film.md new file mode 100644 index 0000000000..35ada3969a --- /dev/null +++ b/.changeset/dry-shirts-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Added the Catalog presentation API to the HomePageRecentlyVisited and HomePageTopVisited components diff --git a/plugins/home/src/components/VisitList/ItemName.tsx b/plugins/home/src/components/VisitList/ItemName.tsx index bf02b1ba07..7140caf61b 100644 --- a/plugins/home/src/components/VisitList/ItemName.tsx +++ b/plugins/home/src/components/VisitList/ItemName.tsx @@ -18,16 +18,28 @@ import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import { Visit } from '../../api/VisitsApi'; import { Link } from '@backstage/core-components'; +import { EntityRefLink } from '@backstage/plugin-catalog-react'; -const useStyles = makeStyles(_theme => ({ +const useStyles = makeStyles(theme => ({ name: { marginLeft: '0.8rem', marginRight: '0.8rem', + fontSize: theme.typography.body1.fontSize, }, })); export const ItemName = ({ visit }: { visit: Visit }) => { const classes = useStyles(); + if (visit.entityRef) + return ( + + ); + return ( Date: Wed, 7 May 2025 15:37:38 +0200 Subject: [PATCH 054/143] search-backend-module-elasticsearch: pass missing queryOptions Signed-off-by: Vincenzo Scamporlino --- .../src/engines/ElasticSearchSearchEngine.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index e2c8a48cd6..2bd5c88f89 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -192,6 +192,9 @@ export class ElasticSearchSearchEngine implements SearchEngine { config.getOptional( 'search.elasticsearch.highlightOptions', ), + config.getOptional( + 'search.elasticsearch.queryOptions', + ), ); for (const indexTemplate of this.readIndexTemplateConfig( From 01f772ca371a90f1eee1705adab1756499f35200 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 7 May 2025 15:39:29 +0200 Subject: [PATCH 055/143] search-backend-module-elasticsearch: queryOptions changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/grumpy-phones-kiss.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/grumpy-phones-kiss.md diff --git a/.changeset/grumpy-phones-kiss.md b/.changeset/grumpy-phones-kiss.md new file mode 100644 index 0000000000..96b6ff05d9 --- /dev/null +++ b/.changeset/grumpy-phones-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Fixed an issue where the `search.elasticsearch.queryOptions` config were not picked up by the `ElasticSearchSearchEngine`. From 8e0f15f6de97753b2b47146c53a2601e4d479ec6 Mon Sep 17 00:00:00 2001 From: Gustavo Lira Date: Mon, 28 Apr 2025 17:35:52 -0300 Subject: [PATCH 056/143] add note about visibility of entity-fetch audit events in logs add clarification about visibility of entity-fetch audit events in logs Signed-off-by: Gustavo Lira --- .changeset/every-bottles-grow.md | 5 +++++ plugins/catalog-backend/README.md | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/every-bottles-grow.md diff --git a/.changeset/every-bottles-grow.md b/.changeset/every-bottles-grow.md new file mode 100644 index 0000000000..a61a7b42b9 --- /dev/null +++ b/.changeset/every-bottles-grow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +"Added a note clarifying that `entity-fetch` audit events are not visible by default in the logs and are only displayed when the log severity level is adjusted." diff --git a/plugins/catalog-backend/README.md b/plugins/catalog-backend/README.md index 680adc0bcd..0d544160d0 100644 --- a/plugins/catalog-backend/README.md +++ b/plugins/catalog-backend/README.md @@ -94,6 +94,7 @@ The Catalog backend emits audit events for various operations. Events are groupe **Entity Events:** - **`entity-fetch`**: Retrieves entities. +- **Note:** By default, `entity-fetch` audit events are not visible in the log output. This is because these events are classified with a severity level of "low", which maps to the "debug" log level. The default log level in Backstage is "info", so debug-level events (severity "low") are filtered out. To see `entity-fetch` events in the logs, adjust the Auditor Service configuration by setting `backend.auditor.severityLogLevelMappings.low` to `info` in your `app-config.yaml`. For more information, refer to the [Auditor Service documentation on severity levels and default mappings](https://backstage.io/docs/backend-system/core-services/auditor/#severity-levels-and-default-mappings). Filter on `queryType`. From a274e0a362dc3e68ad8df6a83fe7e61f181eda34 Mon Sep 17 00:00:00 2001 From: Matt Benson Date: Tue, 29 Apr 2025 11:07:24 -0500 Subject: [PATCH 057/143] Migrate custom fields to new schema factory function; standardize field descriptions to prefer ui:description and present consistently, utilizing ScaffolderField component where possible. Signed-off-by: Matt Benson --- .changeset/violet-breads-obey.md | 7 + plugins/scaffolder/report-alpha.api.md | 2 + plugins/scaffolder/report.api.md | 52 +++--- .../fields/EntityNamePicker/schema.ts | 9 +- .../fields/EntityPicker/EntityPicker.test.tsx | 126 +++++++++++++++ .../fields/EntityPicker/EntityPicker.tsx | 2 +- .../components/fields/EntityPicker/schema.ts | 92 +++++------ .../EntityTagsPicker.test.tsx | 148 ++++++++++++++++++ .../EntityTagsPicker/EntityTagsPicker.tsx | 31 +++- .../fields/EntityTagsPicker/schema.ts | 44 +++--- .../MultiEntityPicker.test.tsx | 102 +++++++++++- .../MultiEntityPicker/MultiEntityPicker.tsx | 22 ++- .../fields/MultiEntityPicker/schema.ts | 74 ++++----- .../MyGroupsPicker/MyGroupsPicker.test.tsx | 102 ++++++++++++ .../fields/MyGroupsPicker/MyGroupsPicker.tsx | 16 +- .../fields/MyGroupsPicker/schema.ts | 26 ++- .../OwnedEntityPicker/OwnedEntityPicker.tsx | 41 +++-- .../fields/OwnedEntityPicker/schema.ts | 75 ++++----- .../components/fields/OwnerPicker/schema.ts | 68 ++++---- .../RepoBranchPicker.test.tsx | 102 ++++++++++++ .../RepoBranchPicker/RepoBranchPicker.tsx | 9 +- .../fields/RepoBranchPicker/schema.ts | 103 ++++++------ .../RepoUrlPicker/RepoUrlPicker.test.tsx | 104 ++++++++++++ .../fields/RepoUrlPicker/RepoUrlPicker.tsx | 10 +- .../components/fields/RepoUrlPicker/schema.ts | 7 +- .../fields/SecretInput/SecretInput.test.tsx | 89 +++++++++++ .../fields/SecretInput/SecretInput.tsx | 3 +- plugins/scaffolder/src/translation.ts | 4 + 28 files changed, 1154 insertions(+), 316 deletions(-) create mode 100644 .changeset/violet-breads-obey.md create mode 100644 plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.test.tsx diff --git a/.changeset/violet-breads-obey.md b/.changeset/violet-breads-obey.md new file mode 100644 index 0000000000..f892e91ee2 --- /dev/null +++ b/.changeset/violet-breads-obey.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Migrate custom fields to new schema factory function; +standardize field descriptions to prefer ui:description and present consistently, +utilizing ScaffolderField component where possible. diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index de088224b8..69fcec11e6 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -289,6 +289,8 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'fields.entityPicker.description': 'An entity from the catalog'; readonly 'fields.entityTagsPicker.title': 'Tags'; readonly 'fields.entityTagsPicker.description': "Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters"; + readonly 'fields.multiEntityPicker.title': 'Entity'; + readonly 'fields.multiEntityPicker.description': 'An entity from the catalog'; readonly 'fields.myGroupsPicker.title': 'Entity'; readonly 'fields.myGroupsPicker.description': 'An entity from the catalog'; readonly 'fields.ownedEntityPicker.title': 'Entity'; diff --git a/plugins/scaffolder/report.api.md b/plugins/scaffolder/report.api.md index b929d7be5b..b44889cded 100644 --- a/plugins/scaffolder/report.api.md +++ b/plugins/scaffolder/report.api.md @@ -71,7 +71,7 @@ export type CustomFieldValidator = // @public export const EntityNamePickerFieldExtension: FieldExtensionComponent_2< string, - {} + any >; // @public @@ -104,7 +104,7 @@ export const EntityPickerFieldExtension: FieldExtensionComponent_2< >; // @public (undocumented) -export const EntityPickerFieldSchema: FieldSchema< +export const EntityPickerFieldSchema: FieldSchema_2< string, { defaultKind?: string | undefined; @@ -133,8 +133,9 @@ export const EntityPickerFieldSchema: FieldSchema< >; // @public -export type EntityPickerUiOptions = - typeof EntityPickerFieldSchema.uiOptionsType; +export type EntityPickerUiOptions = NonNullable< + (typeof EntityPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; // @public export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< @@ -147,7 +148,7 @@ export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< >; // @public (undocumented) -export const EntityTagsPickerFieldSchema: FieldSchema< +export const EntityTagsPickerFieldSchema: FieldSchema_2< string[], { helperText?: string | undefined; @@ -157,8 +158,9 @@ export const EntityTagsPickerFieldSchema: FieldSchema< >; // @public -export type EntityTagsPickerUiOptions = - typeof EntityTagsPickerFieldSchema.uiOptionsType; +export type EntityTagsPickerUiOptions = NonNullable< + (typeof EntityTagsPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; // @public @deprecated (undocumented) export type FieldExtensionComponent<_TReturnValue, _TInputProps> = @@ -233,27 +235,19 @@ export const MultiEntityPickerFieldExtension: FieldExtensionComponent_2< // @public export const MyGroupsPickerFieldExtension: FieldExtensionComponent_2< string, - { - title?: string | undefined; - description?: string | undefined; - } + any >; // @public -export const MyGroupsPickerFieldSchema: FieldSchema< - string, - { - title?: string | undefined; - description?: string | undefined; - } ->; +export const MyGroupsPickerFieldSchema: FieldSchema_2; // @public export const MyGroupsPickerSchema: CustomFieldExtensionSchema_2; // @public -export type MyGroupsPickerUiOptions = - typeof MyGroupsPickerFieldSchema.uiOptionsType; +export type MyGroupsPickerUiOptions = NonNullable< + (typeof MyGroupsPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; // @public export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2< @@ -285,7 +279,7 @@ export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2< >; // @public (undocumented) -export const OwnedEntityPickerFieldSchema: FieldSchema< +export const OwnedEntityPickerFieldSchema: FieldSchema_2< string, { defaultKind?: string | undefined; @@ -314,8 +308,9 @@ export const OwnedEntityPickerFieldSchema: FieldSchema< >; // @public -export type OwnedEntityPickerUiOptions = - typeof OwnedEntityPickerFieldSchema.uiOptionsType; +export type OwnedEntityPickerUiOptions = NonNullable< + (typeof OwnedEntityPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; // @public export const OwnerPickerFieldExtension: FieldExtensionComponent_2< @@ -346,7 +341,7 @@ export const OwnerPickerFieldExtension: FieldExtensionComponent_2< >; // @public (undocumented) -export const OwnerPickerFieldSchema: FieldSchema< +export const OwnerPickerFieldSchema: FieldSchema_2< string, { defaultNamespace?: string | false | undefined; @@ -374,7 +369,9 @@ export const OwnerPickerFieldSchema: FieldSchema< >; // @public -export type OwnerPickerUiOptions = typeof OwnerPickerFieldSchema.uiOptionsType; +export type OwnerPickerUiOptions = NonNullable< + (typeof OwnerPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; // @public export const RepoBranchPickerFieldExtension: FieldExtensionComponent_2< @@ -462,8 +459,9 @@ export const RepoUrlPickerFieldSchema: FieldSchema_2< >; // @public @deprecated -export type RepoUrlPickerUiOptions = - typeof RepoUrlPickerFieldSchema.uiOptionsType; +export type RepoUrlPickerUiOptions = NonNullable< + (typeof RepoUrlPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; export { ReviewStepProps }; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts index 27e33befb5..fe4765b8b8 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; -const EntityNamePickerFieldSchema = makeFieldSchemaFromZod(z.string()); +const EntityNamePickerFieldSchema = makeFieldSchema({ + output: z => z.string(), +}); export const EntityNamePickerSchema = EntityNamePickerFieldSchema.schema; -export type EntityNamePickerProps = typeof EntityNamePickerFieldSchema.type; +export type EntityNamePickerProps = typeof EntityNamePickerFieldSchema.TProps; diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index 2098e3e07d..97c90b2aa5 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -28,6 +28,8 @@ import { EntityPickerProps } from './schema'; import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; import { DefaultEntityPresentationApi } from '@backstage/plugin-catalog'; import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { scaffolderTranslationRef } from '../../../translation'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'scaffolder.backstage.io/v1beta3', @@ -891,4 +893,128 @@ describe('', () => { expect(onChange).toHaveBeenCalledWith(undefined); }); }); + + describe('EntityPicker description', () => { + const description = { + fromSchema: 'EntityPicker description from schema', + fromUiSchema: 'EntityPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string; default?: string }; + + beforeEach(() => { + const RealWrapper = Wrapper; + Wrapper = ({ children }: { children?: ReactNode }) => { + const { t } = useTranslationRef(scaffolderTranslationRef); + description.default = t('fields.entityPicker.description'); + return {children}; + }; + }); + it('presents default description', async () => { + uiSchema = { + 'ui:options': { + catalogFilter: [ + { + kind: ['Group'], + 'metadata.name': 'test-entity', + }, + { + kind: ['User'], + 'metadata.name': 'test-entity', + }, + ], + }, + }; + props = { + onChange, + schema, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(getByText(description.default!)).toBeInTheDocument(); + expect(queryByText(description.fromSchema)).toBe(null); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents schema description', async () => { + uiSchema = { + 'ui:options': { + catalogFilter: [ + { + kind: ['Group'], + 'metadata.name': 'test-entity', + }, + { + kind: ['User'], + 'metadata.name': 'test-entity', + }, + ], + }, + }; + props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + uiSchema = { + 'ui:options': { + catalogFilter: [ + { + kind: ['Group'], + 'metadata.name': 'test-entity', + }, + { + kind: ['User'], + 'metadata.name': 'test-entity', + }, + ], + }, + 'ui:description': description.fromUiSchema, + }; + props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 26f88ea85d..d2197d4426 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -185,7 +185,7 @@ export const EntityPicker = (props: EntityPickerProps) => { return ( z.string(), + uiOptions: z => + z.object({ + /** + * @deprecated Use `catalogFilter` instead. + */ + allowedKinds: z + .array(z.string()) + .optional() + .describe( + 'DEPRECATED: Use `catalogFilter` instead. List of kinds of entities to derive options from', + ), + defaultKind: z + .string() + .optional() + .describe( + 'The default entity kind. Options of this kind will not be prefixed.', + ), + allowArbitraryValues: z + .boolean() + .optional() + .describe('Whether to allow arbitrary user input. Defaults to true'), + defaultNamespace: z + .union([z.string(), z.literal(false)]) + .optional() + .describe( + 'The default namespace. Options with this namespace will not be prefixed.', + ), + catalogFilter: z + .array(entityQueryFilterExpressionSchema) + .or(entityQueryFilterExpressionSchema) + .optional() + .describe('List of key-value filter expression for entities'), + }), +}); /** * The input props that can be specified under `ui:options` for the @@ -71,14 +72,15 @@ export const EntityPickerFieldSchema = makeFieldSchemaFromZod( * * @public */ -export type EntityPickerUiOptions = - typeof EntityPickerFieldSchema.uiOptionsType; +export type EntityPickerUiOptions = NonNullable< + (typeof EntityPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; -export type EntityPickerProps = typeof EntityPickerFieldSchema.type; +export type EntityPickerProps = typeof EntityPickerFieldSchema.TProps; export const EntityPickerSchema = EntityPickerFieldSchema.schema; -export type EntityPickerFilterQuery = z.TypeOf< +export type EntityPickerFilterQuery = zod.TypeOf< typeof entityQueryFilterExpressionSchema >; diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.test.tsx new file mode 100644 index 0000000000..98091f5098 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.test.tsx @@ -0,0 +1,148 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; +import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { ComponentType, PropsWithChildren, ReactNode } from 'react'; +import { EntityTagsPicker } from './EntityTagsPicker'; +import { EntityTagsPickerProps } from './schema'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { scaffolderTranslationRef } from '../../../translation'; + +const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind, + metadata: { namespace, name }, +}); + +describe('', () => { + const entities: Entity[] = [ + makeEntity('Group', 'default', 'team-a'), + makeEntity('Group', 'default', 'squad-b'), + ]; + const onChange = jest.fn(); + const schema = { type: 'array', items: { type: 'string' } }; + const uiSchema: EntityTagsPickerProps['uiSchema'] = { + 'ui:options': {}, + }; + const rawErrors: string[] = []; + const formData = undefined; + + let props: FieldProps; + + const catalogApi = catalogApiMock.mock({ + getEntities: jest.fn(async () => ({ items: entities })), + }); + + let Wrapper: ComponentType>; + + beforeEach(() => { + Wrapper = ({ children }: { children?: ReactNode }) => ( + + {children} + + ); + }); + + afterEach(() => jest.resetAllMocks()); + + describe('EntityTagsPicker description', () => { + const description = { + fromSchema: 'EntityTagsPicker description from schema', + fromUiSchema: 'EntityTagsPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string; default?: string }; + + beforeEach(() => { + const RealWrapper = Wrapper; + Wrapper = ({ children }: { children?: ReactNode }) => { + const { t } = useTranslationRef(scaffolderTranslationRef); + description.default = t('fields.entityTagsPicker.description'); + return {children}; + }; + }); + it('presents default description', async () => { + props = { + onChange, + schema, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(getByText(description.default!)).toBeInTheDocument(); + expect(queryByText(description.fromSchema)).toBe(null); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents schema description', async () => { + props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema: { + ...uiSchema, + 'ui:description': description.fromUiSchema, + }, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx index 3cfa16de23..7d63526fe4 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx @@ -20,12 +20,12 @@ import { GetEntityFacetsRequest } from '@backstage/catalog-client'; import { makeValidator } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import FormControl from '@material-ui/core/FormControl'; import TextField from '@material-ui/core/TextField'; import Autocomplete from '@material-ui/lab/Autocomplete'; import { EntityTagsPickerProps } from './schema'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; import { scaffolderTranslationRef } from '../../../translation'; +import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha'; export { EntityTagsPickerSchema } from './schema'; @@ -36,7 +36,19 @@ export { EntityTagsPickerSchema } from './schema'; * @public */ export const EntityTagsPicker = (props: EntityTagsPickerProps) => { - const { formData, onChange, uiSchema } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); + const { + formData, + onChange, + schema: { + title = t('fields.entityTagsPicker.title'), + description = t('fields.entityTagsPicker.description'), + }, + uiSchema, + rawErrors, + required, + errors, + } = props; const catalogApi = useApi(catalogApiRef); const [tagOptions, setTagOptions] = useState([]); const [inputValue, setInputValue] = useState(''); @@ -47,8 +59,6 @@ export const EntityTagsPicker = (props: EntityTagsPickerProps) => { const helperText = uiSchema['ui:options']?.helperText; const isDisabled = uiSchema?.['ui:disabled'] ?? false; - const { t } = useTranslationRef(scaffolderTranslationRef); - const { loading, value: existingTags } = useAsync(async () => { const facet = 'metadata.tags'; const tagsRequest: GetEntityFacetsRequest = { facets: [facet] }; @@ -97,7 +107,13 @@ export const EntityTagsPicker = (props: EntityTagsPickerProps) => { useEffectOnce(() => onChange(formData || [])); return ( - + { renderInput={params => ( setInputValue(e.target.value)} error={inputError} - helperText={helperText ?? t('fields.entityTagsPicker.description')} FormHelperTextProps={{ margin: 'dense', style: { marginLeft: 0 } }} /> )} /> - + ); }; diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts index 6677d16e98..d1a300f5c8 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts @@ -13,30 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; /** * @public */ -export const EntityTagsPickerFieldSchema = makeFieldSchemaFromZod( - z.array(z.string()), - z.object({ - kinds: z - .array(z.string()) - .optional() - .describe('List of kinds of entities to derive tags from'), - showCounts: z - .boolean() - .optional() - .describe('Whether to show usage counts per tag'), - helperText: z.string().optional().describe('Helper text to display'), - }), -); +export const EntityTagsPickerFieldSchema = makeFieldSchema({ + output: z => z.array(z.string()), + uiOptions: z => + z.object({ + kinds: z + .array(z.string()) + .optional() + .describe('List of kinds of entities to derive tags from'), + showCounts: z + .boolean() + .optional() + .describe('Whether to show usage counts per tag'), + helperText: z + .string() + .optional() + .describe( + 'Helper text to display; DEPRECATED, simply use ui:description', + ), + }), +}); export const EntityTagsPickerSchema = EntityTagsPickerFieldSchema.schema; -export type EntityTagsPickerProps = typeof EntityTagsPickerFieldSchema.type; +export type EntityTagsPickerProps = typeof EntityTagsPickerFieldSchema.TProps; /** * The input props that can be specified under `ui:options` for the @@ -44,5 +49,6 @@ export type EntityTagsPickerProps = typeof EntityTagsPickerFieldSchema.type; * * @public */ -export type EntityTagsPickerUiOptions = - typeof EntityTagsPickerFieldSchema.uiOptionsType; +export type EntityTagsPickerUiOptions = NonNullable< + (typeof EntityTagsPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx index eb80d47e78..acae3418b9 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx @@ -30,6 +30,8 @@ import { MultiEntityPickerProps } from './schema'; import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; import { DefaultEntityPresentationApi } from '@backstage/plugin-catalog'; import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { scaffolderTranslationRef } from '../../../translation'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'scaffolder.backstage.io/v1beta3', @@ -43,7 +45,7 @@ describe('', () => { makeEntity('Group', 'default', 'squad-b'), ]; const onChange = jest.fn(); - const schema = {}; + const schema = { type: 'array', items: { type: 'string' } }; const required = false; let uiSchema: MultiEntityPickerProps['uiSchema']; const rawErrors: string[] = []; @@ -847,4 +849,102 @@ describe('', () => { ]); }); }); + + describe('MultiEntityPicker description', () => { + const description = { + fromSchema: 'MultiEntityPicker description from schema', + fromUiSchema: 'MultiEntityPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string; default?: string }; + + beforeEach(() => { + const RealWrapper = Wrapper; + Wrapper = ({ children }: { children?: ReactNode }) => { + const { t } = useTranslationRef(scaffolderTranslationRef); + description.default = t('fields.multiEntityPicker.description'); + return {children}; + }; + uiSchema = { + 'ui:options': { + catalogFilter: [ + { + kind: ['Group'], + 'metadata.name': 'test-entity', + }, + { + kind: ['User'], + 'metadata.name': 'test-entity', + }, + ], + }, + }; + }); + it('presents default description', async () => { + props = { + onChange, + schema, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(getByText(description.default!)).toBeInTheDocument(); + expect(queryByText(description.fromSchema)).toBe(null); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents schema description', async () => { + props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema: { + ...uiSchema, + 'ui:description': description.fromUiSchema, + }, + rawErrors, + formData, + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx index e6a535af41..e7dcf0f996 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx @@ -30,7 +30,6 @@ import { EntityRefPresentationSnapshot, } from '@backstage/plugin-catalog-react'; import TextField from '@material-ui/core/TextField'; -import FormControl from '@material-ui/core/FormControl'; import Autocomplete, { AutocompleteChangeReason, } from '@material-ui/lab/Autocomplete'; @@ -44,6 +43,9 @@ import { MultiEntityPickerFilterQuery, } from './schema'; import { VirtualizedListbox } from '../VirtualizedListbox'; +import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { scaffolderTranslationRef } from '../../../translation'; export { MultiEntityPickerSchema } from './schema'; @@ -52,14 +54,19 @@ export { MultiEntityPickerSchema } from './schema'; * field extension. */ export const MultiEntityPicker = (props: MultiEntityPickerProps) => { + const { t } = useTranslationRef(scaffolderTranslationRef); const { onChange, - schema: { title = 'Entity', description = 'An entity from the catalog' }, + schema: { + title = t('fields.multiEntityPicker.title'), + description = t('fields.multiEntityPicker.description'), + }, required, uiSchema, rawErrors, formData, idSchema, + errors, } = props; const catalogFilter = buildCatalogFilter(uiSchema); @@ -144,10 +151,12 @@ export const MultiEntityPicker = (props: MultiEntityPickerProps) => { }, [entities, onChange, required, allowArbitraryValues]); return ( - 0 && !formData} + disabled={isDisabled} + errors={errors} > { label={title} disabled={isDisabled} margin="dense" - helperText={description} FormHelperTextProps={{ margin: 'dense', style: { marginLeft: 0 }, @@ -197,7 +205,7 @@ export const MultiEntityPicker = (props: MultiEntityPickerProps) => { )} ListboxComponent={VirtualizedListbox} /> - + ); }; diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/MultiEntityPicker/schema.ts index 2621157d02..667b4638b8 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/schema.ts @@ -13,55 +13,57 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; +import { z as zod } from 'zod'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; -export const entityQueryFilterExpressionSchema = z.record( - z +export const entityQueryFilterExpressionSchema = zod.record( + zod .string() - .or(z.object({ exists: z.boolean().optional() })) - .or(z.array(z.string())), + .or(zod.object({ exists: zod.boolean().optional() })) + .or(zod.array(zod.string())), ); -export const MultiEntityPickerFieldSchema = makeFieldSchemaFromZod( - z.array(z.string()), - z.object({ - defaultKind: z - .string() - .optional() - .describe( - 'The default entity kind. Options of this kind will not be prefixed.', - ), - allowArbitraryValues: z - .boolean() - .optional() - .describe('Whether to allow arbitrary user input. Defaults to true'), - defaultNamespace: z - .union([z.string(), z.literal(false)]) - .optional() - .describe( - 'The default namespace. Options with this namespace will not be prefixed.', - ), - catalogFilter: z - .array(entityQueryFilterExpressionSchema) - .or(entityQueryFilterExpressionSchema) - .optional() - .describe('List of key-value filter expression for entities'), - }), -); +export const MultiEntityPickerFieldSchema = makeFieldSchema({ + output: z => z.array(z.string()), + uiOptions: z => + z.object({ + defaultKind: z + .string() + .optional() + .describe( + 'The default entity kind. Options of this kind will not be prefixed.', + ), + allowArbitraryValues: z + .boolean() + .optional() + .describe('Whether to allow arbitrary user input. Defaults to true'), + defaultNamespace: z + .union([z.string(), z.literal(false)]) + .optional() + .describe( + 'The default namespace. Options with this namespace will not be prefixed.', + ), + catalogFilter: z + .array(entityQueryFilterExpressionSchema) + .or(entityQueryFilterExpressionSchema) + .optional() + .describe('List of key-value filter expression for entities'), + }), +}); /** * The input props that can be specified under `ui:options` for the * `EntityPicker` field extension. */ -export type MultiEntityPickerUiOptions = - typeof MultiEntityPickerFieldSchema.uiOptionsType; +export type MultiEntityPickerUiOptions = NonNullable< + (typeof MultiEntityPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; -export type MultiEntityPickerProps = typeof MultiEntityPickerFieldSchema.type; +export type MultiEntityPickerProps = typeof MultiEntityPickerFieldSchema.TProps; export const MultiEntityPickerSchema = MultiEntityPickerFieldSchema.schema; -export type MultiEntityPickerFilterQuery = z.TypeOf< +export type MultiEntityPickerFilterQuery = zod.TypeOf< typeof entityQueryFilterExpressionSchema >; diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx index 6e0a3b81bc..dcba013093 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx @@ -35,6 +35,9 @@ import { import userEvent from '@testing-library/user-event'; import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; import { DefaultEntityPresentationApi } from '@backstage/plugin-catalog'; +import { ComponentType, PropsWithChildren, ReactNode } from 'react'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { scaffolderTranslationRef } from '../../../translation'; const mockIdentityApi = mockApis.identity({ userEntityRef: 'user:default/bob', @@ -99,6 +102,7 @@ describe('', () => { onChange, schema, required, + uiSchema: {}, } as unknown as FieldProps; await renderInTestApp( @@ -175,6 +179,7 @@ describe('', () => { onChange, schema, required, + uiSchema: {}, } as unknown as FieldProps; const { queryByText, getByRole } = await renderInTestApp( @@ -236,6 +241,7 @@ describe('', () => { onChange, schema, required, + uiSchema: {}, } as unknown as FieldProps; const { getByRole } = await renderInTestApp( @@ -299,6 +305,7 @@ describe('', () => { onChange, schema, required, + uiSchema: {}, formData: 'group:default/group1', } as unknown as FieldProps; @@ -327,4 +334,99 @@ describe('', () => { expect(inputFieldValue).toEqual(userGroups[0].metadata.title); }); + + describe('MyGroupsPicker description', () => { + const description = { + fromSchema: 'MyGroupsPicker description from schema', + fromUiSchema: 'MyGroupsPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string; default?: string }; + + let Wrapper: ComponentType>; + + beforeEach(() => { + Wrapper = ({ children }: { children?: ReactNode }) => { + const { t } = useTranslationRef(scaffolderTranslationRef); + description.default = t('fields.myGroupsPicker.description'); + return ( + + {children} + + ); + }; + }); + it('presents default description', async () => { + const props = { + onChange, + schema, + required: true, + uiSchema: {}, + formData: 'group:default/group1', + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(getByText(description.default!)).toBeInTheDocument(); + expect(queryByText(description.fromSchema)).toBe(null); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents schema description', async () => { + const props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema: {}, + formData: 'group:default/group1', + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + const props = { + onChange, + schema: { + ...schema, + description: description.fromSchema, + }, + required: true, + uiSchema: { + 'ui:description': description.fromUiSchema, + }, + formData: 'group:default/group1', + } as unknown as FieldProps; + + const { getByText, queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(description.default!)).toBe(null); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.tsx b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.tsx index b49a1a1531..e92057c713 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.tsx +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.tsx @@ -21,7 +21,6 @@ import { useApi, } from '@backstage/core-plugin-api'; import TextField from '@material-ui/core/TextField'; -import FormControl from '@material-ui/core/FormControl'; import { MyGroupsPickerProps, MyGroupsPickerSchema } from './schema'; import Autocomplete, { createFilterOptions, @@ -38,6 +37,7 @@ import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { VirtualizedListbox } from '../VirtualizedListbox'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; import { scaffolderTranslationRef } from '../../../translation'; +import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha'; export { MyGroupsPickerSchema }; @@ -52,12 +52,15 @@ export const MyGroupsPicker = (props: MyGroupsPickerProps) => { rawErrors, onChange, formData, + uiSchema, + errors, } = props; const identityApi = useApi(identityApiRef); const catalogApi = useApi(catalogApiRef); const errorApi = useApi(errorApiRef); const entityPresentationApi = useApi(entityPresentationApiRef); + const isDisabled = uiSchema?.['ui:disabled'] ?? false; const { value: groups, loading } = useAsync(async () => { const { userEntityRef } = await identityApi.getBackstageIdentity(); @@ -108,10 +111,12 @@ export const MyGroupsPicker = (props: MyGroupsPickerProps) => { }, [groups, onChange, selectedEntity, required]); return ( - 0} + disabled={isDisabled} + errors={errors} > { {...params} label={title} margin="dense" - helperText={description} FormHelperTextProps={{ margin: 'dense', style: { marginLeft: 0 } }} variant="outlined" required={required} @@ -145,6 +149,6 @@ export const MyGroupsPicker = (props: MyGroupsPickerProps) => { })} ListboxComponent={VirtualizedListbox} /> - + ); }; diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/schema.ts b/plugins/scaffolder/src/components/fields/MyGroupsPicker/schema.ts index d5f8af7c56..6ccda91afb 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/schema.ts @@ -14,42 +14,34 @@ * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; /** * Field schema for the MyGroupsPicker. * @public */ -export const MyGroupsPickerFieldSchema = makeFieldSchemaFromZod( - z.string(), - z.object({ - title: z.string().default('Group').describe('Group'), - description: z - .string() - .default('A group you are part of') - .describe('The group to which the entity belongs'), - }), -); +export const MyGroupsPickerFieldSchema = makeFieldSchema({ + output: z => z.string(), +}); /** * UI options for the MyGroupsPicker. * @public */ -export type MyGroupsPickerUiOptions = - typeof MyGroupsPickerFieldSchema.uiOptionsType; +export type MyGroupsPickerUiOptions = NonNullable< + (typeof MyGroupsPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; + /** * Props for the MyGroupsPicker. * @public */ - -export type MyGroupsPickerProps = typeof MyGroupsPickerFieldSchema.type; +export type MyGroupsPickerProps = typeof MyGroupsPickerFieldSchema.TProps; /** * Schema for the MyGroupsPicker. * @public */ - export const MyGroupsPickerSchema = MyGroupsPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index a7c29c081e..0651066cfb 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -24,6 +24,7 @@ import { OwnedEntityPickerProps } from './schema'; import { EntityPickerProps } from '../EntityPicker/schema'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; import { scaffolderTranslationRef } from '../../../translation'; +import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha'; export { OwnedEntityPickerSchema } from './schema'; @@ -52,22 +53,30 @@ export const OwnedEntityPicker = (props: OwnedEntityPickerProps) => { if (loading) return ( - ( - - )} - options={[]} - /> + + ( + + )} + options={[]} + /> + ); const entityPickerUISchema = buildEntityPickerUISchema( diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts index 2bb75db263..ad5ee34ce1 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts @@ -13,45 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; import { entityQueryFilterExpressionSchema } from '../EntityPicker/schema'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; /** * @public */ -export const OwnedEntityPickerFieldSchema = makeFieldSchemaFromZod( - z.string(), - z.object({ - allowedKinds: z - .array(z.string()) - .optional() - .describe( - 'DEPRECATED: Use `catalogFilter` instead. List of kinds of entities to derive options from', - ), - defaultKind: z - .string() - .optional() - .describe( - 'The default entity kind. Options of this kind will not be prefixed.', - ), - allowArbitraryValues: z - .boolean() - .optional() - .describe('Whether to allow arbitrary user input. Defaults to true'), - defaultNamespace: z - .union([z.string(), z.literal(false)]) - .optional() - .describe( - 'The default namespace. Options with this namespace will not be prefixed.', - ), - catalogFilter: z - .array(entityQueryFilterExpressionSchema) - .or(entityQueryFilterExpressionSchema) - .optional() - .describe('List of key-value filter expression for entities'), - }), -); +export const OwnedEntityPickerFieldSchema = makeFieldSchema({ + output: z => z.string(), + uiOptions: z => + z.object({ + allowedKinds: z + .array(z.string()) + .optional() + .describe( + 'DEPRECATED: Use `catalogFilter` instead. List of kinds of entities to derive options from', + ), + defaultKind: z + .string() + .optional() + .describe( + 'The default entity kind. Options of this kind will not be prefixed.', + ), + allowArbitraryValues: z + .boolean() + .optional() + .describe('Whether to allow arbitrary user input. Defaults to true'), + defaultNamespace: z + .union([z.string(), z.literal(false)]) + .optional() + .describe( + 'The default namespace. Options with this namespace will not be prefixed.', + ), + catalogFilter: z + .array(entityQueryFilterExpressionSchema) + .or(entityQueryFilterExpressionSchema) + .optional() + .describe('List of key-value filter expression for entities'), + }), +}); /** * The input props that can be specified under `ui:options` for the @@ -59,9 +59,10 @@ export const OwnedEntityPickerFieldSchema = makeFieldSchemaFromZod( * * @public */ -export type OwnedEntityPickerUiOptions = - typeof OwnedEntityPickerFieldSchema.uiOptionsType; +export type OwnedEntityPickerUiOptions = NonNullable< + (typeof OwnedEntityPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; -export type OwnedEntityPickerProps = typeof OwnedEntityPickerFieldSchema.type; +export type OwnedEntityPickerProps = typeof OwnedEntityPickerFieldSchema.TProps; export const OwnedEntityPickerSchema = OwnedEntityPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts b/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts index 0dbe2fa74f..3bcb63c91f 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts @@ -13,43 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; import { entityQueryFilterExpressionSchema } from '../EntityPicker/schema'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; /** * @public */ -export const OwnerPickerFieldSchema = makeFieldSchemaFromZod( - z.string(), - z.object({ - /** - * @deprecated Use `catalogFilter` instead. - */ - allowedKinds: z - .array(z.string()) - .default(['Group', 'User']) - .optional() - .describe( - 'DEPRECATED: Use `catalogFilter` instead. List of kinds of entities to derive options from. Defaults to Group and User', - ), - allowArbitraryValues: z - .boolean() - .optional() - .describe('Whether to allow arbitrary user input. Defaults to true'), - defaultNamespace: z - .union([z.string(), z.literal(false)]) - .optional() - .describe( - 'The default namespace. Options with this namespace will not be prefixed.', - ), - catalogFilter: z - .array(entityQueryFilterExpressionSchema) - .or(entityQueryFilterExpressionSchema) - .optional() - .describe('List of key-value filter expression for entities'), - }), -); +export const OwnerPickerFieldSchema = makeFieldSchema({ + output: z => z.string(), + uiOptions: z => + z.object({ + /** + * @deprecated Use `catalogFilter` instead. + */ + allowedKinds: z + .array(z.string()) + .default(['Group', 'User']) + .optional() + .describe( + 'DEPRECATED: Use `catalogFilter` instead. List of kinds of entities to derive options from. Defaults to Group and User', + ), + allowArbitraryValues: z + .boolean() + .optional() + .describe('Whether to allow arbitrary user input. Defaults to true'), + defaultNamespace: z + .union([z.string(), z.literal(false)]) + .optional() + .describe( + 'The default namespace. Options with this namespace will not be prefixed.', + ), + catalogFilter: z + .array(entityQueryFilterExpressionSchema) + .or(entityQueryFilterExpressionSchema) + .optional() + .describe('List of key-value filter expression for entities'), + }), +}); /** * The input props that can be specified under `ui:options` for the @@ -57,7 +57,9 @@ export const OwnerPickerFieldSchema = makeFieldSchemaFromZod( * * @public */ -export type OwnerPickerUiOptions = typeof OwnerPickerFieldSchema.uiOptionsType; +export type OwnerPickerUiOptions = NonNullable< + (typeof OwnerPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; export type OwnerPickerProps = typeof OwnerPickerFieldSchema.type; diff --git a/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.test.tsx index ba1b9642fd..2d479d346a 100644 --- a/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.test.tsx @@ -29,9 +29,11 @@ import { scaffolderApiRef, useTemplateSecrets, ScaffolderRJSFField, + ScaffolderRJSFFormProps as FormProps, } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent, screen } from '@testing-library/react'; import { RepoBranchPicker } from './RepoBranchPicker'; +import { ComponentType, PropsWithChildren, ReactNode } from 'react'; describe('RepoBranchPicker', () => { const mockIntegrationsApi: Partial = { @@ -333,4 +335,104 @@ describe('RepoBranchPicker', () => { expect(getByText('abc123')).toBeInTheDocument(); }); }); + + describe('RepoBranchPicker description', () => { + const description = { + fromSchema: 'RepoBranchPicker description from schema', + fromUiSchema: 'RepoBranchPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string }; + + let Wrapper: ComponentType>; + + beforeEach(() => { + Wrapper = ({ children }: { children?: ReactNode }) => { + return ( + + {children} + + ); + }; + }); + it('omits description', async () => { + const props = { + validator, + schema: { type: 'string' }, + uiSchema: { 'ui:field': 'RepoBranchPicker' }, + fields: { + RepoBranchPicker: RepoBranchPicker as ScaffolderRJSFField, + }, + formContext: { + formData: {}, + }, + } as unknown as FormProps; + + const { container } = await renderInTestApp( + +
+ , + ); + expect( + container.getElementsByClassName('MuiTypography-body1'), + ).toHaveLength(0); + }); + + it('presents schema description', async () => { + const props = { + validator, + schema: { type: 'string', description: description.fromSchema }, + uiSchema: { 'ui:field': 'RepoBranchPicker' }, + fields: { + RepoBranchPicker: RepoBranchPicker as ScaffolderRJSFField, + }, + formContext: { + formData: {}, + }, + } as unknown as FormProps; + + const { container, getByText, queryByText } = await renderInTestApp( + + + , + ); + expect( + container.getElementsByClassName('MuiTypography-body1'), + ).toHaveLength(1); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + const props = { + validator, + schema: { type: 'string', description: description.fromSchema }, + uiSchema: { + 'ui:field': 'RepoBranchPicker', + 'ui:description': description.fromUiSchema, + }, + fields: { + RepoBranchPicker: RepoBranchPicker as ScaffolderRJSFField, + }, + formContext: { + formData: {}, + }, + } as unknown as FormProps; + + const { container, getByText, queryByText } = await renderInTestApp( + + + , + ); + expect( + container.getElementsByClassName('MuiTypography-body1'), + ).toHaveLength(1); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.tsx b/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.tsx index f81091f115..34f968d0de 100644 --- a/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoBranchPicker/RepoBranchPicker.tsx @@ -31,6 +31,7 @@ import { RepoBranchPickerState } from './types'; import { BitbucketRepoBranchPicker } from './BitbucketRepoBranchPicker'; import { DefaultRepoBranchPicker } from './DefaultRepoBranchPicker'; import { GitHubRepoBranchPicker } from './GitHubRepoBranchPicker'; +import { MarkdownContent } from '@backstage/core-components'; /** * The underlying component that is rendered in the form for the `RepoBranchPicker` @@ -164,6 +165,8 @@ export const RepoBranchPicker = (props: RepoBranchPickerProps) => { } }; + const description = uiSchema['ui:description'] ?? schema.description; + return ( <> {schema.title && ( @@ -172,8 +175,10 @@ export const RepoBranchPicker = (props: RepoBranchPickerProps) => { )} - {schema.description && ( - {schema.description} + {description && ( + + + )} {renderRepoBranchPicker()} diff --git a/plugins/scaffolder/src/components/fields/RepoBranchPicker/schema.ts b/plugins/scaffolder/src/components/fields/RepoBranchPicker/schema.ts index fae5e6435e..62a3b66e14 100644 --- a/plugins/scaffolder/src/components/fields/RepoBranchPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/RepoBranchPicker/schema.ts @@ -13,58 +13,58 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { z } from 'zod'; -import { makeFieldSchemaFromZod } from '../utils'; +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; /** * @public */ -export const RepoBranchPickerFieldSchema = makeFieldSchemaFromZod( - z.string(), - z.object({ - requestUserCredentials: z - .object({ - secretsKey: z - .string() - .describe( - 'Key used within the template secrets context to store the credential', - ), - additionalScopes: z - .object({ - gitea: z - .array(z.string()) - .optional() - .describe('Additional Gitea scopes to request'), - gerrit: z - .array(z.string()) - .optional() - .describe('Additional Gerrit scopes to request'), - github: z - .array(z.string()) - .optional() - .describe('Additional GitHub scopes to request'), - gitlab: z - .array(z.string()) - .optional() - .describe('Additional GitLab scopes to request'), - bitbucket: z - .array(z.string()) - .optional() - .describe('Additional BitBucket scopes to request'), - azure: z - .array(z.string()) - .optional() - .describe('Additional Azure scopes to request'), - }) - .optional() - .describe('Additional permission scopes to request'), - }) - .optional() - .describe( - 'If defined will request user credentials to auth against the given SCM platform', - ), - }), -); +export const RepoBranchPickerFieldSchema = makeFieldSchema({ + output: z => z.string(), + uiOptions: z => + z.object({ + requestUserCredentials: z + .object({ + secretsKey: z + .string() + .describe( + 'Key used within the template secrets context to store the credential', + ), + additionalScopes: z + .object({ + gitea: z + .array(z.string()) + .optional() + .describe('Additional Gitea scopes to request'), + gerrit: z + .array(z.string()) + .optional() + .describe('Additional Gerrit scopes to request'), + github: z + .array(z.string()) + .optional() + .describe('Additional GitHub scopes to request'), + gitlab: z + .array(z.string()) + .optional() + .describe('Additional GitLab scopes to request'), + bitbucket: z + .array(z.string()) + .optional() + .describe('Additional BitBucket scopes to request'), + azure: z + .array(z.string()) + .optional() + .describe('Additional Azure scopes to request'), + }) + .optional() + .describe('Additional permission scopes to request'), + }) + .optional() + .describe( + 'If defined will request user credentials to auth against the given SCM platform', + ), + }), +}); /** * The input props that can be specified under `ui:options` for the @@ -72,10 +72,11 @@ export const RepoBranchPickerFieldSchema = makeFieldSchemaFromZod( * * @public */ -export type RepoBranchPickerUiOptions = - typeof RepoBranchPickerFieldSchema.uiOptionsType; +export type RepoBranchPickerUiOptions = NonNullable< + (typeof RepoBranchPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; -export type RepoBranchPickerProps = typeof RepoBranchPickerFieldSchema.type; +export type RepoBranchPickerProps = typeof RepoBranchPickerFieldSchema.TProps; // This has been duplicated from /plugins/scaffolder/src/components/fields/RepoUrlPicker/schema.ts // NOTE: There is a bug with this failing validation in the custom field explorer due diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index c5d88275f6..f23d8356ac 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -30,9 +30,11 @@ import { ScaffolderApi, useTemplateSecrets, ScaffolderRJSFField, + ScaffolderRJSFFormProps as FormProps, } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { ComponentType, PropsWithChildren, ReactNode } from 'react'; describe('RepoUrlPicker', () => { const mockScaffolderApi: Partial = { @@ -417,4 +419,106 @@ describe('RepoUrlPicker', () => { }); }); }); + + describe('RepoUrlPicker description', () => { + const description = { + fromSchema: 'RepoUrlPicker description from schema', + fromUiSchema: 'RepoUrlPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string }; + + let Wrapper: ComponentType>; + + beforeEach(() => { + Wrapper = ({ children }: { children?: ReactNode }) => { + return ( + + {children} + + ); + }; + }); + it('omits description', async () => { + const props = { + validator, + schema: { type: 'string' }, + uiSchema: { 'ui:field': 'RepoUrlPicker' }, + fields: { + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, + }, + formContext: { + formData: {}, + }, + } as unknown as FormProps; + + const { container } = await renderInTestApp( + + + , + ); + expect( + container.getElementsByClassName('MuiTypography-body1'), + ).toHaveLength(0); + }); + + it('presents schema description', async () => { + const props = { + validator, + schema: { type: 'string', description: description.fromSchema }, + uiSchema: { + 'ui:field': 'RepoUrlPicker', + }, + fields: { + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, + }, + formContext: { + formData: {}, + }, + } as unknown as FormProps; + + const { container, getByText, queryByText } = await renderInTestApp( + + + , + ); + expect( + container.getElementsByClassName('MuiTypography-body1'), + ).toHaveLength(1); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + const props = { + validator, + schema: { type: 'string', description: description.fromSchema }, + uiSchema: { + 'ui:field': 'RepoUrlPicker', + 'ui:description': description.fromUiSchema, + }, + fields: { + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, + }, + formContext: { + formData: {}, + }, + } as unknown as FormProps; + + const { container, getByText, queryByText } = await renderInTestApp( + + + , + ); + expect( + container.getElementsByClassName('MuiTypography-body1'), + ).toHaveLength(1); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 953b607b07..8f1e3a67b7 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -35,6 +35,7 @@ import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; import { RepoUrlPickerFieldSchema } from './schema'; import { RepoUrlPickerState } from './types'; import { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils'; +import { MarkdownContent } from '@backstage/core-components'; export { RepoUrlPickerSchema } from './schema'; @@ -166,6 +167,9 @@ export const RepoUrlPicker = ( const hostType = (state.host && integrationApi.byHost(state.host)?.type) ?? null; + + const description = uiSchema['ui:description'] ?? schema.description; + return ( <> {schema.title && ( @@ -174,8 +178,10 @@ export const RepoUrlPicker = ( )} - {schema.description && ( - {schema.description} + {description && ( + + + )} ; -export type RepoUrlPickerProps = typeof RepoUrlPickerFieldSchema.type; +export type RepoUrlPickerProps = typeof RepoUrlPickerFieldSchema.TProps; // This has been duplicated to /plugins/scaffolder/src/components/fields/RepoBranchPicker/schema.ts // NOTE: There is a bug with this failing validation in the custom field explorer due diff --git a/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.test.tsx b/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.test.tsx index f1619aacba..d4ddaea537 100644 --- a/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.test.tsx +++ b/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.test.tsx @@ -19,6 +19,7 @@ import { } from '@backstage/plugin-scaffolder-react'; import { SecretInput } from './SecretInput'; import { renderInTestApp } from '@backstage/test-utils'; +import { ScaffolderRJSFFormProps as FormProps } from '@backstage/plugin-scaffolder-react'; import { Form } from '@backstage/plugin-scaffolder-react/alpha'; import validator from '@rjsf/validator-ajv8'; import { fireEvent, act, waitFor } from '@testing-library/react'; @@ -73,4 +74,92 @@ describe('', () => { { timeout: 500 }, ); }); + + describe('SecretInput description', () => { + const description = { + fromSchema: 'MyGroupsPicker description from schema', + fromUiSchema: 'MyGroupsPicker description from uiSchema', + } as { fromSchema: string; fromUiSchema: string }; + + it('omits description', async () => { + const props = { + validator, + schema: { + properties: { myKey: { type: 'string', title: 'secret' } }, + }, + uiSchema: { + myKey: { + 'ui:field': 'Secret', + }, + }, + fields: { + Secret: SecretInput, + }, + } as unknown as FormProps; + + const { queryByText } = await renderInTestApp( + + + + , + ); + expect(queryByText(description.fromSchema)).toBe(null); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents schema description', async () => { + const props = { + validator, + schema: { + properties: { myKey: { type: 'string', title: 'secret' } }, + description: description.fromSchema, + }, + uiSchema: { + myKey: { + 'ui:field': 'Secret', + }, + }, + fields: { + Secret: SecretInput, + }, + } as unknown as FormProps; + + const { getByText, queryByText } = await renderInTestApp( + + + + , + ); + expect(getByText(description.fromSchema)).toBeInTheDocument(); + expect(queryByText(description.fromUiSchema)).toBe(null); + }); + + it('presents uiSchema description', async () => { + const props = { + validator, + schema: { + properties: { myKey: { type: 'string', title: 'secret' } }, + description: description.fromSchema, + }, + uiSchema: { + myKey: { + 'ui:field': 'Secret', + }, + 'ui:description': description.fromUiSchema, + }, + fields: { + Secret: SecretInput, + }, + } as unknown as FormProps; + + const { getByText, queryByText } = await renderInTestApp( + + + + , + ); + expect(queryByText(description.fromSchema)).toBe(null); + expect(getByText(description.fromUiSchema)).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx b/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx index d3bfd09502..b21356d6a8 100644 --- a/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx +++ b/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx @@ -26,12 +26,13 @@ export const SecretInput = (props: ScaffolderRJSFFieldProps) => { disabled, errors, required, + uiSchema, } = props; return ( Date: Wed, 30 Apr 2025 14:35:38 -0500 Subject: [PATCH 058/143] use callback to define entityQueryFilterExpression schema; deprecated exported const entityQueryFilterExpressionSchema Signed-off-by: Matt Benson --- .../components/fields/EntityPicker/schema.ts | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts index 38cb6b8929..26e11d651f 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts @@ -16,15 +16,20 @@ import { z as zod } from 'zod'; import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; +const createEntityQueryFilterExpressionSchema = (z: typeof zod) => + z.record( + z + .string() + .or(z.object({ exists: z.boolean().optional() })) + .or(z.array(z.string())), + ); + /** * @public + * @deprecated */ -export const entityQueryFilterExpressionSchema = zod.record( - zod - .string() - .or(zod.object({ exists: zod.boolean().optional() })) - .or(zod.array(zod.string())), -); +export const entityQueryFilterExpressionSchema = + createEntityQueryFilterExpressionSchema(zod); /** * @public @@ -58,9 +63,9 @@ export const EntityPickerFieldSchema = makeFieldSchema({ .describe( 'The default namespace. Options with this namespace will not be prefixed.', ), - catalogFilter: z - .array(entityQueryFilterExpressionSchema) - .or(entityQueryFilterExpressionSchema) + catalogFilter: (t => t.or(t.array()))( + createEntityQueryFilterExpressionSchema(z), + ) .optional() .describe('List of key-value filter expression for entities'), }), @@ -81,7 +86,7 @@ export type EntityPickerProps = typeof EntityPickerFieldSchema.TProps; export const EntityPickerSchema = EntityPickerFieldSchema.schema; export type EntityPickerFilterQuery = zod.TypeOf< - typeof entityQueryFilterExpressionSchema + ReturnType >; export type EntityPickerFilterQueryValue = From 65555af78014d828b7a260a2815ab3e03d2fffec Mon Sep 17 00:00:00 2001 From: Matt Benson Date: Wed, 30 Apr 2025 15:48:23 -0500 Subject: [PATCH 059/143] remove entityQueryFilterExpressionSchema export; refactor DRY for specialized EntityPicker fields Signed-off-by: Matt Benson --- .../components/fields/EntityPicker/schema.ts | 9 +---- .../fields/OwnedEntityPicker/schema.ts | 37 +------------------ .../components/fields/OwnerPicker/schema.ts | 10 ++--- 3 files changed, 8 insertions(+), 48 deletions(-) diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts index 26e11d651f..5102d248b7 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts @@ -16,7 +16,7 @@ import { z as zod } from 'zod'; import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; -const createEntityQueryFilterExpressionSchema = (z: typeof zod) => +export const createEntityQueryFilterExpressionSchema = (z: typeof zod) => z.record( z .string() @@ -24,13 +24,6 @@ const createEntityQueryFilterExpressionSchema = (z: typeof zod) => .or(z.array(z.string())), ); -/** - * @public - * @deprecated - */ -export const entityQueryFilterExpressionSchema = - createEntityQueryFilterExpressionSchema(zod); - /** * @public */ diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts index ad5ee34ce1..6dd00df49d 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts @@ -13,45 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { entityQueryFilterExpressionSchema } from '../EntityPicker/schema'; -import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; +import { EntityPickerFieldSchema } from '../EntityPicker/schema'; /** * @public */ -export const OwnedEntityPickerFieldSchema = makeFieldSchema({ - output: z => z.string(), - uiOptions: z => - z.object({ - allowedKinds: z - .array(z.string()) - .optional() - .describe( - 'DEPRECATED: Use `catalogFilter` instead. List of kinds of entities to derive options from', - ), - defaultKind: z - .string() - .optional() - .describe( - 'The default entity kind. Options of this kind will not be prefixed.', - ), - allowArbitraryValues: z - .boolean() - .optional() - .describe('Whether to allow arbitrary user input. Defaults to true'), - defaultNamespace: z - .union([z.string(), z.literal(false)]) - .optional() - .describe( - 'The default namespace. Options with this namespace will not be prefixed.', - ), - catalogFilter: z - .array(entityQueryFilterExpressionSchema) - .or(entityQueryFilterExpressionSchema) - .optional() - .describe('List of key-value filter expression for entities'), - }), -}); +export const OwnedEntityPickerFieldSchema = EntityPickerFieldSchema; /** * The input props that can be specified under `ui:options` for the diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts b/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts index 3bcb63c91f..76389216ba 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { entityQueryFilterExpressionSchema } from '../EntityPicker/schema'; import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; +import { createEntityQueryFilterExpressionSchema } from '../EntityPicker/schema'; /** * @public @@ -43,9 +43,9 @@ export const OwnerPickerFieldSchema = makeFieldSchema({ .describe( 'The default namespace. Options with this namespace will not be prefixed.', ), - catalogFilter: z - .array(entityQueryFilterExpressionSchema) - .or(entityQueryFilterExpressionSchema) + catalogFilter: (t => t.or(t.array()))( + createEntityQueryFilterExpressionSchema(z), + ) .optional() .describe('List of key-value filter expression for entities'), }), @@ -61,6 +61,6 @@ export type OwnerPickerUiOptions = NonNullable< (typeof OwnerPickerFieldSchema.TProps.uiSchema)['ui:options'] >; -export type OwnerPickerProps = typeof OwnerPickerFieldSchema.type; +export type OwnerPickerProps = typeof OwnerPickerFieldSchema.TProps; export const OwnerPickerSchema = OwnerPickerFieldSchema.schema; From f20bebc941b01de2ad5b47b5fb194fdef80f2201 Mon Sep 17 00:00:00 2001 From: Matt Benson Date: Fri, 2 May 2025 10:23:47 -0500 Subject: [PATCH 060/143] rename template extensions->templating extensions in docs Signed-off-by: Matt Benson --- .../{template-extensions.md => templating-extensions.md} | 8 ++++---- docs/features/software-templates/writing-templates.md | 4 ++-- microsite/docusaurus.config.ts | 4 ++++ microsite/sidebars.ts | 2 +- mkdocs.yml | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) rename docs/features/software-templates/{template-extensions.md => templating-extensions.md} (98%) diff --git a/docs/features/software-templates/template-extensions.md b/docs/features/software-templates/templating-extensions.md similarity index 98% rename from docs/features/software-templates/template-extensions.md rename to docs/features/software-templates/templating-extensions.md index a43f590e9f..91d0343ae9 100644 --- a/docs/features/software-templates/template-extensions.md +++ b/docs/features/software-templates/templating-extensions.md @@ -1,7 +1,7 @@ --- -id: template-extensions -title: Template Extensions -description: Template extensions system +id: templating-extensions +title: Templating Extensions +description: Templating extensions system --- Backstage templating is powered by [Nunjucks][]. The basics: @@ -117,7 +117,7 @@ may be any combination of filters, global functions and global values. With the new backend you would use a scaffolder plugin module for this; later we will demonstrate the analogous approach with the old backend. -## Streamlining Template Extension Module Creation with the Backstage CLI +## Streamlining Templating Extension Module Creation with the Backstage CLI The creation of a "template environment customization" module in Backstage can be accelerated using the Backstage CLI. diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index f02b2722f6..eeaa4ad203 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -711,9 +711,9 @@ powerful [Nunjucks templating engine](https://mozilla.github.io/nunjucks/). To learn more about basic Nunjucks templating please see [templating documentation](https://mozilla.github.io/nunjucks/templating.html). -Information about Backstage's built-in Nunjucks extensions, as well as how to +Information about Backstage's built-in templating extensions, as well as how to create your own customizations, may be found at -[Template Extensions](./template-extensions.md). +[Templating Extensions](./templating-extensions.md). ## Template Editor diff --git a/microsite/docusaurus.config.ts b/microsite/docusaurus.config.ts index 71331710d5..0213ebc05b 100644 --- a/microsite/docusaurus.config.ts +++ b/microsite/docusaurus.config.ts @@ -269,6 +269,10 @@ const config: Config = { from: '/docs/plugins/url-reader/', to: '/docs/backend-system/core-services/url-reader', }, + { + from: '/docs/features/software-templates/template-extensions/', + to: '/docs/features/software-templates/templating-extensions', + }, ], }), [ diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index dd52f9a801..1f8d3defb7 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -228,7 +228,7 @@ export default { 'features/software-templates/migrating-from-v1beta2-to-v1beta3', 'features/software-templates/dry-run-testing', 'features/software-templates/experimental', - 'features/software-templates/template-extensions', + 'features/software-templates/templating-extensions', ], }, { diff --git a/mkdocs.yml b/mkdocs.yml index d56ec49b66..688ca1a078 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -71,7 +71,7 @@ nav: - Builtin Actions: 'features/software-templates/builtin-actions.md' - Writing Custom Actions: 'features/software-templates/writing-custom-actions.md' - Writing Custom Step Layouts: 'features/software-templates/writing-custom-step-layouts.md' - - Template Extensions: 'features/software-templates/template-extensions.md' + - Templating Extensions: 'features/software-templates/templating-extensions.md' - Migrating from v1beta2 to v1beta3 templates: 'features/software-templates/migrating-from-v1beta2-to-v1beta3.md' - Dry Run Testing: 'features/software-templates/dry-run-testing.md' - Backstage Search: From aa3a63aeedea3524cba5486087dfec2e5ecc89d5 Mon Sep 17 00:00:00 2001 From: Scott Guymer Date: Thu, 8 May 2025 10:06:06 +0200 Subject: [PATCH 061/143] Notifications Email Module - Enable endpoint configuration for SES Enable the ability to configure the endpoint for the SES connection used in the notifications email module. This enables the configuration of alternate endpoints as required, for example for local testing or alternative stacks. Signed-off-by: Scott Guymer --- .changeset/moody-women-itch.md | 5 +++++ plugins/notifications-backend-module-email/config.d.ts | 4 ++++ .../src/processor/transports/ses.ts | 1 + 3 files changed, 10 insertions(+) create mode 100644 .changeset/moody-women-itch.md diff --git a/.changeset/moody-women-itch.md b/.changeset/moody-women-itch.md new file mode 100644 index 0000000000..f68fddb848 --- /dev/null +++ b/.changeset/moody-women-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications-backend-module-email': patch +--- + +Enable the ability to configure the endpoint for the SES connection used in the notifications email module. This enables the configuration of alternate endpoints as required, for example for local testing or alternative stacks. diff --git a/plugins/notifications-backend-module-email/config.d.ts b/plugins/notifications-backend-module-email/config.d.ts index bce7a4b332..97a6495246 100644 --- a/plugins/notifications-backend-module-email/config.d.ts +++ b/plugins/notifications-backend-module-email/config.d.ts @@ -64,6 +64,10 @@ export interface Config { * AWS account ID to use */ accountId?: string; + /** + * AWS endpoint to use, defaults to standard AWS endpoint based on region + */ + endpoint?: string; /** * AWS region to use */ diff --git a/plugins/notifications-backend-module-email/src/processor/transports/ses.ts b/plugins/notifications-backend-module-email/src/processor/transports/ses.ts index 0be23078ab..3ac351307e 100644 --- a/plugins/notifications-backend-module-email/src/processor/transports/ses.ts +++ b/plugins/notifications-backend-module-email/src/processor/transports/ses.ts @@ -30,6 +30,7 @@ export const createSesTransport = async ( apiVersion: config.getOptionalString('apiVersion') ?? '2010-12-01', credentials: credentials.sdkCredentialProvider, region: config.getOptionalString('region'), + endpoint: config.getOptionalString('endpoint'), }, ]); return createTransport({ From 1e06afd80c16f344f483da725a1ba0e72d9ae3f2 Mon Sep 17 00:00:00 2001 From: Thomas Cardonne Date: Thu, 8 May 2025 12:14:05 +0200 Subject: [PATCH 062/143] feat(backend-defaults): use isGlob in GithubUrlReader to match glob patterns Signed-off-by: Thomas Cardonne --- .changeset/cool-groups-fail.md | 8 ++++++++ docs/integrations/github/discovery.md | 2 +- packages/backend-defaults/package.json | 2 ++ .../entrypoints/urlReader/lib/GithubUrlReader.test.ts | 11 +++++++++++ .../src/entrypoints/urlReader/lib/GithubUrlReader.ts | 3 ++- yarn.lock | 2 ++ 6 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 .changeset/cool-groups-fail.md diff --git a/.changeset/cool-groups-fail.md b/.changeset/cool-groups-fail.md new file mode 100644 index 0000000000..459358676b --- /dev/null +++ b/.changeset/cool-groups-fail.md @@ -0,0 +1,8 @@ +--- +'@backstage/backend-defaults': patch +--- + +`GithubUrlReader`'s search detects glob-patterns supported by `minimatch`, instead of just detecting +`*` and `?` characters. + +For example, this allows to search for patterns like `{C,c}atalog-info.yaml`. diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index 354569cdb6..c1dfd62ce5 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -148,7 +148,7 @@ If you do so, `default` will be used as provider ID. - **`catalogPath`** _(optional)_: Default: `/catalog-info.yaml`. Path where to look for `catalog-info.yaml` files. - You can use wildcards - `*` or `**` - to search the path and/or the filename. + You can use wildcards - `*`, `**` or a glob pattern supported by [`minimatch`](https://github.com/isaacs/minimatch) - to search the path and/or the filename. Wildcards cannot be used if the `validateLocationsExist` option is set to `true`. - **`filters`** _(optional)_: - **`branch`** _(optional)_: diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 093ebdc422..c865f66067 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -163,6 +163,7 @@ "fs-extra": "^11.2.0", "git-url-parse": "^15.0.0", "helmet": "^6.0.0", + "is-glob": "^4.0.3", "jose": "^5.0.0", "keyv": "^5.2.1", "knex": "^3.0.0", @@ -200,6 +201,7 @@ "@types/compression": "^1.7.5", "@types/concat-stream": "^2.0.0", "@types/http-errors": "^2.0.0", + "@types/is-glob": "^4.0.2", "@types/node-forge": "^1.3.0", "@types/pg-format": "^1.0.5", "@types/yauzl": "^2.10.0", diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.test.ts index 4e1c5a2d08..861b3ad7cb 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.test.ts @@ -923,6 +923,17 @@ describe('GithubUrlReader', () => { await expect(r5.files[0].content()).resolves.toEqual( Buffer.from('# Test\n'), ); + + const r6 = await reader.search( + `${baseUrl}/backstage/mock/tree/main/{M,m}kdocs.yml`, + ); + expect(r6.files.length).toBe(1); + expect(r6.files[0].url).toBe( + `${baseUrl}/backstage/mock/tree/main/mkdocs.yml`, + ); + await expect(r6.files[0].content()).resolves.toEqual( + Buffer.from('site_name: Test\n'), + ); } // eslint-disable-next-line jest/expect-expect diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts index 1dbade8477..fe0bd08fec 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts @@ -45,6 +45,7 @@ import { import { ReadTreeResponseFactory, ReaderFactory } from './types'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; +import isGlob from 'is-glob'; export type GhRepoResponse = RestEndpointMethodTypes['repos']['get']['response']['data']; @@ -186,7 +187,7 @@ export class GithubUrlReader implements UrlReaderService { const { filepath } = parseGitUrl(url); // If it's a direct URL we use readUrl instead - if (!filepath?.match(/[*?]/)) { + if (!isGlob(filepath)) { try { const data = await this.readUrl(url, options); diff --git a/yarn.lock b/yarn.lock index f700a3af06..800d6463b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3587,6 +3587,7 @@ __metadata: "@types/cors": "npm:^2.8.6" "@types/express": "npm:^4.17.6" "@types/http-errors": "npm:^2.0.0" + "@types/is-glob": "npm:^4.0.2" "@types/node-forge": "npm:^1.3.0" "@types/pg-format": "npm:^1.0.5" "@types/yauzl": "npm:^2.10.0" @@ -3605,6 +3606,7 @@ __metadata: git-url-parse: "npm:^15.0.0" helmet: "npm:^6.0.0" http-errors: "npm:^2.0.0" + is-glob: "npm:^4.0.3" jose: "npm:^5.0.0" keyv: "npm:^5.2.1" knex: "npm:^3.0.0" From e4dabc605c9426763567421bff87bd501fdca487 Mon Sep 17 00:00:00 2001 From: Vinnie McGuinness Date: Thu, 8 May 2025 12:17:26 +0100 Subject: [PATCH 063/143] feat(catalog-backend-module-gitea) add new Gitea provider module Signed-off-by: Vinnie McGuinness feat(catalog-backend-module-gitea) add new Gitea provider module Signed-off-by: Vinnie McGuinness adding tests --- .changeset/orange-banks-deny.md | 5 + .github/CODEOWNERS | 1 + docs/integrations/gitea/discovery.md | 63 +++ .../catalog-backend-module-gitea/.eslintrc.js | 1 + .../catalog-backend-module-gitea/README.md | 8 + .../catalog-info.yaml | 10 + .../catalog-backend-module-gitea/package.json | 51 ++ .../report.api.md | 36 ++ .../catalog-backend-module-gitea/src/index.ts | 24 + .../src/module.test.ts | 86 +++ .../src/module.ts | 47 ++ .../src/providers/GiteaEntityProvider.test.ts | 532 ++++++++++++++++++ .../src/providers/GiteaEntityProvider.ts | 266 +++++++++ .../src/providers/config.test.ts | 125 ++++ .../src/providers/config.ts | 58 ++ .../src/providers/core.test.ts | 42 ++ .../src/providers/core.ts | 26 + .../src/providers/index.ts | 17 + .../src/providers/types.ts | 36 ++ yarn.lock | 18 + 20 files changed, 1452 insertions(+) create mode 100644 .changeset/orange-banks-deny.md create mode 100644 docs/integrations/gitea/discovery.md create mode 100644 plugins/catalog-backend-module-gitea/.eslintrc.js create mode 100644 plugins/catalog-backend-module-gitea/README.md create mode 100644 plugins/catalog-backend-module-gitea/catalog-info.yaml create mode 100644 plugins/catalog-backend-module-gitea/package.json create mode 100644 plugins/catalog-backend-module-gitea/report.api.md create mode 100644 plugins/catalog-backend-module-gitea/src/index.ts create mode 100644 plugins/catalog-backend-module-gitea/src/module.test.ts create mode 100644 plugins/catalog-backend-module-gitea/src/module.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/config.test.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/config.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/core.test.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/core.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/index.ts create mode 100644 plugins/catalog-backend-module-gitea/src/providers/types.ts diff --git a/.changeset/orange-banks-deny.md b/.changeset/orange-banks-deny.md new file mode 100644 index 0000000000..3719206865 --- /dev/null +++ b/.changeset/orange-banks-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitea': minor +--- + +add new gitea provider module diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 41f409a651..f5c6f49617 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -51,6 +51,7 @@ yarn.lock @backstage/maintainers @backst /plugins/catalog-backend-module-aws @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-bitbucket-cloud @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-backstage-openapi @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers +/plugins/catalog-backend-module-gitea @backstage/maintainers @backstage/reviewers @vinnie-jog-on /plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-puppetdb @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers /plugins/catalog-graph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @backstage/sda-se-reviewers diff --git a/docs/integrations/gitea/discovery.md b/docs/integrations/gitea/discovery.md new file mode 100644 index 0000000000..c01ea52edf --- /dev/null +++ b/docs/integrations/gitea/discovery.md @@ -0,0 +1,63 @@ +--- +id: discovery +title: Gitea Discovery +sidebar_label: Discovery +# prettier-ignore +description: Automatically discovering catalog entities from Gitea repositories +--- + +:::info +This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). +::: + +The Gitea integration has a special entity provider for discovering catalog entities +from Gitea repositories. The provider uses the "List Projects" API in Gitea to get +a list of repositories and will automatically ingest all `catalog-info.yaml` files +stored in the root of the matching projects. + +## Installation + +As this provider is not one of the default providers, you will first need to install +the Gitea provider plugin: + +```bash title="From your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-gitea +``` + +Then update your backend by adding the following line: + +```ts title="packages/backend/src/index.ts" +backend.add(import('@backstage/plugin-catalog-backend')); +/* highlight-add-start */ +backend.add(import('@backstage/plugin-catalog-backend-module-gitea')); +/* highlight-add-end */ +``` + +## Configuration + +To use the discovery processor, you'll need a Gitea integration +[set up](locations.md). Then you can add any number of providers. + +```yaml +# app-config.yaml +catalog: + providers: + gitea: + yourProviderId: # identifies your dataset / provider independent of config changes + organization: 'your-company' # string + host: gitea-your-company.com + branch: 'main' # Optional, defaults to 'main' + catalogPath: 'catalog-info.yaml' # Optional, defaults to catalog-info.yaml + schedule: + # supports cron, ISO duration, "human duration" as used in code + frequency: { minutes: 30 } + # supports ISO duration, "human duration" as used in code + timeout: { minutes: 3 } +``` + +The provider configuration consists of the following parts: + +- **`organization`**: Name of your organization account/workspace. If you want to add multiple organizations, you need to add one provider config each. +- **`host`**: the host of the Gitea integration to use. +- **`branch`** _(optional)_: the branch where we will look for catalog entities (defaults to 'main'). +- **`catalogPath`**: path relative to the root of the repository where the Backstage manifests are stored. diff --git a/plugins/catalog-backend-module-gitea/.eslintrc.js b/plugins/catalog-backend-module-gitea/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/catalog-backend-module-gitea/README.md b/plugins/catalog-backend-module-gitea/README.md new file mode 100644 index 0000000000..6b93c9c90a --- /dev/null +++ b/plugins/catalog-backend-module-gitea/README.md @@ -0,0 +1,8 @@ +# Catalog Backend Module for Gitea + +This is an extension module to the plugin-catalog-backend plugin, providing extensions targeted at Gitea integrations. + +## Getting started + +See [Backstage documentation](https://backstage.io/docs/integrations/gitea/discovery.md) +for details on how to install and configure the plugin. diff --git a/plugins/catalog-backend-module-gitea/catalog-info.yaml b/plugins/catalog-backend-module-gitea/catalog-info.yaml new file mode 100644 index 0000000000..eb580d570b --- /dev/null +++ b/plugins/catalog-backend-module-gitea/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-catalog-backend-module-gitea + title: '@backstage/plugin-catalog-backend-module-gitea' + description: The gitea backend module for the catalog plugin provide by intive.com +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/catalog-backend-module-gitea/package.json b/plugins/catalog-backend-module-gitea/package.json new file mode 100644 index 0000000000..fbba66a039 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/package.json @@ -0,0 +1,51 @@ +{ + "name": "@backstage/plugin-catalog-backend-module-gitea", + "version": "0.1.0", + "license": "Apache-2.0", + "private": true, + "description": "The gitea backend module for the catalog plugin.", + "main": "src/index.ts", + "types": "src/index.ts", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-backend-module-gitea" + }, + "backstage": { + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/integration": "workspace:^", + "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^", + "p-limit": "^3.0.2", + "uuid": "^11.0.0" + }, + "devDependencies": { + "@backstage/backend-common": "^0.25.0", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/catalog-backend-module-gitea/report.api.md b/plugins/catalog-backend-module-gitea/report.api.md new file mode 100644 index 0000000000..1aae80271a --- /dev/null +++ b/plugins/catalog-backend-module-gitea/report.api.md @@ -0,0 +1,36 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-gitea" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; +import { EntityProvider } from '@backstage/plugin-catalog-node'; +import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { SchedulerService } from '@backstage/backend-plugin-api'; +import { SchedulerServiceTaskRunner } from '@backstage/backend-plugin-api'; + +// @public (undocumented) +const catalogModuleGitea: BackendFeature; +export default catalogModuleGitea; + +// @public (undocumented) +export class GiteaEntityProvider implements EntityProvider { + // (undocumented) + connect(connection: EntityProviderConnection): Promise; + // (undocumented) + static fromConfig( + configRoot: Config, + options: { + logger: LoggerService; + schedule?: SchedulerServiceTaskRunner; + scheduler?: SchedulerService; + }, + ): GiteaEntityProvider[]; + // (undocumented) + getProviderName(): string; + // (undocumented) + refresh(logger: LoggerService): Promise; +} +``` diff --git a/plugins/catalog-backend-module-gitea/src/index.ts b/plugins/catalog-backend-module-gitea/src/index.ts new file mode 100644 index 0000000000..b92ced7fcf --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The gitea backend module for the catalog plugin. + * + * @packageDocumentation + */ + +export { catalogModuleGitea as default } from './module'; +export { GiteaEntityProvider } from './providers/GiteaEntityProvider'; diff --git a/plugins/catalog-backend-module-gitea/src/module.test.ts b/plugins/catalog-backend-module-gitea/src/module.test.ts new file mode 100644 index 0000000000..0ce2d4319a --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/module.test.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugin-api'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; +import { catalogModuleGitea } from './module'; +import { GiteaEntityProvider } from './providers/GiteaEntityProvider'; + +describe('catalogModuleGitea', () => { + it('should register provider at the catalog extension point', async () => { + let addedProviders: Array | undefined; + let usedSchedule: SchedulerServiceTaskScheduleDefinition | undefined; + + const extensionPoint = { + addEntityProvider: (providers: any) => { + addedProviders = providers; + }, + }; + const runner = jest.fn(); + const scheduler = mockServices.scheduler.mock({ + createScheduledTaskRunner(schedule) { + usedSchedule = schedule; + return { run: runner }; + }, + }); + + const config = { + catalog: { + providers: { + gitea: { + test: { + host: 'g.com', + organization: 'org', + branch: 'main', + schedule: { + frequency: 'P1M', + timeout: 'PT3M', + }, + }, + }, + }, + }, + integrations: { + gitea: [ + { + host: 'g.com', + baseUrl: 'https://g.com/gitea', + gitilesBaseUrl: 'https:/g.com/gitiles', + }, + ], + }, + }; + + await startTestBackend({ + extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], + features: [ + catalogModuleGitea, + mockServices.rootConfig.factory({ data: config }), + mockServices.logger.factory(), + scheduler.factory, + ], + }); + + expect(usedSchedule?.frequency).toEqual({ months: 1 }); + expect(usedSchedule?.timeout).toEqual({ minutes: 3 }); + expect(addedProviders?.length).toEqual(1); + expect(addedProviders?.pop()?.getProviderName()).toEqual( + 'gitea-provider:test', + ); + expect(runner).not.toHaveBeenCalled(); + }); +}); diff --git a/plugins/catalog-backend-module-gitea/src/module.ts b/plugins/catalog-backend-module-gitea/src/module.ts new file mode 100644 index 0000000000..91e019c6fb --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/module.ts @@ -0,0 +1,47 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; + +import { GiteaEntityProvider } from './providers/GiteaEntityProvider'; +/** + * @public + */ +export const catalogModuleGitea = createBackendModule({ + pluginId: 'catalog', + moduleId: 'gitea', + register(reg) { + reg.registerInit({ + deps: { + catalog: catalogProcessingExtensionPoint, + config: coreServices.rootConfig, + logger: coreServices.logger, + scheduler: coreServices.scheduler, + }, + + async init({ catalog, config, logger, scheduler }) { + const providers = GiteaEntityProvider.fromConfig(config, { + logger, + scheduler, + }); + catalog.addEntityProvider(providers); + }, + }); + }, +}); diff --git a/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts new file mode 100644 index 0000000000..c17b3bc20e --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts @@ -0,0 +1,532 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { getVoidLogger } from '@backstage/backend-common'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { ConfigReader } from '@backstage/config'; +import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; +import { GiteaEntityProvider } from './GiteaEntityProvider'; +import * as uuid from 'uuid'; +import { readGiteaConfigs } from './config'; +import { getGiteaApiUrl } from './core'; +import { GiteaIntegration } from '@backstage/integration'; + +jest.mock('./config'); +jest.mock('./core'); +jest.mock('uuid'); + +describe('GiteaEntityProvider', () => { + const logger = getVoidLogger() as unknown as LoggerService; + const mockScheduler = { + createScheduledTaskRunner: jest.fn(), + triggerTask: jest.fn(), + scheduleTask: jest.fn(), + getScheduledTasks: jest.fn(), + }; + const mockTaskRunner = { + run: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + (readGiteaConfigs as jest.Mock).mockReturnValue([ + { + id: 'test-provider', + host: 'gitea.example.com', + organization: 'test-org', + catalogPath: 'catalog-info.yaml', + branch: 'main', + schedule: { + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }, + }, + ]); + (getGiteaApiUrl as jest.Mock).mockReturnValue( + 'https://gitea.example.com/api/v1/', + ); + mockScheduler.createScheduledTaskRunner.mockReturnValue(mockTaskRunner); + (uuid.v4 as jest.Mock).mockReturnValue('test-uuid'); + + // Mock global fetch + global.fetch = jest.fn(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('fromConfig', () => { + it('should create providers from config', () => { + const config = new ConfigReader({ + integrations: { + gitea: [ + { + host: 'gitea.example.com', + token: 'test-token', + }, + ], + }, + catalog: { + providers: { + gitea: { + 'test-provider': { + host: 'gitea.example.com', + organization: 'test-org', + }, + }, + }, + }, + }); + + const providers = GiteaEntityProvider.fromConfig(config, { + logger, + scheduler: mockScheduler, + }); + + expect(providers).toHaveLength(1); + expect(providers[0].getProviderName()).toBe( + 'gitea-provider:test-provider', + ); + }); + + it('should throw if no schedule or scheduler is provided', () => { + const config = new ConfigReader({ + integrations: { + gitea: [ + { + host: 'gitea.example.com', + token: 'test-token', + }, + ], + }, + catalog: { + providers: { + gitea: { + 'test-provider': { + host: 'gitea.example.com', + organization: 'test-org', + }, + }, + }, + }, + }); + + expect(() => + GiteaEntityProvider.fromConfig(config, { + logger, + } as any), + ).toThrow('Either schedule or scheduler must be provided.'); + }); + + it('should throw if no matching integration is found', () => { + const config = new ConfigReader({ + integrations: { + gitea: [ + { + host: 'wrong-host.example.com', + token: 'test-token', + }, + ], + }, + catalog: { + providers: { + gitea: { + 'test-provider': { + host: 'gitea.example.com', + organization: 'test-org', + }, + }, + }, + }, + }); + + expect(() => + GiteaEntityProvider.fromConfig(config, { + logger, + scheduler: mockScheduler, + }), + ).toThrow( + 'No Gitea integration found that matches host gitea.example.com', + ); + }); + + it('should throw if no schedule is provided in code or config', () => { + const config = new ConfigReader({ + integrations: { + gitea: [ + { + host: 'gitea.example.com', + token: 'test-token', + }, + ], + }, + catalog: { + providers: { + gitea: { + 'test-provider': { + host: 'gitea.example.com', + organization: 'test-org', + schedule: undefined, + }, + }, + }, + }, + }); + + (readGiteaConfigs as jest.Mock).mockReturnValue([ + { + id: 'test-provider', + host: 'gitea.example.com', + organization: 'test-org', + catalogPath: 'catalog-info.yaml', + branch: 'main', + schedule: undefined, + }, + ]); + + expect(() => + GiteaEntityProvider.fromConfig(config, { + logger, + scheduler: mockScheduler, + }), + ).toThrow( + 'No schedule provided neither via code nor config for Gitea-provider:test-provider.', + ); + }); + }); + + describe('getProviderName', () => { + it('should return the correct provider name', () => { + const config = new ConfigReader({ + integrations: { + gitea: [ + { + host: 'gitea.example.com', + token: 'test-token', + }, + ], + }, + catalog: { + providers: { + gitea: { + 'test-provider': { + host: 'gitea.example.com', + organization: 'test-org', + }, + }, + }, + }, + }); + + const providers = GiteaEntityProvider.fromConfig(config, { + logger, + scheduler: mockScheduler, + }); + + expect(providers[0].getProviderName()).toBe( + 'gitea-provider:test-provider', + ); + }); + }); + + describe('connect', () => { + let provider: GiteaEntityProvider; + const mockConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + refresh: jest.fn(), + }; + + beforeEach(() => { + const config = new ConfigReader({ + integrations: { + gitea: [ + { + host: 'gitea.example.com', + token: 'test-token', + }, + ], + }, + catalog: { + providers: { + gitea: { + 'test-provider': { + host: 'gitea.example.com', + organization: 'test-org', + }, + }, + }, + }, + }); + + provider = GiteaEntityProvider.fromConfig(config, { + logger, + scheduler: mockScheduler, + })[0]; + }); + + it('should connect and schedule a refresh', async () => { + await provider.connect(mockConnection); + + expect(mockTaskRunner.run).toHaveBeenCalledWith({ + id: 'gitea-provider:test-provider:refresh', + fn: expect.any(Function), + }); + }); + + it('should run the scheduled refresh function', async () => { + await provider.connect(mockConnection); + + // Extract and call the scheduled function + const runArgument = mockTaskRunner.run.mock.calls[0][0]; + const refreshFn = runArgument.fn; + + // Mock the refresh behavior + (global.fetch as jest.Mock).mockImplementation(async (url: string) => { + if (url.includes('/orgs/test-org/repos')) { + if (url.includes('page=1')) { + return { + ok: true, + json: async () => [ + { + name: 'repo1', + html_url: 'https://gitea.example.com/test-org/repo1', + empty: false, + }, + { + name: 'repo2', + html_url: 'https://gitea.example.com/test-org/repo2', + empty: false, + }, + ], + }; + } + return { + ok: true, + json: async () => [], + }; + } else if (url.includes('/contents/catalog-info.yaml')) { + if (url.includes('repo1')) { + return { ok: true }; + } + } + return { ok: false }; + }); + + const abortController = new AbortController(); + await refreshFn(abortController.signal); + + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [ + { + locationKey: 'gitea-provider:test-provider', + entity: expect.objectContaining({ + metadata: expect.objectContaining({ + annotations: expect.objectContaining({ + 'backstage.io/managed-by-location': + 'url:https://gitea.example.com/test-org/repo1/src/branch/main/catalog-info.yaml', + }), + }), + }), + }, + ], + }); + }); + }); + + describe('refresh', () => { + let provider: GiteaEntityProvider; + let integration: GiteaIntegration; + const mockConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + refresh: jest.fn(), + }; + + beforeEach(() => { + // Need to access the provider internals for refresh tests + integration = { + config: { + host: 'gitea.example.com', + token: 'test-token', + }, + } as unknown as GiteaIntegration; + + // Direct instantiation for testing the refresh method + provider = new (GiteaEntityProvider as any)( + { + id: 'test-provider', + host: 'gitea.example.com', + organization: 'test-org', + catalogPath: 'catalog-info.yaml', + branch: 'main', + }, + integration, + logger, + mockTaskRunner, + ); + }); + + it('should throw if not connected', async () => { + await expect(provider.refresh(logger)).rejects.toThrow( + 'Gitea discovery connection not initialized', + ); + }); + + it('should handle API errors gracefully', async () => { + await provider.connect(mockConnection); + + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: false, + status: 500, + }); + + await expect(provider.refresh(logger)).rejects.toThrow( + 'Failed to list Gitea projects for organization test-org', + ); + }); + + it('should handle empty results', async () => { + await provider.connect(mockConnection); + + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: async () => [], + }); + + await provider.refresh(logger); + + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [], + }); + }); + + it('should handle pagination and filter repos with catalog files', async () => { + await provider.connect(mockConnection); + + // Page 1 response + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + name: 'repo1', + html_url: 'https://gitea.example.com/test-org/repo1', + empty: false, + }, + { + name: 'repo2', + html_url: 'https://gitea.example.com/test-org/repo2', + empty: false, + }, + { + name: 'empty-repo', + html_url: 'https://gitea.example.com/test-org/empty-repo', + empty: true, + }, + ], + }); + + // Page 2 response + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + name: 'repo3', + html_url: 'https://gitea.example.com/test-org/repo3', + empty: false, + }, + ], + }); + + // Empty page 3 to terminate pagination + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: async () => [], + }); + + // Catalog check for repo1 - has catalog file + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + }); + + // Catalog check for repo2 - no catalog file + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: false, + }); + + // Catalog check for repo3 - has catalog file + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + }); + + await provider.refresh(logger); + + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [ + expect.objectContaining({ + locationKey: 'gitea-provider:test-provider', + entity: expect.anything(), + }), + expect.objectContaining({ + locationKey: 'gitea-provider:test-provider', + entity: expect.anything(), + }), + ], + }); + + // Verify we made requests for all repos + expect(global.fetch).toHaveBeenCalledTimes(6); + }); + + it('should handle errors when applying mutations', async () => { + await provider.connect(mockConnection); + + // Mock repository data + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + name: 'repo1', + html_url: 'https://gitea.example.com/test-org/repo1', + empty: false, + }, + ], + }); + + // Empty page 2 + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: async () => [], + }); + + // Catalog check - has catalog file + (global.fetch as jest.Mock).mockResolvedValueOnce({ + ok: true, + }); + + // Mock mutation failure + (mockConnection.applyMutation as jest.Mock).mockRejectedValueOnce( + new Error('Mutation failed'), + ); + + // Should not throw but log the error + await provider.refresh(logger); + + expect(mockConnection.applyMutation).toHaveBeenCalled(); + }); + }); +}); diff --git a/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts new file mode 100644 index 0000000000..7097edf2ca --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts @@ -0,0 +1,266 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import * as uuid from 'uuid'; +import { Config } from '@backstage/config'; +import { InputError } from '@backstage/errors'; +import { + EntityProvider, + EntityProviderConnection, + locationSpecToLocationEntity, +} from '@backstage/plugin-catalog-node'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { + GiteaIntegration, + getGiteaRequestOptions, + ScmIntegrations, +} from '@backstage/integration'; +import { getGiteaApiUrl } from './core'; + +import { readGiteaConfigs } from './config'; +import { GiteaProjectQueryResult, GiteaProviderConfig } from './types'; +import { + LoggerService, + SchedulerService, + SchedulerServiceTaskRunner, +} from '@backstage/backend-plugin-api'; + +/** @public */ +export class GiteaEntityProvider implements EntityProvider { + private readonly config: GiteaProviderConfig; + private readonly integration: GiteaIntegration; + private readonly logger: LoggerService; + private readonly scheduleFn: () => Promise; + private connection?: EntityProviderConnection; + + static fromConfig( + configRoot: Config, + options: { + logger: LoggerService; + schedule?: SchedulerServiceTaskRunner; + scheduler?: SchedulerService; + }, + ): GiteaEntityProvider[] { + if (!options.schedule && !options.scheduler) { + throw new Error('Either schedule or scheduler must be provided.'); + } + + const providerConfigs = readGiteaConfigs(configRoot); + const integrations = ScmIntegrations.fromConfig(configRoot).gitea; + const providers: GiteaEntityProvider[] = []; + + providerConfigs.forEach(providerConfig => { + const integration = integrations.byHost(providerConfig.host); + if (!integration) { + throw new InputError( + `No Gitea integration found that matches host ${providerConfig.host}`, + ); + } + + if (!options.schedule && !providerConfig.schedule) { + throw new Error( + `No schedule provided neither via code nor config for Gitea-provider:${providerConfig.id}.`, + ); + } + + const taskRunner = + options.schedule ?? + options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!); + + providers.push( + new GiteaEntityProvider( + providerConfig, + integration, + options.logger, + taskRunner, + ), + ); + }); + + return providers; + } + + private constructor( + config: GiteaProviderConfig, + integration: GiteaIntegration, + logger: LoggerService, + taskRunner: SchedulerServiceTaskRunner, + ) { + this.config = config; + this.integration = integration; + this.logger = logger.child({ + target: this.getProviderName(), + }); + this.scheduleFn = this.createScheduleFn(taskRunner); + } + + getProviderName(): string { + return `gitea-provider:${this.config.id}`; + } + + async connect(connection: EntityProviderConnection): Promise { + this.connection = connection; + await this.scheduleFn(); + } + + private async parseGiteaJsonResponse( + response: Response, + ): Promise { + if (!response.ok) { + throw new Error( + `Failed to fetch Gitea repositories, status: ${response.status}`, + ); + } + try { + return await response.json(); + } catch (error) { + throw new Error(`Failed to parse Gitea API response: ${error}`); + } + } + + private createScheduleFn( + taskRunner: SchedulerServiceTaskRunner, + ): () => Promise { + return async () => { + const taskId = `${this.getProviderName()}:refresh`; + return taskRunner.run({ + id: taskId, + fn: async () => { + const logger = this.logger.child({ + class: GiteaEntityProvider.prototype.constructor.name, + taskId, + taskInstanceId: uuid.v4(), + }); + + try { + await this.refresh(logger); + } catch (error) { + logger.error( + `${this.getProviderName()} refresh failed, ${error}`, + error as Error, + ); + } + }, + }); + }; + } + + async refresh(logger: LoggerService): Promise { + if (!this.connection) { + throw new Error('Gitea discovery connection not initialized'); + } + let allRepos: any[] = []; + + try { + // Step 1: Fetch all repos for an organization + const OrgRepoApiUrl = `${getGiteaApiUrl(this.integration.config)}orgs/${ + this.config.organization + }/repos`; + let page = 1; + let hasMoreData = true; + + while (hasMoreData) { + const url = `${OrgRepoApiUrl}?page=${page}`; + const response = await fetch(url, { + method: 'GET', + ...getGiteaRequestOptions(this.integration.config), + }); + + if (!response.ok) { + throw new Error( + `Failed to fetch page ${page} of repos, status: ${response.status}`, + ); + } + + const projectsPage = (await this.parseGiteaJsonResponse( + response, + )) as GiteaProjectQueryResult; + + if (!Array.isArray(projectsPage) || projectsPage.length === 0) { + hasMoreData = false; + } else { + allRepos = allRepos.concat(projectsPage); + page++; + } + } + } catch (e) { + throw new Error( + `Failed to list Gitea projects for organization ${this.config.organization}, ${e}`, + ); + } + + // Step 2: Filter for repos that have catalog-info.yaml at root + const { default: pLimit } = await import('p-limit'); + const limit = pLimit(5); + const validRepos: string[] = []; + + await Promise.all( + allRepos.map(repo => + limit(async () => { + if (repo.empty) { + logger.warn(`Repo ${repo.html_url} is empty, skipping`); + return; + } + const contentsApiUrl = `${getGiteaApiUrl( + this.integration.config, + )}repos/${this.config.organization}/${repo.name}/contents/${ + this.config.catalogPath + }`; + + const res = await fetch(contentsApiUrl, { + method: 'GET', + ...getGiteaRequestOptions(this.integration.config), + }); + if (res.ok) { + validRepos.push(repo.html_url); + } else { + logger.warn( + `Repo ${repo.html_url} does not contain a catalog-info.yaml file`, + ); + return; + } + }), + ), + ); + // Step 3: create location specs for each valid repo + const locations = await Promise.all( + validRepos.map(repo => limit(() => this.createLocationSpec(repo))), + ); + // Step 4: Apply the locations to the catalog + try { + const providerName: string = this.getProviderName(); + const entities = locations.map(location => ({ + locationKey: providerName, + entity: locationSpecToLocationEntity({ location }), + })); + await this.connection.applyMutation({ + type: 'full', + entities: entities, + }); + } catch (e) { + logger.error(`Failed to apply mutation: ${e}`); + } + logger.info( + `Found ${locations.length} locations from ${allRepos.length} repos`, + ); + } + + private async createLocationSpec(repo: string): Promise { + return { + type: 'url', + target: `${repo}/src/branch/${this.config.branch}/${this.config.catalogPath}`, + }; + } +} diff --git a/plugins/catalog-backend-module-gitea/src/providers/config.test.ts b/plugins/catalog-backend-module-gitea/src/providers/config.test.ts new file mode 100644 index 0000000000..5efece4e5a --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/config.test.ts @@ -0,0 +1,125 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { readGiteaConfigs } from './config'; +import { ConfigReader } from '@backstage/config'; +import { readSchedulerServiceTaskScheduleDefinitionFromConfig } from '@backstage/backend-plugin-api'; + +jest.mock('@backstage/backend-plugin-api', () => ({ + ...jest.requireActual('@backstage/backend-plugin-api'), + readSchedulerServiceTaskScheduleDefinitionFromConfig: jest.fn(), +})); +jest.mock('p-limit'); + +describe('readGiteaConfigs', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it('returns empty array when no gitea provider config is present', () => { + const config = new ConfigReader({}); + + const result = readGiteaConfigs(config); + + expect(result).toEqual([]); + }); + + it('parses multiple gitea provider configurations correctly', () => { + ( + readSchedulerServiceTaskScheduleDefinitionFromConfig as jest.Mock + ).mockReturnValue({ + frequency: { minutes: 5 }, + timeout: { minutes: 3 }, + }); + + const config = new ConfigReader({ + catalog: { + providers: { + gitea: { + myProvider: { + host: 'gitea.example.com', + organization: 'example-org', + branch: 'dev', + catalogPath: 'custom-path.yaml', + schedule: { + frequency: { minutes: 5 }, + timeout: { minutes: 3 }, + }, + }, + }, + }, + }, + }); + + const result = readGiteaConfigs(config); + + expect(result).toEqual([ + { + id: 'myProvider', + host: 'gitea.example.com', + organization: 'example-org', + branch: 'dev', + catalogPath: 'custom-path.yaml', + schedule: { + frequency: { minutes: 5 }, + timeout: { minutes: 3 }, + }, + }, + ]); + }); + + it('applies defaults for optional fields', () => { + const config = new ConfigReader({ + catalog: { + providers: { + gitea: { + default: { + host: 'gitea.com', + organization: 'default-org', + }, + }, + }, + }, + }); + + const result = readGiteaConfigs(config); + + expect(result[0]).toMatchObject({ + id: 'default', + host: 'gitea.com', + organization: 'default-org', + branch: 'main', + catalogPath: 'catalog-info.yaml', + schedule: undefined, + }); + }); + + it('throws if required fields are missing', () => { + const config = new ConfigReader({ + catalog: { + providers: { + gitea: { + bad: {}, + }, + }, + }, + }); + + expect(() => readGiteaConfigs(config)).toThrow( + /Missing required config value/, + ); + }); +}); diff --git a/plugins/catalog-backend-module-gitea/src/providers/config.ts b/plugins/catalog-backend-module-gitea/src/providers/config.ts new file mode 100644 index 0000000000..5863e76bf0 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/config.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { readSchedulerServiceTaskScheduleDefinitionFromConfig } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; +import { GiteaProviderConfig } from './types'; + +function readGiteaConfig(id: string, config: Config): GiteaProviderConfig { + const branch = config.getOptionalString('branch') ?? 'main'; + const catalogPath = + config.getOptionalString('catalogPath') ?? 'catalog-info.yaml'; + const host = config.getString('host'); + const organization = config.getString('organization'); + + const schedule = config.has('schedule') + ? readSchedulerServiceTaskScheduleDefinitionFromConfig( + config.getConfig('schedule'), + ) + : undefined; + + return { + branch, + catalogPath, + host, + id, + schedule, + organization, + }; +} + +export function readGiteaConfigs(config: Config): GiteaProviderConfig[] { + const configs: GiteaProviderConfig[] = []; + + const providerConfigs = config.getOptionalConfig('catalog.providers.gitea'); + + if (!providerConfigs) { + return configs; + } + + for (const id of providerConfigs.keys()) { + configs.push(readGiteaConfig(id, providerConfigs.getConfig(id))); + } + + return configs; +} diff --git a/plugins/catalog-backend-module-gitea/src/providers/core.test.ts b/plugins/catalog-backend-module-gitea/src/providers/core.test.ts new file mode 100644 index 0000000000..883dab7edc --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/core.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getGiteaApiUrl } from './core'; +import { GiteaIntegrationConfig } from '@backstage/integration'; + +describe('getGiteaApiUrl', () => { + it('should return the correct Gitea API base URL', () => { + const config: GiteaIntegrationConfig = { + host: 'gitea.example.com', + baseUrl: 'https://gitea.example.com', + }; + + const result = getGiteaApiUrl(config); + + expect(result).toBe('https://gitea.example.com/api/v1/'); + }); + + it('should handle trailing slash in baseUrl correctly', () => { + const config: GiteaIntegrationConfig = { + host: 'gitea.example.com', + baseUrl: 'https://gitea.example.com/', + }; + + const result = getGiteaApiUrl(config); + + expect(result).toBe('https://gitea.example.com//api/v1/'); + }); +}); diff --git a/plugins/catalog-backend-module-gitea/src/providers/core.ts b/plugins/catalog-backend-module-gitea/src/providers/core.ts new file mode 100644 index 0000000000..c994f3a714 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/core.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { GiteaIntegrationConfig } from '@backstage/integration'; +/** + * Return the url to query available repos using the Gitea API. + * + * @param config - A Gitea provider config. + * @public + */ +export function getGiteaApiUrl(config: GiteaIntegrationConfig) { + return `${config.baseUrl}/api/v1/`; +} diff --git a/plugins/catalog-backend-module-gitea/src/providers/index.ts b/plugins/catalog-backend-module-gitea/src/providers/index.ts new file mode 100644 index 0000000000..9914fda397 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { getGiteaApiUrl } from './core'; diff --git a/plugins/catalog-backend-module-gitea/src/providers/types.ts b/plugins/catalog-backend-module-gitea/src/providers/types.ts new file mode 100644 index 0000000000..0bbd09f9e7 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/src/providers/types.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugin-api'; + +export type GiteaProjectInfo = { + id: string; + name: string; + parent?: string; + state?: string; + branch?: string; +}; + +export type GiteaProjectQueryResult = Record; + +export type GiteaProviderConfig = { + host: string; + id: string; + branch?: string; + catalogPath?: string; + organization?: string; + schedule?: SchedulerServiceTaskScheduleDefinition; +}; diff --git a/yarn.lock b/yarn.lock index f700a3af06..6fa02a3a52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5942,6 +5942,24 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-catalog-backend-module-gitea@workspace:plugins/catalog-backend-module-gitea": + version: 0.0.0-use.local + resolution: "@backstage/plugin-catalog-backend-module-gitea@workspace:plugins/catalog-backend-module-gitea" + dependencies: + "@backstage/backend-common": "npm:^0.25.0" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-catalog-node": "workspace:^" + p-limit: "npm:^3.0.2" + uuid: "npm:^11.0.0" + languageName: unknown + linkType: soft + "@backstage/plugin-catalog-backend-module-github-org@workspace:plugins/catalog-backend-module-github-org": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-github-org@workspace:plugins/catalog-backend-module-github-org" From e08577146159378b11974d23fe2f7a8b484cb055 Mon Sep 17 00:00:00 2001 From: Kamil Markow Date: Thu, 8 May 2025 11:27:41 -0400 Subject: [PATCH 064/143] Update docs on TemplateExamples and how to test them Signed-off-by: Kamil Markow --- .../writing-custom-actions.md | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 9a502d7195..009e3c9506 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -151,11 +151,15 @@ and writing of template entity definitions. ### Adding a TemplateExample -A TemplateExample is a predefined structure that can be used to create custom actions in your software templates. It -serves as a blueprint for users to understand how to use a specific action and its fields as well as to ensure -consistency and standardization across different custom actions. +A TemplateExample is a way to document different ways that your custom action can be used. Once added it will be visible +in your backstage instance under [/create/actions](https://demo.backstage.io/create/actions) path. You can have multiple +examples for one action that can demonstrate different combinations of inputs and how to use them. -#### Define a TemplateExample and add to your Custom Action +#### Define TemplateExamples + +Below is a sample TemplateExample that is used for `publish:github`. The source code is available +on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts) +and preview on [demo.backstage.io/create/actions](https://demo.backstage.io/create/actions) ```ts title="With JSON Schema" import { TemplateExample } from '@backstage/plugin-scaffolder-node'; @@ -163,15 +167,33 @@ import yaml from 'yaml'; export const examples: TemplateExample[] = [ { - description: 'Template Example for Creating an Acme file', + description: 'Initializes a GitHub repository with a description.', example: yaml.stringify({ steps: [ { - action: 'acme:file:create', - name: 'Create an Acme file.', + id: 'publish', + action: 'publish:github', + name: 'Publish to GitHub', input: { - contents: 'file contents...', - filename: 'ACME.properties', + repoUrl: 'github.com?repo=repo&owner=owner', + description: 'Initialize a git repository', + }, + }, + ], + }), + }, + { + description: + 'Initializes a GitHub repository with public repo visibility, if not set defaults to private', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:github', + name: 'Publish to GitHub', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + repoVisibility: 'public', }, }, ], @@ -180,24 +202,28 @@ export const examples: TemplateExample[] = [ ]; ``` -Add the example to `createTemplateAction` by including the `examples` property: +#### Register TemplateExample with your custom action + +It is also crucial +to [register](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.ts#L126) +the `TemplateExample` when calling `createTemplateAction` by including the `examples` +property. ```ts return createTemplateAction({ - id: 'acme:file:create', - description: 'Create an Acme file', - schema: { - input: { - contents: d => d.string().describe('The contents of the file'), - filename: d => - d.string().describe('The filename of the file that will be created'), - }, - }, + id: 'publish:github', + description: + 'Initializes a git repository of contents in workspace and publishes it to GitHub.', examples, // ...rest of the action configuration }); ``` +#### Test TemplateAction examples + +It is also possible to test your example TemplateActions. You can see a sample test +on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts) + ### The context object When the action `handler` is called, we provide you a `context` as the only From a51855db73ac325e79df3b221e48e582f7c3fd88 Mon Sep 17 00:00:00 2001 From: Matt Benson Date: Thu, 8 May 2025 15:59:33 -0500 Subject: [PATCH 065/143] add unit tests for parseRepoUrl Signed-off-by: Matt Benson --- .../scaffolder-node/src/actions/util.test.ts | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 plugins/scaffolder-node/src/actions/util.test.ts diff --git a/plugins/scaffolder-node/src/actions/util.test.ts b/plugins/scaffolder-node/src/actions/util.test.ts new file mode 100644 index 0000000000..71e173c585 --- /dev/null +++ b/plugins/scaffolder-node/src/actions/util.test.ts @@ -0,0 +1,222 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ScmIntegrationRegistry } from '@backstage/integration'; +import { parseRepoUrl } from './util'; + +const queryString = ( + params: Partial< + Record<'owner' | 'organization' | 'workspace' | 'project' | 'repo', string> + > = {}, +): string => { + const pEntries = Object.entries(params); + if (pEntries.length) { + return `?${pEntries + .map(([k, v]) => `${k}=${encodeURIComponent(v)}`) + .join('&')}`; + } + return ''; +}; + +describe('scaffolder action utils', () => { + describe('parseRepoUrl', () => { + const byHost = jest.fn(); + const integrations = { + byHost, + } as unknown as ScmIntegrationRegistry; + + describe('rejects url when', () => { + it('empty', () => + expect(() => parseRepoUrl('', integrations)).toThrow( + /Invalid repo URL passed/, + )); + it('blank', () => + expect(() => parseRepoUrl(' ', integrations)).toThrow( + /Invalid repo URL passed/, + )); + }); + it('requires that host match an integration type', () => { + byHost.mockClear(); + expect(() => parseRepoUrl('foo', integrations)).toThrow( + /No matching integration configuration for host/, + ); + }); + describe('bitbucket', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'bitbucket' })); + describe('cloud', () => { + const [host, workspace, project, repo] = [ + 'www.bitbucket.org', + 'foo', + 'bar', + 'baz', + ]; + it('requires workspace', () => + expect(() => + parseRepoUrl( + `${host}${queryString({ project, repo })}`, + integrations, + ), + ).toThrow(/missing workspace/)); + it('requires project', () => + expect(() => + parseRepoUrl( + `${host}${queryString({ workspace, repo })}`, + integrations, + ), + ).toThrow(/missing project/)); + it('requires repo', () => + expect(() => + parseRepoUrl( + `${host}${queryString({ workspace, project })}`, + integrations, + ), + ).toThrow(/missing repo/)); + it('happy path', () => + expect( + parseRepoUrl( + `${host}${queryString({ workspace, project, repo })}`, + integrations, + ), + ).toMatchObject({ + host, + workspace, + project, + repo, + })); + }); + describe('other', () => { + const [host, project, repo] = ['bitbucket.other', 'foo', 'bar']; + it('requires project', () => + expect(() => + parseRepoUrl(`${host}${queryString({ repo })}`, integrations), + ).toThrow(/missing project/)); + it('requires repo', () => + expect(() => + parseRepoUrl(`${host}${queryString({ project })}`, integrations), + ).toThrow(/missing repo/)); + it('happy path', () => + expect( + parseRepoUrl( + `${host}${queryString({ project, repo })}`, + integrations, + ), + ).toMatchObject({ + host, + project, + repo, + })); + }); + }); + describe('azure', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'azure' })); + const [host, project, repo] = ['az.ure', 'foo', 'bar']; + it('requires project', () => + expect(() => + parseRepoUrl(`${host}${queryString({ repo })}`, integrations), + ).toThrow(/missing project/)); + it('requires repo', () => + expect(() => + parseRepoUrl(`${host}${queryString({ project })}`, integrations), + ).toThrow(/missing repo/)); + it('happy path', () => + expect( + parseRepoUrl( + `${host}${queryString({ project, repo })}`, + integrations, + ), + ).toMatchObject({ + host, + project, + repo, + })); + }); + describe('gitlab', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'gitlab' })); + const [host, owner, repo, project] = ['gitl.ab', 'foo', 'bar', '123456']; + it('requires owner', () => + expect(() => + parseRepoUrl(`${host}${queryString({ repo })}`, integrations), + ).toThrow(/missing owner/)); + it('requires repo', () => + expect(() => + parseRepoUrl(`${host}${queryString({ owner })}`, integrations), + ).toThrow(/missing repo/)); + it('unless project specified', () => + expect( + parseRepoUrl(`${host}${queryString({ project })}`, integrations), + ).toMatchObject({ host, project })); + it('happy path', () => + expect( + parseRepoUrl(`${host}${queryString({ owner, repo })}`, integrations), + ).toMatchObject({ + host, + owner, + repo, + })); + }); + describe('gitea', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'gitea' })); + const [host, repo] = ['git.ea', 'foo']; + it('requires repo', () => + expect(() => parseRepoUrl(host, integrations)).toThrow(/missing repo/)); + it('happy path', () => + expect( + parseRepoUrl(`${host}${queryString({ repo })}`, integrations), + ).toMatchObject({ host, repo })); + }); + describe('gerrit', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'gerrit' })); + const [host, repo] = ['gerr.it', 'foo']; + it('requires repo', () => + expect(() => parseRepoUrl(host, integrations)).toThrow(/missing repo/)); + it('happy path', () => + expect( + parseRepoUrl(`${host}${queryString({ repo })}`, integrations), + ).toMatchObject({ + host, + repo, + })); + }); + describe('generic type', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'generic' })); + const [host, owner, repo] = ['oth.er', 'foo', 'bar']; + it('requires owner', () => + expect(() => + parseRepoUrl(`${host}${queryString({ repo })}`, integrations), + ).toThrow(/missing owner/)); + it('requires repo', () => + expect(() => + parseRepoUrl(`${host}${queryString({ owner })}`, integrations), + ).toThrow(/missing repo/)); + it('happy path', () => + expect( + parseRepoUrl(`${host}${queryString({ owner, repo })}`, integrations), + ).toMatchObject({ + host, + owner, + repo, + })); + }); + describe('facilitates naive URL construction', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'irrelevant' })); + it('decodes encoded params', () => { + const [host, owner, repo] = ['with_the_most', 'foo/bar/baz', 'blah']; + expect( + parseRepoUrl(`${host}${queryString({ owner, repo })}`, integrations), + ).toMatchObject({ host, owner, repo }); + }); + }); + }); +}); From 16e2e9c1db2c17632af8110ce80cc10b9dac68d0 Mon Sep 17 00:00:00 2001 From: Matt Benson Date: Thu, 8 May 2025 16:25:20 -0500 Subject: [PATCH 066/143] trim leading and trailing slashes from parseRepoUrl query parameters Signed-off-by: Matt Benson --- .changeset/proud-women-hammer.md | 5 ++++ plugins/scaffolder-node/package.json | 4 ++- .../scaffolder-node/src/actions/util.test.ts | 25 +++++++++++++++++++ plugins/scaffolder-node/src/actions/util.ts | 19 +++++++------- yarn.lock | 2 ++ 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 .changeset/proud-women-hammer.md diff --git a/.changeset/proud-women-hammer.md b/.changeset/proud-women-hammer.md new file mode 100644 index 0000000000..030fc5bf7b --- /dev/null +++ b/.changeset/proud-women-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-node': patch +--- + +trim leading and trailing slashes from parseRepoUrl query parameters diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 011b09c91f..ba938c3843 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -66,6 +66,7 @@ "globby": "^11.0.0", "isomorphic-git": "^1.23.0", "jsonschema": "^1.5.0", + "lodash": "^4.17.21", "p-limit": "^3.1.0", "tar": "^6.1.12", "winston": "^3.2.1", @@ -76,6 +77,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@backstage/config": "workspace:^" + "@backstage/config": "workspace:^", + "@types/lodash": "^4.14.151" } } diff --git a/plugins/scaffolder-node/src/actions/util.test.ts b/plugins/scaffolder-node/src/actions/util.test.ts index 71e173c585..4b1e787bbc 100644 --- a/plugins/scaffolder-node/src/actions/util.test.ts +++ b/plugins/scaffolder-node/src/actions/util.test.ts @@ -15,6 +15,7 @@ */ import { ScmIntegrationRegistry } from '@backstage/integration'; import { parseRepoUrl } from './util'; +import { mapValues } from 'lodash'; const queryString = ( params: Partial< @@ -217,6 +218,30 @@ describe('scaffolder action utils', () => { parseRepoUrl(`${host}${queryString({ owner, repo })}`, integrations), ).toMatchObject({ host, owner, repo }); }); + it('trims leading and trailing / from params', () => { + const [host, owner, organization, workspace, project, repo] = [ + 'anywhere', + 'anyone', + 'anything', + 'anyway', + 'anyhow', + 'any', + ]; + const junkedUp = mapValues( + { owner, organization, workspace, project, repo }, + v => `//${v}//`, + ); + return expect( + parseRepoUrl(`${host}${queryString(junkedUp)}`, integrations), + ).toMatchObject({ + host, + owner, + organization, + workspace, + project, + repo, + }); + }); }); }); }); diff --git a/plugins/scaffolder-node/src/actions/util.ts b/plugins/scaffolder-node/src/actions/util.ts index f1775bb318..12f73b0c6c 100644 --- a/plugins/scaffolder-node/src/actions/util.ts +++ b/plugins/scaffolder-node/src/actions/util.ts @@ -22,6 +22,7 @@ import { TemplateActionOptions } from './createTemplateAction'; import zodToJsonSchema from 'zod-to-json-schema'; import { z } from 'zod'; import { Schema } from 'jsonschema'; +import { trim } from 'lodash'; /** * @public @@ -67,11 +68,6 @@ export const parseRepoUrl = ( ); } const host = parsed.host; - const owner = parsed.searchParams.get('owner') ?? undefined; - const organization = parsed.searchParams.get('organization') ?? undefined; - const workspace = parsed.searchParams.get('workspace') ?? undefined; - const project = parsed.searchParams.get('project') ?? undefined; - const type = integrations.byHost(host)?.type; if (!type) { @@ -79,8 +75,14 @@ export const parseRepoUrl = ( `No matching integration configuration for host ${host}, please check your integrations config`, ); } - - const repo: string = parsed.searchParams.get('repo')!; + const { owner, organization, workspace, project, repo } = Object.fromEntries( + ['owner', 'organization', 'workspace', 'project', 'repo'].map(param => [ + param, + parsed.searchParams.has(param) + ? trim(parsed.searchParams.get(param)!, '/') + : undefined, + ]), + ); switch (type) { case 'bitbucket': { if (host === 'www.bitbucket.org') { @@ -113,8 +115,7 @@ export const parseRepoUrl = ( break; } } - - return { host, owner, repo, organization, workspace, project }; + return { host, owner, repo: repo!, organization, workspace, project }; }; function checkRequiredParams(repoUrl: URL, ...params: string[]) { diff --git a/yarn.lock b/yarn.lock index f700a3af06..1d55543152 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8020,11 +8020,13 @@ __metadata: "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/types": "workspace:^" "@isomorphic-git/pgp-plugin": "npm:^0.0.7" + "@types/lodash": "npm:^4.14.151" concat-stream: "npm:^2.0.0" fs-extra: "npm:^11.2.0" globby: "npm:^11.0.0" isomorphic-git: "npm:^1.23.0" jsonschema: "npm:^1.5.0" + lodash: "npm:^4.17.21" p-limit: "npm:^3.1.0" tar: "npm:^6.1.12" winston: "npm:^3.2.1" From ec42f8ed8ec23573f1acb240661c9e3107e56b32 Mon Sep 17 00:00:00 2001 From: Bogdan Nechyporenko Date: Fri, 9 May 2025 07:31:25 +0200 Subject: [PATCH 067/143] Fix issue 29505: Retries with EXPERIMENTAL_strategy doesn't handle authentication properly Signed-off-by: Bogdan Nechyporenko --- .changeset/young-dancers-shave.md | 6 ++++++ plugins/scaffolder-backend/report.api.md | 10 ++++++++-- .../src/scaffolder/tasks/DatabaseTaskStore.ts | 10 ++++++++-- .../src/scaffolder/tasks/StorageTaskBroker.ts | 7 +++++-- .../src/scaffolder/tasks/types.ts | 2 +- .../scaffolder-backend/src/service/router.ts | 17 ++++++++++++++++- plugins/scaffolder-node/report.api.md | 2 +- plugins/scaffolder-node/src/tasks/types.ts | 2 +- 8 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 .changeset/young-dancers-shave.md diff --git a/.changeset/young-dancers-shave.md b/.changeset/young-dancers-shave.md new file mode 100644 index 0000000000..f7cdc3f3c2 --- /dev/null +++ b/.changeset/young-dancers-shave.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-node': patch +--- + +Generating new tokens on each Scaffolder Task Retry diff --git a/plugins/scaffolder-backend/report.api.md b/plugins/scaffolder-backend/report.api.md index 0438922de3..41c228e3f1 100644 --- a/plugins/scaffolder-backend/report.api.md +++ b/plugins/scaffolder-backend/report.api.md @@ -502,7 +502,10 @@ export class DatabaseTaskStore implements TaskStore { targetPath: string; }): Promise; // (undocumented) - retryTask?(options: { taskId: string }): Promise; + retryTask?(options: { + secrets?: TaskSecrets_2; + taskId: string; + }): Promise; // (undocumented) saveTaskState(options: { taskId: string; state?: JsonObject }): Promise; // (undocumented) @@ -769,7 +772,10 @@ export interface TaskStore { targetPath: string; }): Promise; // (undocumented) - retryTask?(options: { taskId: string }): Promise; + retryTask?(options: { + secrets?: TaskSecrets_2; + taskId: string; + }): Promise; // (undocumented) saveTaskState?(options: { taskId: string; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 4dbe938679..51a30a20ec 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -654,12 +654,18 @@ export class DatabaseTaskStore implements TaskStore { }); } - async retryTask?(options: { taskId: string }): Promise { + async retryTask?(options: { + secrets?: TaskSecrets; + taskId: string; + }): Promise { + const { secrets, taskId } = options; + await this.db.transaction(async tx => { const result = await tx('tasks') - .where('id', options.taskId) + .where('id', taskId) .update( { + ...(secrets && { secrets: JSON.stringify(secrets) }), status: 'open', last_heartbeat_at: this.db.fn.now(), }, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 0fd18a9ee5..27a4499772 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -503,8 +503,11 @@ export class StorageTaskBroker implements TaskBroker { }); } - async retry?(taskId: string): Promise { - await this.storage.retryTask?.({ taskId }); + async retry?(options: { + secrets?: TaskSecrets; + taskId: string; + }): Promise { + await this.storage.retryTask?.(options); this.signalDispatch(); } } diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index 874793922f..1556c4838c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -171,7 +171,7 @@ export interface TaskStore { options: TaskStoreCreateTaskOptions, ): Promise; - retryTask?(options: { taskId: string }): Promise; + retryTask?(options: { secrets?: TaskSecrets; taskId: string }): Promise; recoverTasks?( options: TaskStoreRecoverTaskOptions, diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index e5c384987a..f2e323e831 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -828,7 +828,22 @@ export async function createRouter( await auditorEvent?.success(); - await taskBroker.retry?.(taskId); + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: 'catalog', + }); + + const secrets: InternalTaskSecrets = { + ...req.body.secrets, + backstageToken: token, + __initiatorCredentials: JSON.stringify({ + ...credentials, + // credentials.token is nonenumerable and will not be serialized, so we need to add it explicitly + token: (credentials as any).token, + }), + }; + + await taskBroker.retry?.({ secrets, taskId }); res.status(201).json({ id: taskId }); } catch (err) { await auditorEvent?.fail({ error: err }); diff --git a/plugins/scaffolder-node/report.api.md b/plugins/scaffolder-node/report.api.md index 6dabcbf346..f2e8501527 100644 --- a/plugins/scaffolder-node/report.api.md +++ b/plugins/scaffolder-node/report.api.md @@ -414,7 +414,7 @@ export interface TaskBroker { // (undocumented) recoverTasks?(): Promise; // (undocumented) - retry?(taskId: string): Promise; + retry?(options: { secrets?: TaskSecrets; taskId: string }): Promise; // (undocumented) vacuumTasks(options: { timeoutS: number }): Promise; } diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index fdfeb49a0b..d8cfd24530 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -165,7 +165,7 @@ export interface TaskContext { export interface TaskBroker { cancel?(taskId: string): Promise; - retry?(taskId: string): Promise; + retry?(options: { secrets?: TaskSecrets; taskId: string }): Promise; claim(): Promise; From a29ef4316aa849bbae80fe580356200b9d4ec209 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Fri, 9 May 2025 13:34:47 +0530 Subject: [PATCH 068/143] Add KodeKloud Certified Backstage Associate Course to Training and Certifications section Signed-off-by: Abhinav --- microsite/src/pages/community/index.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/microsite/src/pages/community/index.tsx b/microsite/src/pages/community/index.tsx index 0a45464805..8c1736e1e9 100644 --- a/microsite/src/pages/community/index.tsx +++ b/microsite/src/pages/community/index.tsx @@ -70,6 +70,13 @@ const Community = () => { link: 'https://www.cncf.io/training/certification/cba/', label: 'Learn more', }, + { + title: 'KodeKloud Certified Backstage Associate Course', + content: + 'KodeKloud offers an interactive course with hands-on labs to prepare you for the Certified Backstage Associate exam. Perfect for practical learners who want to gain real-world Backstage skills.', + link: 'https://learn.kodekloud.com/user/courses?search=backstage', + label: 'Learn more', + }, ]; const partners: { name: string; url: string; logo: string }[] = [ From ee9f59f3e0011f1ff54bdd9d65312c3992d486e0 Mon Sep 17 00:00:00 2001 From: Benjamin Janssens Date: Fri, 9 May 2025 11:47:59 +0200 Subject: [PATCH 069/143] feat(catalog): add filter to include archived repositories Signed-off-by: Benjamin Janssens --- .changeset/old-parents-cut.md | 5 +++++ docs/integrations/github/discovery.md | 2 ++ .../catalog-backend-module-github/config.d.ts | 10 ++++++++++ .../src/providers/GithubEntityProvider.ts | 19 +++++++++++-------- .../GithubEntityProviderConfig.test.ts | 9 +++++++++ .../providers/GithubEntityProviderConfig.ts | 8 ++++++-- 6 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 .changeset/old-parents-cut.md diff --git a/.changeset/old-parents-cut.md b/.changeset/old-parents-cut.md new file mode 100644 index 0000000000..d2fdaac564 --- /dev/null +++ b/.changeset/old-parents-cut.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Added filter to include archived repositories diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index 354569cdb6..1c45d12f83 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -168,6 +168,8 @@ If you do so, `default` will be used as provider ID. If configured, all repositories _except_ those with one (or more) topics(s) present in the exclusion filter will be ingested. - **`visibility`** _(optional)_: An array of strings used to filter results based on their visibility. Available options are `private`, `internal`, `public`. If configured (non empty), only repositories with visibility present in the filter will be ingested + - **`includeArchived`** _(optional)_: + Whether to include archived repositories. Defaults to `false`. - **`host`** _(optional)_: The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md). - **`organization`**: diff --git a/plugins/catalog-backend-module-github/config.d.ts b/plugins/catalog-backend-module-github/config.d.ts index c94593b985..976256ac9e 100644 --- a/plugins/catalog-backend-module-github/config.d.ts +++ b/plugins/catalog-backend-module-github/config.d.ts @@ -117,6 +117,11 @@ export interface Config { * (Optional) GitHub repository visibility filter. */ visibility?: Array<'private' | 'internal' | 'public'>; + /** + * (Optional) Whether to include archived repositories. + * Default: `false`. + */ + includeArchived?: boolean; }; /** * (Optional) TaskScheduleDefinition for the refresh. @@ -186,6 +191,11 @@ export interface Config { * (Optional) GitHub repository visibility filter. */ visibility?: Array<'private' | 'internal' | 'public'>; + /** + * (Optional) Whether to include archived repositories. + * Default: `false`. + */ + includeArchived?: boolean; }; /** * (Optional) TaskScheduleDefinition for the refresh. diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts index e0837de54e..7790be56a0 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts @@ -256,15 +256,16 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { } private matchesFilters(repositories: Repository[]): Repository[] { - const repositoryFilter = this.config.filters?.repository; - const topicFilters = this.config.filters?.topic; - const allowForks = this.config.filters?.allowForks ?? true; - const visibilities = this.config.filters?.visibility ?? []; + const repositoryFilter = this.config.filters.repository; + const topicFilters = this.config.filters.topic; + const allowForks = this.config.filters.allowForks; + const visibilities = this.config.filters.visibility ?? []; + const includeArchived = this.config.filters.includeArchived; return repositories.filter(r => { const repoTopics: string[] = r.repositoryTopics; return ( - !r.isArchived && + (includeArchived || !r.isArchived) && (!repositoryFilter || repositoryFilter.test(r.name)) && satisfiesTopicFilter(repoTopics, topicFilters) && satisfiesForkFilter(allowForks, r.isFork) && @@ -276,7 +277,7 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { private createLocationUrl(repository: Repository): string { const branch = - this.config.filters?.branch || repository.defaultBranchRef || '-'; + this.config.filters.branch || repository.defaultBranchRef || '-'; const catalogFile = this.config.catalogPath.startsWith('/') ? this.config.catalogPath.substring(1) : this.config.catalogPath; @@ -334,7 +335,7 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { this.logger.debug(`handle github:push event for ${repoName} - ${repoUrl}`); const branch = - this.config.filters?.branch || event.repository.default_branch; + this.config.filters.branch || event.repository.default_branch; if (!event.ref.includes(branch)) { this.logger.debug(`skipping push event from ref ${event.ref}`); @@ -468,6 +469,8 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { * @param event - The repository archived event. */ private async onRepoArchived(event: RepositoryArchivedEvent) { + if (this.config.filters.includeArchived) return; + const repository = this.createRepoFromEvent(event); await this.removeEntitiesForRepo(repository); this.logger.debug( @@ -549,7 +552,7 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { * * Creates new entities for the repository if it matches the filters. * - * @param event - The repository unarchived event. + * @param event - The repository transferred event. */ private async onRepoTransferred(event: RepositoryTransferredEvent) { const repository = this.createRepoFromEvent(event); diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts index bddb4d27cd..0edde80252 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts @@ -126,6 +126,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -144,6 +145,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -162,6 +164,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -180,6 +183,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -198,6 +202,7 @@ describe('readProviderConfigs', () => { exclude: ['backstage-exclude'], }, visibility: undefined, + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -216,6 +221,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -234,6 +240,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: ['public', 'internal'], + includeArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -252,6 +259,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, validateLocationsExist: false, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, @@ -270,6 +278,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, + includeArchived: false, }, schedule: { frequency: { minutes: 30 }, diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts index 781239978f..9004444f28 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts @@ -37,12 +37,13 @@ export type GithubEntityProviderConfig = { catalogPath: string; organization: string; host: string; - filters?: { + filters: { repository?: RegExp; branch?: string; topic?: GithubTopicFilters; - allowForks?: boolean; + allowForks: boolean; visibility?: string[]; + includeArchived: boolean; }; validateLocationsExist: boolean; schedule?: SchedulerServiceTaskScheduleDefinition; @@ -90,6 +91,8 @@ function readProviderConfig( const topicFilterExclude = config?.getOptionalStringArray( 'filters.topic.exclude', ); + const includeArchived = + config.getOptionalBoolean('filters.includeArchived') ?? false; const validateLocationsExist = config?.getOptionalBoolean('validateLocationsExist') ?? false; @@ -132,6 +135,7 @@ function readProviderConfig( exclude: topicFilterExclude, }, visibility: visibilityFilterInclude, + includeArchived, }, schedule, validateLocationsExist, From 9e6c479fddee34fe94a5ecccf9ae078a826704c5 Mon Sep 17 00:00:00 2001 From: Benjamin Janssens Date: Fri, 9 May 2025 11:57:57 +0200 Subject: [PATCH 070/143] test(catalog:) extend existing tests Signed-off-by: Benjamin Janssens --- .../GithubEntityProviderConfig.test.ts | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts index 0edde80252..9ed1bb2e27 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts @@ -92,6 +92,12 @@ describe('readProviderConfigs', () => { visibility: ['public', 'internal'], }, }, + providerWithArchiveFilter: { + organization: 'test-org6', + filters: { + includeArchived: true, + }, + }, providerWithHost: { organization: 'test-org1', host: 'ghe.internal.com', @@ -111,7 +117,7 @@ describe('readProviderConfigs', () => { }); const providerConfigs = readProviderConfigs(config); - expect(providerConfigs).toHaveLength(9); + expect(providerConfigs).toHaveLength(10); expect(providerConfigs[0]).toEqual({ id: 'providerOrganizationOnly', organization: 'test-org1', @@ -246,6 +252,25 @@ describe('readProviderConfigs', () => { validateLocationsExist: false, }); expect(providerConfigs[7]).toEqual({ + id: 'providerWithArchiveFilter', + organization: 'test-org6', + catalogPath: '/catalog-info.yaml', + host: 'github.com', + filters: { + repository: undefined, + branch: undefined, + allowForks: true, + topic: { + include: undefined, + exclude: undefined, + }, + visibility: undefined, + includeArchived: true, + }, + schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, + validateLocationsExist: false, + }); + expect(providerConfigs[8]).toEqual({ id: 'providerWithHost', organization: 'test-org1', catalogPath: '/catalog-info.yaml', @@ -264,7 +289,7 @@ describe('readProviderConfigs', () => { validateLocationsExist: false, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, }); - expect(providerConfigs[8]).toEqual({ + expect(providerConfigs[9]).toEqual({ id: 'providerWithSchedule', organization: 'test-org1', catalogPath: '/catalog-info.yaml', From b85aeefdd5c0fe543231084639d93e5c01cb49da Mon Sep 17 00:00:00 2001 From: Gustavo Lira e Silva Date: Fri, 9 May 2025 10:57:04 -0300 Subject: [PATCH 071/143] Update plugins/catalog-backend/README.md Co-authored-by: Paul Schultz Signed-off-by: Gustavo Lira e Silva --- plugins/catalog-backend/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend/README.md b/plugins/catalog-backend/README.md index 0d544160d0..8593ade53e 100644 --- a/plugins/catalog-backend/README.md +++ b/plugins/catalog-backend/README.md @@ -94,7 +94,8 @@ The Catalog backend emits audit events for various operations. Events are groupe **Entity Events:** - **`entity-fetch`**: Retrieves entities. -- **Note:** By default, `entity-fetch` audit events are not visible in the log output. This is because these events are classified with a severity level of "low", which maps to the "debug" log level. The default log level in Backstage is "info", so debug-level events (severity "low") are filtered out. To see `entity-fetch` events in the logs, adjust the Auditor Service configuration by setting `backend.auditor.severityLogLevelMappings.low` to `info` in your `app-config.yaml`. For more information, refer to the [Auditor Service documentation on severity levels and default mappings](https://backstage.io/docs/backend-system/core-services/auditor/#severity-levels-and-default-mappings). +- **Note:** By default, "low" severity audit events like `entity-fetch` aren't logged because they map to the "debug" level, while Backstage defaults to "info" level logging. To see `entity-fetch` events, update your `app-config.yaml` by setting `backend.auditor.severityLogLevelMappings.low: info`. See the [Auditor Service documentation](https://backstage.io/docs/backend-system/core-services/auditor/#severity-levels-and-default-mappings) for details on severity mappings. + Filter on `queryType`. From 269ce9604fab2fbcfb730ccccfaffb9d120d4dcd Mon Sep 17 00:00:00 2001 From: Gustavo Lira Date: Fri, 9 May 2025 12:56:09 -0300 Subject: [PATCH 072/143] update README to clarify logging configuration for entity-fetch audit events Signed-off-by: Gustavo Lira --- plugins/catalog-backend/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/catalog-backend/README.md b/plugins/catalog-backend/README.md index 8593ade53e..00b88cf060 100644 --- a/plugins/catalog-backend/README.md +++ b/plugins/catalog-backend/README.md @@ -96,7 +96,6 @@ The Catalog backend emits audit events for various operations. Events are groupe - **`entity-fetch`**: Retrieves entities. - **Note:** By default, "low" severity audit events like `entity-fetch` aren't logged because they map to the "debug" level, while Backstage defaults to "info" level logging. To see `entity-fetch` events, update your `app-config.yaml` by setting `backend.auditor.severityLogLevelMappings.low: info`. See the [Auditor Service documentation](https://backstage.io/docs/backend-system/core-services/auditor/#severity-levels-and-default-mappings) for details on severity mappings. - Filter on `queryType`. - **`all`**: Fetching all entities. (GET `/entities`) From 590bd5fefe971c510861c26c6bbd5c9cdbaeff88 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Fri, 9 May 2025 12:04:35 -0400 Subject: [PATCH 073/143] handle context menu item filtering in the entity page Signed-off-by: Mark Dunphy --- plugins/catalog-react/report-alpha.api.md | 30 ++++++- .../EntityContextMenuItemBlueprint.test.tsx | 18 ++++ .../EntityContextMenuItemBlueprint.tsx | 39 +++------ plugins/catalog/report-alpha.api.md | 79 +++++++++++++---- plugins/catalog/src/alpha/pages.test.tsx | 87 +++++++++++++++++++ plugins/catalog/src/alpha/pages.tsx | 33 +++++-- 6 files changed, 232 insertions(+), 54 deletions(-) diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index 595741ab67..bb296e7c28 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -338,7 +338,22 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ kind: 'entity-context-menu-item'; name: undefined; params: EntityContextMenuItemParams; - output: ConfigurableExtensionDataRef; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; inputs: {}; config: { filter: EntityPredicate | undefined; @@ -346,7 +361,18 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ configInput: { filter?: EntityPredicate | undefined; }; - dataRefs: never; + dataRefs: { + filterFunction: ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + {} + >; + filterExpression: ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + {} + >; + }; }>; // @alpha (undocumented) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 694e79bb8c..2491b714b1 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -220,6 +220,24 @@ describe('EntityContextMenuItemBlueprint', () => { "name": "test", "output": [ [Function], + { + "$$type": "@backstage/ExtensionDataRef", + "config": { + "optional": true, + }, + "id": "catalog.entity-filter-function", + "optional": [Function], + "toString": [Function], + }, + { + "$$type": "@backstage/ExtensionDataRef", + "config": { + "optional": true, + }, + "id": "catalog.entity-filter-expression", + "optional": [Function], + "toString": [Function], + }, ], "override": [Function], "toString": [Function], diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx index acc3ddbc48..59cd0b48e4 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx @@ -26,14 +26,12 @@ import ListItemText from '@material-ui/core/ListItemText'; import { useEntityContextMenu } from '../../hooks/useEntityContextMenu'; import { EntityPredicate } from '../predicates'; import type { Entity } from '@backstage/catalog-model'; -import { useEntity } from '../../hooks/useEntity'; import { entityFilterExpressionDataRef, entityFilterFunctionDataRef, } from './extensionData'; import { createEntityPredicateSchema } from '../predicates/createEntityPredicateSchema'; import { resolveEntityFilterData } from './resolveEntityFilterData'; -import { buildFilterFn } from '../filter/FilterWrapper'; /** @alpha */ export type UseProps = () => | { @@ -58,7 +56,15 @@ export type EntityContextMenuItemParams = { export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ kind: 'entity-context-menu-item', attachTo: { id: 'page:catalog/entity', input: 'contextMenuItems' }, - output: [coreExtensionData.reactElement], + output: [ + coreExtensionData.reactElement, + entityFilterFunctionDataRef.optional(), + entityFilterExpressionDataRef.optional(), + ], + dataRefs: { + filterFunction: entityFilterFunctionDataRef, + filterExpression: entityFilterExpressionDataRef, + }, config: { schema: { filter: z => @@ -66,30 +72,9 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ }, }, *factory(params: EntityContextMenuItemParams, { node, config }) { - const resolvedFilterData = []; - - for (const resolved of resolveEntityFilterData( - params.filter, - config, - node, - )) { - resolvedFilterData.push(resolved); - } - - const resolvedFilter = resolvedFilterData.pop(); - const filter = buildFilterFn( - resolvedFilter?.id === entityFilterFunctionDataRef.id - ? resolvedFilter.value - : undefined, - resolvedFilter?.id === entityFilterExpressionDataRef.id - ? resolvedFilter.value - : undefined, - ); - const loader = async () => { const Component = () => { const { onMenuClose } = useEntityContextMenu(); - const { entity } = useEntity(); const { title, ...menuItemProps } = params.useProps(); let handleClick = undefined; @@ -104,10 +89,6 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ }; } - if (entity && !filter(entity)) { - return null; - } - return ( {params.icon} @@ -120,5 +101,7 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ }; yield coreExtensionData.reactElement(ExtensionBoundary.lazy(node, loader)); + + yield* resolveEntityFilterData(params.filter, config, node); }, }); diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index 246c7929f0..93a4e94225 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -869,11 +869,22 @@ const _default: FrontendPlugin< configInput: { filter?: EntityPredicate | undefined; }; - output: ConfigurableExtensionDataRef< - JSX_2.Element, - 'core.reactElement', - {} - >; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; inputs: {}; params: EntityContextMenuItemParams; }>; @@ -886,11 +897,22 @@ const _default: FrontendPlugin< configInput: { filter?: EntityPredicate | undefined; }; - output: ConfigurableExtensionDataRef< - JSX_2.Element, - 'core.reactElement', - {} - >; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; inputs: {}; params: EntityContextMenuItemParams; }>; @@ -903,11 +925,22 @@ const _default: FrontendPlugin< configInput: { filter?: EntityPredicate | undefined; }; - output: ConfigurableExtensionDataRef< - JSX_2.Element, - 'core.reactElement', - {} - >; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; inputs: {}; params: EntityContextMenuItemParams; }>; @@ -1057,7 +1090,21 @@ const _default: FrontendPlugin< } >; contextMenuItems: ExtensionInput< - ConfigurableExtensionDataRef, + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >, { singleton: false; optional: false; diff --git a/plugins/catalog/src/alpha/pages.test.tsx b/plugins/catalog/src/alpha/pages.test.tsx index f5aeb7d196..6e5d3fab95 100644 --- a/plugins/catalog/src/alpha/pages.test.tsx +++ b/plugins/catalog/src/alpha/pages.test.tsx @@ -36,6 +36,7 @@ import { } from '@backstage/plugin-catalog-react'; import { convertLegacyRouteRef } from '@backstage/core-compat-api'; import { rootRouteRef } from '../routes'; +import { Entity } from '@backstage/catalog-model'; describe('Entity page', () => { const entityMock = { @@ -733,5 +734,91 @@ describe('Entity page', () => { expect(onClickMock).toHaveBeenCalledTimes(disabled ? 0 : 1); }); }); + + it.each([ + { + positive: { params: {} }, + negative: { params: { filter: 'kind:api' } }, + }, + { + positive: { params: { filter: 'kind:component' } }, + negative: { params: { filter: 'kind:api' } }, + }, + { + positive: { + params: { + filter: (e: Entity) => e.kind.toLowerCase() === 'component', + }, + }, + negative: { + params: { filter: (e: Entity) => e.kind.toLowerCase() === 'api' }, + }, + }, + ])( + 'should render menu items according to filters', + async ({ positive, negative }) => { + const menuItem = EntityContextMenuItemBlueprint.make({ + name: 'should-render-menu-item', + params: { + icon: Test Icon, + useProps: () => ({ + onClick: onClickMock, + title: 'Should Render', + }), + ...positive.params, + }, + }); + + const filteredMenuItem = EntityContextMenuItemBlueprint.make({ + name: 'should-not-render-menu-item', + params: { + icon: Test Icon, + useProps: () => ({ + onClick: onClickMock, + title: 'Should Not Render', + }), + ...negative.params, + }, + }); + + const tester = createExtensionTester( + Object.assign({ namespace: 'catalog' }, catalogEntityPage), + ) + .add(menuItem) + .add(filteredMenuItem); + + renderInTestApp( + + {tester.reactElement()} + , + { + config: { + app: { + title: 'Custom app', + }, + backend: { baseUrl: 'http://localhost:7000' }, + }, + mountedRoutes: { + '/catalog': convertLegacyRouteRef(rootRouteRef), + '/catalog/:namespace/:kind/:name': + convertLegacyRouteRef(entityRouteRef), + }, + }, + ); + + await waitFor(async () => { + await userEvent.click(screen.getByTestId('menu-button')); + expect(screen.getByText('Should Render')).toBeInTheDocument(); + expect( + screen.queryByText('Should Not Render'), + ).not.toBeInTheDocument(); + }); + }, + ); }); }); diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index f822cb0fed..3708ae11fa 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -32,10 +32,10 @@ import { EntityContentBlueprint, defaultEntityContentGroups, buildFilterFn, + EntityContextMenuItemBlueprint, } from '@backstage/plugin-catalog-react/alpha'; import { rootRouteRef } from '../routes'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; -import { EntityHeader } from './components/EntityHeader'; export const catalogPage = PageBlueprint.makeWithOverrides({ inputs: { @@ -72,7 +72,11 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ EntityContentBlueprint.dataRefs.filterExpression.optional(), EntityContentBlueprint.dataRefs.group.optional(), ]), - contextMenuItems: createExtensionInput([coreExtensionData.reactElement]), + contextMenuItems: createExtensionInput([ + coreExtensionData.reactElement, + EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional(), + EntityContextMenuItemBlueprint.dataRefs.filterExpression.optional(), + ]), }, config: { schema: { @@ -89,9 +93,13 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ loader: async () => { const { EntityLayout } = await import('./components/EntityLayout'); - const menuItems = inputs.contextMenuItems.map(item => - item.get(coreExtensionData.reactElement), - ); + const menuItems = inputs.contextMenuItems.map(item => ({ + element: item.get(coreExtensionData.reactElement), + filter: buildFilterFn( + item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction), + item.get(EntityContextMenuItemBlueprint.dataRefs.filterExpression), + ), + })); type Groups = Record< string, @@ -100,7 +108,7 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ const header = inputs.header?.get( EntityHeaderBlueprint.dataRefs.element, - ) ?? ; + ); let groups = Object.entries(defaultEntityContentGroups).reduce( (rest, group) => { @@ -137,9 +145,18 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ } const Component = () => { + const entityFromUrl = useEntityFromUrl(); + const { entity } = entityFromUrl; + const filteredMenuItems = entity + ? menuItems.filter(i => i.filter(entity)).map(i => i.element) + : []; + return ( - - + + {Object.values(groups).flatMap(({ title, items }) => items.map(output => ( Date: Fri, 9 May 2025 21:05:21 +0200 Subject: [PATCH 074/143] docs: tweaks proxy usage Signed-off-by: Vincenzo Scamporlino --- .../using-backstage-proxy-within-plugin.md | 74 ++++++++++++++----- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/docs/tutorials/using-backstage-proxy-within-plugin.md b/docs/tutorials/using-backstage-proxy-within-plugin.md index f171f951c4..c82db9ff6c 100644 --- a/docs/tutorials/using-backstage-proxy-within-plugin.md +++ b/docs/tutorials/using-backstage-proxy-within-plugin.md @@ -22,10 +22,11 @@ If your plugin requires access to an API, backstage offers - [Setting up the backstage proxy](#setting-up-the-backstage-proxy) - [Calling an API using the backstage proxy](#calling-an-api-using-the-backstage-proxy) - - [Defining the API client interface](#defining-the-api-client-interface) - - [Creating the API client](#creating-the-api-client) - - [Bundling your ApiRef with your plugin](#bundling-your-apiref-with-your-plugin) - - [Using the API in your components](#using-your-plugin-in-your-components) + - [Option 1: Calling the proxy directly from the frontend plugin](#option-1-calling-the-proxy-directly-from-the-frontend-plugin) + - [Option 2: Defining the API client interface](#defining-the-api-client-interface) + - [Creating the API client](#creating-the-api-client) + - [Bundling your ApiRef with your plugin](#bundling-your-apiref-with-your-plugin) + - [Using the API in your components](#using-your-plugin-in-your-components) ## Setting up the backstage proxy @@ -55,9 +56,44 @@ the proxy. Backstage is structured in such a way that you could run the backstage frontend independently of the backend. So when calling your API you need to prepend the backend URL to your http call. -The recommended pattern for calling out to services is to wrap your calls in a -[Utility API](../api/utility-apis.md). This section describes the steps to wrap -your API client in a Utility API, which are: +There are two recommended patterns for calling out to services: using +`discoveryApi` and +`fetchApi` directly from your frontend plugin or wrapping your calls in a [Utility API](../api/utility-apis.md). + +## Option 1: Calling the proxy directly from the frontend plugin + +From you frontend plugin use the `fetchApi` and `discoveryApi` to call the proper +proxy endpoint: + +```tsx title="plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx" +import { + useApi, + discoveryApiRef, + fetchApiRef, +} from '@backstage/core-plugin-api'; +import { Progress, Alert } from '@backstage/core-components'; +import useAsync from 'react-use/esm/useAsync'; +import { myAwesomeApiRef } from '../../api'; + +export const AwesomeUsersTable = () => { + const fetchApi = useApi(fetchApiRef); + const discoveryApi = useApi(discoveryApiRef); + + const { value, loading, error } = useAsync(async () => { + const baseUrl = await discoveryApi.getBaseUrl('proxy'); + // As configured previously for the backend proxy + const resp = await fetchApi.fetch(`${baseUrl}/`); + if (!resp.ok) throw new Error(resp.statusText); + return resp.json(); + }, [fetchApi, discoveryApi]); + + // ... +}; +``` + +## Option 2: Defining the API client interface + +This section describes the steps to wrap your API client in a [Utility API](../api/utility-apis.md), which are: - use [`createApiRef`](../reference/core-plugin-api.createapiref.md) to create a new [`ApiRef`](../reference/core-plugin-api.apiref.md) @@ -69,7 +105,7 @@ your API client in a Utility API, which are: - finally, you can use your API in your components by calling [`useApi`](../reference/core-plugin-api.useapi.md) -## Defining the API client interface +### Defining the API client interface Continuing from the previous example, let's assume that _https://api.myawesomeservice.com/v1_ has the following endpoints: @@ -103,7 +139,7 @@ export const myAwesomeApiRef = createApiRef({ }); ``` -## Creating the API client +### Creating the API client The `myAwesomeApiRef` is what you will use within backstage to reference the API client in your plugin. The API ref itself is a global singleton object that @@ -155,7 +191,7 @@ export class MyAwesomeApiClient implements MyAwesomeApi { > [DiscoveryApi](../reference/core-plugin-api.discoveryapi.md) or the > [FetchApi](../reference/core-plugin-api.fetchapi.md) -## Bundling your ApiRef with your plugin +### Bundling your ApiRef with your plugin The final piece in the puzzle is bundling the `myAwesomeApiRef` with a factory for `MyAwesomeApiClient` objects. This is usually done in the `plugin.ts` file @@ -195,22 +231,24 @@ export const myCustomPlugin = createPlugin({ }); ``` -## Using the API in your components +### Using the API in your components Now you should be able to access your API using the backstage hook [`useApi`](../reference/core-plugin-api.useapi.md) from within your plugin code. -```ts -/* plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx */ +```ts title="plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx" import { useApi } from '@backstage/core-plugin-api'; import { myAwesomeApiRef } from '../../api'; +import useAsync from 'react-use/esm/useAsync'; export const AwesomeUsersTable = () => { const apiClient = useApi(myAwesomeApiRef); - apiClient.listUsers() - .then( - ... - ) -} + const { value, loading, error } = useAsync(async () => { + const users = await apiClient.listUsers(); + return users; + }, [apiClient]); + + // ... +}; ``` From 651b56033240ad701e138eb52eddb3ffec35511b Mon Sep 17 00:00:00 2001 From: Reyna Nikolayev Date: Fri, 9 May 2025 15:13:53 -0700 Subject: [PATCH 075/143] rename CatalogReactComponentsNameToClassKey as suggested Signed-off-by: Reyna Nikolayev --- .changeset/honest-teams-shave.md | 1 + plugins/home-react/report.api.md | 14 +++++++------- plugins/home-react/src/overridableComponents.ts | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.changeset/honest-teams-shave.md b/.changeset/honest-teams-shave.md index 931cfd2f63..6afbf37039 100644 --- a/.changeset/honest-teams-shave.md +++ b/.changeset/honest-teams-shave.md @@ -4,6 +4,7 @@ --- Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. +Renamed `CatalogReactComponentsNameToClassKey` to `PluginHomeComponentsNameToClassKey` in `overridableComponents.ts` Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. diff --git a/plugins/home-react/report.api.md b/plugins/home-react/report.api.md index ee14be9a3f..26ef6267aa 100644 --- a/plugins/home-react/report.api.md +++ b/plugins/home-react/report.api.md @@ -13,8 +13,8 @@ import { UiSchema } from '@rjsf/utils'; // @public (undocumented) export type BackstageOverrides = Overrides & { - [Name in keyof CatalogReactComponentsNameToClassKey]?: Partial< - StyleRules + [Name in keyof PluginHomeComponentsNameToClassKey]?: Partial< + StyleRules >; }; @@ -49,11 +49,6 @@ export type CardSettings = { uiSchema?: UiSchema; }; -// @public (undocumented) -export type CatalogReactComponentsNameToClassKey = { - PluginHomeContentModal: PluginHomeContentModalClassKey; -}; - // @public (undocumented) export type ComponentParts = { Content: (props?: any) => JSX.Element; @@ -86,6 +81,11 @@ export function createCardExtension(options: { settings?: CardSettings; }): Extension<(props: CardExtensionProps) => JSX_2.Element>; +// @public (undocumented) +export type PluginHomeComponentsNameToClassKey = { + PluginHomeContentModal: PluginHomeContentModalClassKey; +}; + // @public (undocumented) export type PluginHomeContentModalClassKey = 'contentModal' | 'linkText'; diff --git a/plugins/home-react/src/overridableComponents.ts b/plugins/home-react/src/overridableComponents.ts index e9ee530de0..8a88fd5c94 100644 --- a/plugins/home-react/src/overridableComponents.ts +++ b/plugins/home-react/src/overridableComponents.ts @@ -19,18 +19,18 @@ import { StyleRules } from '@material-ui/core/styles/withStyles'; import { PluginHomeContentModalClassKey } from './'; /** @public */ -export type CatalogReactComponentsNameToClassKey = { +export type PluginHomeComponentsNameToClassKey = { PluginHomeContentModal: PluginHomeContentModalClassKey; }; /** @public */ export type BackstageOverrides = Overrides & { - [Name in keyof CatalogReactComponentsNameToClassKey]?: Partial< - StyleRules + [Name in keyof PluginHomeComponentsNameToClassKey]?: Partial< + StyleRules >; }; declare module '@backstage/theme' { interface OverrideComponentNameToClassKeys - extends CatalogReactComponentsNameToClassKey {} + extends PluginHomeComponentsNameToClassKey {} } From c2cae47800d7555300184c78a74efa3a9d1e8e8a Mon Sep 17 00:00:00 2001 From: aramissennyeydd Date: Fri, 9 May 2025 23:26:15 -0400 Subject: [PATCH 076/143] fix: missing commands in backstage-cli-alpha Signed-off-by: aramissennyeydd --- .changeset/fifty-trains-bow.md | 5 + .../cli/cli-report.backstage-cli-alpha.md | 96 +++++++++++++++++++ packages/cli/src/alpha.ts | 12 ++- 3 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 .changeset/fifty-trains-bow.md diff --git a/.changeset/fifty-trains-bow.md b/.changeset/fifty-trains-bow.md new file mode 100644 index 0000000000..29c0ee4315 --- /dev/null +++ b/.changeset/fifty-trains-bow.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': minor +--- + +Add missing modules to the Backstage CLI alpha entrypoint. diff --git a/packages/cli/cli-report.backstage-cli-alpha.md b/packages/cli/cli-report.backstage-cli-alpha.md index 386a642c21..331385f6f6 100644 --- a/packages/cli/cli-report.backstage-cli-alpha.md +++ b/packages/cli/cli-report.backstage-cli-alpha.md @@ -241,8 +241,12 @@ Options: Commands: build + clean help [command] lint + postpack + prepack + start test ``` @@ -260,6 +264,15 @@ Options: -h, --help ``` +### `backstage-cli-alpha package clean` + +``` +Usage: program [options] + +Options: + -h, --help +``` + ### `backstage-cli-alpha package lint` ``` @@ -273,6 +286,40 @@ Options: -h, --help ``` +### `backstage-cli-alpha package postpack` + +``` +Usage: program [options] + +Options: + -h, --help +``` + +### `backstage-cli-alpha package prepack` + +``` +Usage: program [options] + +Options: + -h, --help +``` + +### `backstage-cli-alpha package start` + +``` +Usage: program [options] + +Options: + --check + --config + --inspect [host] + --inspect-brk [host] + --link + --require + --role + -h, --help +``` + ### `backstage-cli-alpha package test` ``` @@ -397,8 +444,12 @@ Options: Commands: build + clean + fix help [command] lint + list-deprecations + start test ``` @@ -414,6 +465,26 @@ Options: -h, --help ``` +### `backstage-cli-alpha repo clean` + +``` +Usage: program [options] + +Options: + -h, --help +``` + +### `backstage-cli-alpha repo fix` + +``` +Usage: program [options] + +Options: + --check + --publish + -h, --help +``` + ### `backstage-cli-alpha repo lint` ``` @@ -430,6 +501,31 @@ Options: -h, --help ``` +### `backstage-cli-alpha repo list-deprecations` + +``` +Usage: program [options] + +Options: + --json + -h, --help +``` + +### `backstage-cli-alpha repo start` + +``` +Usage: program [options] [...packageNameOrPath] + +Options: + --config + --inspect [host] + --inspect-brk [host] + --link + --plugin + --require + -h, --help +``` + ### `backstage-cli-alpha repo test` ``` diff --git a/packages/cli/src/alpha.ts b/packages/cli/src/alpha.ts index 3324ed8d75..a29594e135 100644 --- a/packages/cli/src/alpha.ts +++ b/packages/cli/src/alpha.ts @@ -25,13 +25,15 @@ import chalk from 'chalk'; ), ); const initializer = new CliInitializer(); - initializer.add(import('./modules/new/alpha')); + initializer.add(import('./modules/build/alpha')); + initializer.add(import('./modules/config/alpha')); initializer.add(import('./modules/create-github-app/alpha')); initializer.add(import('./modules/info/alpha')); - initializer.add(import('./modules/config/alpha')); - initializer.add(import('./modules/build/alpha')); - initializer.add(import('./modules/migrate/alpha')); - initializer.add(import('./modules/test/alpha')); initializer.add(import('./modules/lint/alpha')); + initializer.add(import('./modules/maintenance/alpha')); + initializer.add(import('./modules/migrate/alpha')); + initializer.add(import('./modules/new/alpha')); + initializer.add(import('./modules/start/alpha')); + initializer.add(import('./modules/test/alpha')); await initializer.run(); })(); From e344416dd7e152445aabc3b56eb38739b44e40c7 Mon Sep 17 00:00:00 2001 From: aramissennyeydd Date: Fri, 9 May 2025 23:32:15 -0400 Subject: [PATCH 077/143] owners: apply for tooling-maintainers Signed-off-by: aramissennyeydd --- OWNERS.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/OWNERS.md b/OWNERS.md index b29889fec1..85ffadae42 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -168,14 +168,15 @@ Team: @backstage/tooling-maintainers Scope: All published Backstage CLI tools in the main `backstage` repository that do not belong to other areas, including `@backstage/cli` and `@backstage/repo-tools`. -| Name | Organization | Team | GitHub | Discord | -| -------------------- | ------------ | ------------- | ----------------------------------------------- | --------------- | -| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` | -| Ben Lambert | Spotify | Cubic Belugas | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` | -| Camila Loiola | Spotify | Cubic Belugas | [camilaibs](http://github.com/camilaibs) | `camilal#0226` | -| Fredrik Adelöw | Spotify | Cubic Belugas | [freben](https://github.com/freben) | `freben#3926` | -| Mihai Tabara | Spotify | Cubic Belugas | [MihaiTabara](http://github.com/MihaiTabara) | `mihait#3107` | -| Vincenzo Scamporlino | Spotify | Cubic Belugas | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` | +| Name | Organization | Team | GitHub | Discord | +| -------------------- | ------------ | ------------- | ----------------------------------------------------- | --------------- | +| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` | +| Ben Lambert | Spotify | Cubic Belugas | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` | +| Camila Loiola | Spotify | Cubic Belugas | [camilaibs](http://github.com/camilaibs) | `camilal#0226` | +| Fredrik Adelöw | Spotify | Cubic Belugas | [freben](https://github.com/freben) | `freben#3926` | +| Mihai Tabara | Spotify | Cubic Belugas | [MihaiTabara](http://github.com/MihaiTabara) | `mihait#3107` | +| Vincenzo Scamporlino | Spotify | Cubic Belugas | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` | +| Aramis Sennyey | DoorDash | | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` | ## Incubating Project Areas From f1ea17f20f2275b00555053070286702a4a8881e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 12 May 2025 11:02:06 +0200 Subject: [PATCH 078/143] remove explicit tag fetching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .github/workflows/sync_version-packages.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index 4a33b2241e..d01e805fb7 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -24,9 +24,6 @@ jobs: fetch-tags: true token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - - name: Fetch tags # See https://github.com/actions/checkout/issues/2041 - run: git fetch --tags - - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request From ab2180d85563d7e7294c9e007912711a41bed292 Mon Sep 17 00:00:00 2001 From: Musaab Elfaqih Date: Mon, 12 May 2025 12:18:37 +0200 Subject: [PATCH 079/143] use more specific flags type Signed-off-by: Musaab Elfaqih --- packages/frontend-app-api/report.api.md | 4 +++- packages/frontend-app-api/src/wiring/createSpecializedApp.tsx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/frontend-app-api/report.api.md b/packages/frontend-app-api/report.api.md index 91a33d277d..d2a3ac4d3b 100644 --- a/packages/frontend-app-api/report.api.md +++ b/packages/frontend-app-api/report.api.md @@ -34,7 +34,9 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; - flags?: Record; + flags?: { + allowUnknownExtensionConfig?: boolean; + }; }): { apis: ApiHolder; tree: AppTree; diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 3d356e2a74..dbe5868176 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -208,7 +208,7 @@ export function createSpecializedApp(options?: { extensionFactoryMiddleware?: | ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; - flags?: Record; + flags?: { allowUnknownExtensionConfig?: boolean }; }): { apis: ApiHolder; tree: AppTree } { const config = options?.config ?? new ConfigReader({}, 'empty-config'); const features = deduplicateFeatures(options?.features ?? []); From 2cb6ba630b09a545aaea8b300eec09b6f0651df6 Mon Sep 17 00:00:00 2001 From: "Kevin L." Date: Sun, 11 May 2025 14:02:10 -0400 Subject: [PATCH 080/143] Fix a broken link in the page "Keeping Backstage Updated". Signed-off-by: Kevin L. --- docs/getting-started/keeping-backstage-updated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/keeping-backstage-updated.md b/docs/getting-started/keeping-backstage-updated.md index a44cb3c8bc..dea0cc2939 100644 --- a/docs/getting-started/keeping-backstage-updated.md +++ b/docs/getting-started/keeping-backstage-updated.md @@ -21,7 +21,7 @@ starting point that's meant to be evolved. The Backstage CLI has a command to bump all `@backstage` packages and dependencies you're using to the latest versions: -[versions:bump](https://backstage.io/docs/tooling/cli/03-commands#versionsbump). +[versions:bump](../tooling/cli/03-commands.md#versionsbump). ```bash yarn backstage-cli versions:bump From 9f3bdef5f321afefa4261a970a1dc68db7c66032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 12 May 2025 15:10:24 +0200 Subject: [PATCH 081/143] use the new version of the changeset action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .github/workflows/sync_version-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index d01e805fb7..42dadb5a57 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -27,7 +27,7 @@ jobs: - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request - uses: backstage/changesets-action@291bfc1f76d1dcfbf967f5810dc0423592eae09a # v2.3.1 + uses: backstage/changesets-action@a39baf18913e669734ffb00c2fd9900472cfa240 # v2.3.2 with: # Calls out to `changeset version`, but also runs prettier version: yarn release From 4034e67bf3d42d8cf2dfb672001336fcd23c252f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 14:12:48 +0000 Subject: [PATCH 082/143] Update dependency @changesets/cli to v2.29.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1d55543152..03834abf75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9216,9 +9216,9 @@ __metadata: languageName: node linkType: hard -"@changesets/assemble-release-plan@npm:^6.0.7": - version: 6.0.7 - resolution: "@changesets/assemble-release-plan@npm:6.0.7" +"@changesets/assemble-release-plan@npm:^6.0.8": + version: 6.0.8 + resolution: "@changesets/assemble-release-plan@npm:6.0.8" dependencies: "@changesets/errors": "npm:^0.2.0" "@changesets/get-dependents-graph": "npm:^2.1.3" @@ -9226,7 +9226,7 @@ __metadata: "@changesets/types": "npm:^6.1.0" "@manypkg/get-packages": "npm:^1.1.3" semver: "npm:^7.5.3" - checksum: 10/61e0962c8116b802de11c7eddc34aa0a827166dba84686b69705da7c8e57bf16101f062b4de784a622f511e967554685b050d6f54fffe953da04f6564e65e414 + checksum: 10/5d01fc42c67229874cc70b93fbdc971e11909aa7a72f1909c585ecb3fdc69f3ac105d243e1341cd5b07c02dee133be461fa48138125f00d137e71f8b7e8f428e languageName: node linkType: hard @@ -9240,16 +9240,16 @@ __metadata: linkType: hard "@changesets/cli@npm:^2.14.0": - version: 2.29.3 - resolution: "@changesets/cli@npm:2.29.3" + version: 2.29.4 + resolution: "@changesets/cli@npm:2.29.4" dependencies: "@changesets/apply-release-plan": "npm:^7.0.12" - "@changesets/assemble-release-plan": "npm:^6.0.7" + "@changesets/assemble-release-plan": "npm:^6.0.8" "@changesets/changelog-git": "npm:^0.2.1" "@changesets/config": "npm:^3.1.1" "@changesets/errors": "npm:^0.2.0" "@changesets/get-dependents-graph": "npm:^2.1.3" - "@changesets/get-release-plan": "npm:^4.0.11" + "@changesets/get-release-plan": "npm:^4.0.12" "@changesets/git": "npm:^3.0.4" "@changesets/logger": "npm:^0.1.1" "@changesets/pre": "npm:^2.0.2" @@ -9273,7 +9273,7 @@ __metadata: term-size: "npm:^2.1.0" bin: changeset: bin.js - checksum: 10/9ab528d026651b8544d071000d7c26a9f6ac157299050ca67279b001ef6215f9647b83906aa5a4c761215696d898e704e5613df16c81c4bab7895ef1fabea9e0 + checksum: 10/fc325447b81a811464107e72a687f6c0414c5f928e518cb122d1efde1d71c205b1972464795ab97fb26087900ea55b99a551e9a010c9681def3d7561fd1c3f0b languageName: node linkType: hard @@ -9313,17 +9313,17 @@ __metadata: languageName: node linkType: hard -"@changesets/get-release-plan@npm:^4.0.11": - version: 4.0.11 - resolution: "@changesets/get-release-plan@npm:4.0.11" +"@changesets/get-release-plan@npm:^4.0.12": + version: 4.0.12 + resolution: "@changesets/get-release-plan@npm:4.0.12" dependencies: - "@changesets/assemble-release-plan": "npm:^6.0.7" + "@changesets/assemble-release-plan": "npm:^6.0.8" "@changesets/config": "npm:^3.1.1" "@changesets/pre": "npm:^2.0.2" "@changesets/read": "npm:^0.6.5" "@changesets/types": "npm:^6.1.0" "@manypkg/get-packages": "npm:^1.1.3" - checksum: 10/4a05b4474847a60604dc6158d0c8204a400a98fcb4593dc46b897abca3a1ce1eea40af208100e119e50ad693e34f061cc9b84912aa5ff3eb1560d4db59a4af59 + checksum: 10/d6482ecb6f1c2c47266493a36d05b484f0950d0a4472820649e953d073e3fdd612cdd8a4df9e3d7e00756d4e446dae639f9d6e0dab8a25f76bb6df77cd91c21c languageName: node linkType: hard From e3240feef3d744c7cfb1fd9cfd26794ba88dc592 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 14:21:23 +0000 Subject: [PATCH 083/143] Update dependency @rspack/core to v1.3.9 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 166 +++++++++++++++++++++++++++--------------------------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/yarn.lock b/yarn.lock index c448914729..03d40b8f3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12287,10 +12287,10 @@ __metadata: languageName: node linkType: hard -"@module-federation/error-codes@npm:0.13.0": - version: 0.13.0 - resolution: "@module-federation/error-codes@npm:0.13.0" - checksum: 10/42a826d374f8451c320236f73f1337f69449d1875ee1141e70a0150c4820cd2c0a2997bb134aa01f39e405fe7142d5998b008c8ea32d493e9a507ae7c29c3ec9 +"@module-federation/error-codes@npm:0.13.1": + version: 0.13.1 + resolution: "@module-federation/error-codes@npm:0.13.1" + checksum: 10/fa9bbc0936ad9d037116c05f741bfb0ff741c3e2eaa682fa0132f4825d66ef0c63da0c20ec931ca16c8e7b660c1fdc60101a24ccab8951f19e07fba642aa1c6a languageName: node linkType: hard @@ -12358,13 +12358,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime-core@npm:0.13.0": - version: 0.13.0 - resolution: "@module-federation/runtime-core@npm:0.13.0" +"@module-federation/runtime-core@npm:0.13.1": + version: 0.13.1 + resolution: "@module-federation/runtime-core@npm:0.13.1" dependencies: - "@module-federation/error-codes": "npm:0.13.0" - "@module-federation/sdk": "npm:0.13.0" - checksum: 10/04d23270be780dc3626a2391d14fe7b794aed9dc2e31b02339d399e9369b21cdc4c80b86edd14a06b0142fe711539284b381a2ea4894898923d3b457a472e569 + "@module-federation/error-codes": "npm:0.13.1" + "@module-federation/sdk": "npm:0.13.1" + checksum: 10/81b52eb7866f623115922af325bcc1dba6c85f95216dfa2cbf2f777b37ec11ba856846892a4a5ab446105a18837c495b0a05cb5d574f7d2e50f340d1e57413f4 languageName: node linkType: hard @@ -12378,13 +12378,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime-tools@npm:0.13.0": - version: 0.13.0 - resolution: "@module-federation/runtime-tools@npm:0.13.0" +"@module-federation/runtime-tools@npm:0.13.1": + version: 0.13.1 + resolution: "@module-federation/runtime-tools@npm:0.13.1" dependencies: - "@module-federation/runtime": "npm:0.13.0" - "@module-federation/webpack-bundler-runtime": "npm:0.13.0" - checksum: 10/deb7abf5e44714a19766ec6009efd656e9e4da8e1ddeea775fa8d2d4b3d2e165629163ed86c83a003a4f4e76f17649b9d889582ce0c5d35a7a2eacf8da5bfb2e + "@module-federation/runtime": "npm:0.13.1" + "@module-federation/webpack-bundler-runtime": "npm:0.13.1" + checksum: 10/821f32979ef2235cd043b3ef561fd63f7554211bd86d3af7e17a57dd5c709c6ee2ae57935222318694732115d7771c122cf51fb9f71f879269d452bc5ab0a8d2 languageName: node linkType: hard @@ -12398,14 +12398,14 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime@npm:0.13.0": - version: 0.13.0 - resolution: "@module-federation/runtime@npm:0.13.0" +"@module-federation/runtime@npm:0.13.1": + version: 0.13.1 + resolution: "@module-federation/runtime@npm:0.13.1" dependencies: - "@module-federation/error-codes": "npm:0.13.0" - "@module-federation/runtime-core": "npm:0.13.0" - "@module-federation/sdk": "npm:0.13.0" - checksum: 10/a79accc2a44e2a8b5d6f5025582520c8904776c1b8fabe62554c20baf4602937a0bfdde2bf69c6b29cefb3e108ba8cc6b00c2dc78751da3f9dfd75722cede4af + "@module-federation/error-codes": "npm:0.13.1" + "@module-federation/runtime-core": "npm:0.13.1" + "@module-federation/sdk": "npm:0.13.1" + checksum: 10/2536ea17d0704bf4d093fe5791720e61fa3f4f4e83b6927b33f1d2ee132bf0cc9232e960cffefe32a6c79f3aedd864738b1be79b3790ad0c9dbd924f15ef2841 languageName: node linkType: hard @@ -12420,10 +12420,10 @@ __metadata: languageName: node linkType: hard -"@module-federation/sdk@npm:0.13.0": - version: 0.13.0 - resolution: "@module-federation/sdk@npm:0.13.0" - checksum: 10/aa08ca793fa6f0912d06f02592337340d973672a79f632b278527f72cc76ee19d3a95579ecb930ac355120b89c13c0260dc37fe08de1854f99626a796e5a6a7f +"@module-federation/sdk@npm:0.13.1": + version: 0.13.1 + resolution: "@module-federation/sdk@npm:0.13.1" + checksum: 10/7cfc98a6ee09aa338a9d76df146d064b5f4c6163b985daf3aa641e3f0e52d7cc40116b449cd1265b1333a66eeec31ce8bb40e1944f3ac62797d87323ce0e91ec languageName: node linkType: hard @@ -12445,13 +12445,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/webpack-bundler-runtime@npm:0.13.0": - version: 0.13.0 - resolution: "@module-federation/webpack-bundler-runtime@npm:0.13.0" +"@module-federation/webpack-bundler-runtime@npm:0.13.1": + version: 0.13.1 + resolution: "@module-federation/webpack-bundler-runtime@npm:0.13.1" dependencies: - "@module-federation/runtime": "npm:0.13.0" - "@module-federation/sdk": "npm:0.13.0" - checksum: 10/692fdbd6d99d5dac9420691f581eebbb7d0538a7b01e6f7d6d2e4c3ec23798962f693775a6239298e53daf4b7cb4b5cac4775ce15625257c7c12aa7d6aa5b398 + "@module-federation/runtime": "npm:0.13.1" + "@module-federation/sdk": "npm:0.13.1" + checksum: 10/bebccaa4411c00355bb399e2dddb946586967642b90da4d4436554093fecb614fdff6c65dc73cef944c7344f169d2c0ecc22ed0b5b899e21d4535507806145e0 languageName: node linkType: hard @@ -16548,82 +16548,82 @@ __metadata: languageName: node linkType: hard -"@rspack/binding-darwin-arm64@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-darwin-arm64@npm:1.3.8" +"@rspack/binding-darwin-arm64@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-darwin-arm64@npm:1.3.9" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-darwin-x64@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-darwin-x64@npm:1.3.8" +"@rspack/binding-darwin-x64@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-darwin-x64@npm:1.3.9" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rspack/binding-linux-arm64-gnu@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-linux-arm64-gnu@npm:1.3.8" +"@rspack/binding-linux-arm64-gnu@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-linux-arm64-gnu@npm:1.3.9" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-arm64-musl@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-linux-arm64-musl@npm:1.3.8" +"@rspack/binding-linux-arm64-musl@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-linux-arm64-musl@npm:1.3.9" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rspack/binding-linux-x64-gnu@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-linux-x64-gnu@npm:1.3.8" +"@rspack/binding-linux-x64-gnu@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-linux-x64-gnu@npm:1.3.9" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-x64-musl@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-linux-x64-musl@npm:1.3.8" +"@rspack/binding-linux-x64-musl@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-linux-x64-musl@npm:1.3.9" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rspack/binding-win32-arm64-msvc@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-win32-arm64-msvc@npm:1.3.8" +"@rspack/binding-win32-arm64-msvc@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-win32-arm64-msvc@npm:1.3.9" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-win32-ia32-msvc@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-win32-ia32-msvc@npm:1.3.8" +"@rspack/binding-win32-ia32-msvc@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-win32-ia32-msvc@npm:1.3.9" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rspack/binding-win32-x64-msvc@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding-win32-x64-msvc@npm:1.3.8" +"@rspack/binding-win32-x64-msvc@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding-win32-x64-msvc@npm:1.3.9" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rspack/binding@npm:1.3.8": - version: 1.3.8 - resolution: "@rspack/binding@npm:1.3.8" +"@rspack/binding@npm:1.3.9": + version: 1.3.9 + resolution: "@rspack/binding@npm:1.3.9" dependencies: - "@rspack/binding-darwin-arm64": "npm:1.3.8" - "@rspack/binding-darwin-x64": "npm:1.3.8" - "@rspack/binding-linux-arm64-gnu": "npm:1.3.8" - "@rspack/binding-linux-arm64-musl": "npm:1.3.8" - "@rspack/binding-linux-x64-gnu": "npm:1.3.8" - "@rspack/binding-linux-x64-musl": "npm:1.3.8" - "@rspack/binding-win32-arm64-msvc": "npm:1.3.8" - "@rspack/binding-win32-ia32-msvc": "npm:1.3.8" - "@rspack/binding-win32-x64-msvc": "npm:1.3.8" + "@rspack/binding-darwin-arm64": "npm:1.3.9" + "@rspack/binding-darwin-x64": "npm:1.3.9" + "@rspack/binding-linux-arm64-gnu": "npm:1.3.9" + "@rspack/binding-linux-arm64-musl": "npm:1.3.9" + "@rspack/binding-linux-x64-gnu": "npm:1.3.9" + "@rspack/binding-linux-x64-musl": "npm:1.3.9" + "@rspack/binding-win32-arm64-msvc": "npm:1.3.9" + "@rspack/binding-win32-ia32-msvc": "npm:1.3.9" + "@rspack/binding-win32-x64-msvc": "npm:1.3.9" dependenciesMeta: "@rspack/binding-darwin-arm64": optional: true @@ -16643,24 +16643,24 @@ __metadata: optional: true "@rspack/binding-win32-x64-msvc": optional: true - checksum: 10/2b4427240e97899845b08f592af4f806884b49e192fb2b5a93f450f11c97a3ecbef581bb32b9cf1b2bfca48fd65426a978011f04fc7484307e84005ffd174211 + checksum: 10/bf7679a324dbf67a563e27e9d441b161b0d292b64f24c47b3955a1f12f705b4a60c215735ea09cb2c4e2bfc68cb4dfb24af88daef055a683a7369a5156a2a808 languageName: node linkType: hard "@rspack/core@npm:^1.0.10": - version: 1.3.8 - resolution: "@rspack/core@npm:1.3.8" + version: 1.3.9 + resolution: "@rspack/core@npm:1.3.9" dependencies: - "@module-federation/runtime-tools": "npm:0.13.0" - "@rspack/binding": "npm:1.3.8" + "@module-federation/runtime-tools": "npm:0.13.1" + "@rspack/binding": "npm:1.3.9" "@rspack/lite-tapable": "npm:1.0.1" - caniuse-lite: "npm:^1.0.30001715" + caniuse-lite: "npm:^1.0.30001717" peerDependencies: "@swc/helpers": ">=0.5.1" peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/e2f3fd21d512faa3865a784f219f92b78497713e0e9dd2fd03c4ec6c9bcfa33c53c301f9d5c5546dd7e86e8e46309b0aef3ab6f1661fed10c622482b8717b588 + checksum: 10/9a4c5cdd51ba66354d27a27b23736c44a5eeac13c70729ae75589cb2bc4bbe600ceb0cf4b11cb0686f8cc96f61b3bf36827b269537c134713278a22d54eb6957 languageName: node linkType: hard @@ -25540,10 +25540,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001669, caniuse-lite@npm:^1.0.30001715": - version: 1.0.30001715 - resolution: "caniuse-lite@npm:1.0.30001715" - checksum: 10/5608cdaf609eb5fe3a86ab6c1c2f3943dbdab813041725f4747f5432b05e6e19fc606faa8a9b75c329b37b772c91c47e8db483e76a6b715b59c289ce53dcba68 +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001669, caniuse-lite@npm:^1.0.30001717": + version: 1.0.30001717 + resolution: "caniuse-lite@npm:1.0.30001717" + checksum: 10/e47dfd8707ea305baa177f3d3d531df614f5a9ac6335363fc8f86f0be4caf79f5734f3f68b601fee4edd9d79f1e5ffc0931466bb894bf955ed6b1dd5a1c34b1d languageName: node linkType: hard From f9934b64985a60cb5aa152fc409becbc7028fe0c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 15:02:50 +0000 Subject: [PATCH 084/143] Update dependency @codemirror/view to v6.36.8 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 cec9a1d548..82e0381e66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9525,13 +9525,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.23.0": - version: 6.36.7 - resolution: "@codemirror/view@npm:6.36.7" + version: 6.36.8 + resolution: "@codemirror/view@npm:6.36.8" dependencies: "@codemirror/state": "npm:^6.5.0" style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: 10/0ba49a3025fbb381a8a35022135ea40363a3a3c298d41e3083bb5e263dfa4f11ff9419a46f2b78ef8e853376384ad6c7e48d2a7887e10d366e878d10b53e3b54 + checksum: 10/cb2cbfb8a41ee1d6cfb17c2ea91b9763e692f85d523b55276cc46ab7fda3f6ba0bcc03e2194ad6cf6b413ec34d309ab408300c19b62d5d6d6f9e2071fb99d489 languageName: node linkType: hard From ba2d5ef3d9fb99e249aec8badd758b6f652350c5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 15:03:31 +0000 Subject: [PATCH 085/143] Update dependency @rspack/plugin-react-refresh to v1.4.3 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 cec9a1d548..f732c78009 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16690,8 +16690,8 @@ __metadata: linkType: hard "@rspack/plugin-react-refresh@npm:^1.0.0": - version: 1.4.1 - resolution: "@rspack/plugin-react-refresh@npm:1.4.1" + version: 1.4.3 + resolution: "@rspack/plugin-react-refresh@npm:1.4.3" dependencies: error-stack-parser: "npm:^2.1.4" html-entities: "npm:^2.6.0" @@ -16701,7 +16701,7 @@ __metadata: peerDependenciesMeta: webpack-hot-middleware: optional: true - checksum: 10/0d6ee27a6577947399b7d457b54dbc65dc2c1199cacd257baf9b16ecd4621b288ae4c73a47e753ee8ff62a51b11fe2cac4ac0d168543299593cb59fa35c38119 + checksum: 10/ddbe4268f0c5eb1e6c4384db16cad42628596ff7ca97707b5075be894f60bb87de2483fe2735129dc624380e46b7999735af7c418123a6bb2d01280ca5fea2c1 languageName: node linkType: hard From 5e3880c6ef24e101faf67b04a0548cb88f48f057 Mon Sep 17 00:00:00 2001 From: Kamil Markow Date: Mon, 12 May 2025 11:28:40 -0400 Subject: [PATCH 086/143] Update docs/features/software-templates/writing-custom-actions.md Co-authored-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Signed-off-by: Kamil Markow --- docs/features/software-templates/writing-custom-actions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 009e3c9506..1e2ffb64b6 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -152,7 +152,7 @@ and writing of template entity definitions. ### Adding a TemplateExample A TemplateExample is a way to document different ways that your custom action can be used. Once added it will be visible -in your backstage instance under [/create/actions](https://demo.backstage.io/create/actions) path. You can have multiple +in your Backstage instance under the [/create/actions](https://demo.backstage.io/create/actions) path. You can have multiple examples for one action that can demonstrate different combinations of inputs and how to use them. #### Define TemplateExamples From fe3991af73e0d8cc863b27cef847d38c1030ba6c Mon Sep 17 00:00:00 2001 From: Kamil Markow Date: Mon, 12 May 2025 11:28:52 -0400 Subject: [PATCH 087/143] Update docs/features/software-templates/writing-custom-actions.md Co-authored-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Signed-off-by: Kamil Markow --- docs/features/software-templates/writing-custom-actions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 1e2ffb64b6..26773c15c6 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -159,7 +159,7 @@ examples for one action that can demonstrate different combinations of inputs an Below is a sample TemplateExample that is used for `publish:github`. The source code is available on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts) -and preview on [demo.backstage.io/create/actions](https://demo.backstage.io/create/actions) +and preview on [demo.backstage.io/create/actions](https://demo.backstage.io/create/actions#publish-github) ```ts title="With JSON Schema" import { TemplateExample } from '@backstage/plugin-scaffolder-node'; From bc7751a74ec33530312b62cd9d671c61960e210b Mon Sep 17 00:00:00 2001 From: Benjamin Janssens Date: Mon, 12 May 2025 18:00:59 +0200 Subject: [PATCH 088/143] chore(catalog): rename includeArchived to allowArchived Signed-off-by: Benjamin Janssens --- docs/integrations/github/discovery.md | 2 +- .../catalog-backend-module-github/config.d.ts | 4 ++-- .../src/providers/GithubEntityProvider.ts | 6 ++--- .../GithubEntityProviderConfig.test.ts | 22 +++++++++---------- .../providers/GithubEntityProviderConfig.ts | 8 +++---- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index 1c45d12f83..697efc9cff 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -168,7 +168,7 @@ If you do so, `default` will be used as provider ID. If configured, all repositories _except_ those with one (or more) topics(s) present in the exclusion filter will be ingested. - **`visibility`** _(optional)_: An array of strings used to filter results based on their visibility. Available options are `private`, `internal`, `public`. If configured (non empty), only repositories with visibility present in the filter will be ingested - - **`includeArchived`** _(optional)_: + - **`allowArchived`** _(optional)_: Whether to include archived repositories. Defaults to `false`. - **`host`** _(optional)_: The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md). diff --git a/plugins/catalog-backend-module-github/config.d.ts b/plugins/catalog-backend-module-github/config.d.ts index 976256ac9e..f7c8781c30 100644 --- a/plugins/catalog-backend-module-github/config.d.ts +++ b/plugins/catalog-backend-module-github/config.d.ts @@ -121,7 +121,7 @@ export interface Config { * (Optional) Whether to include archived repositories. * Default: `false`. */ - includeArchived?: boolean; + allowArchived?: boolean; }; /** * (Optional) TaskScheduleDefinition for the refresh. @@ -195,7 +195,7 @@ export interface Config { * (Optional) Whether to include archived repositories. * Default: `false`. */ - includeArchived?: boolean; + allowArchived?: boolean; }; /** * (Optional) TaskScheduleDefinition for the refresh. diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts index 7790be56a0..131237c581 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProvider.ts @@ -260,12 +260,12 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { const topicFilters = this.config.filters.topic; const allowForks = this.config.filters.allowForks; const visibilities = this.config.filters.visibility ?? []; - const includeArchived = this.config.filters.includeArchived; + const allowArchived = this.config.filters.allowArchived; return repositories.filter(r => { const repoTopics: string[] = r.repositoryTopics; return ( - (includeArchived || !r.isArchived) && + (allowArchived || !r.isArchived) && (!repositoryFilter || repositoryFilter.test(r.name)) && satisfiesTopicFilter(repoTopics, topicFilters) && satisfiesForkFilter(allowForks, r.isFork) && @@ -469,7 +469,7 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { * @param event - The repository archived event. */ private async onRepoArchived(event: RepositoryArchivedEvent) { - if (this.config.filters.includeArchived) return; + if (this.config.filters.allowArchived) return; const repository = this.createRepoFromEvent(event); await this.removeEntitiesForRepo(repository); diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts index 9ed1bb2e27..28a3f5e7dd 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts @@ -95,7 +95,7 @@ describe('readProviderConfigs', () => { providerWithArchiveFilter: { organization: 'test-org6', filters: { - includeArchived: true, + allowArchived: true, }, }, providerWithHost: { @@ -132,7 +132,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -151,7 +151,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -170,7 +170,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -189,7 +189,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -208,7 +208,7 @@ describe('readProviderConfigs', () => { exclude: ['backstage-exclude'], }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -227,7 +227,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -246,7 +246,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: ['public', 'internal'], - includeArchived: false, + allowArchived: false, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -265,7 +265,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: true, + allowArchived: true, }, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, validateLocationsExist: false, @@ -284,7 +284,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, validateLocationsExist: false, schedule: DEFAULT_GITHUB_ENTITY_PROVIDER_CONFIG_SCHEDULE, @@ -303,7 +303,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, visibility: undefined, - includeArchived: false, + allowArchived: false, }, schedule: { frequency: { minutes: 30 }, diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts index 9004444f28..e33e7adfdd 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.ts @@ -43,7 +43,7 @@ export type GithubEntityProviderConfig = { topic?: GithubTopicFilters; allowForks: boolean; visibility?: string[]; - includeArchived: boolean; + allowArchived: boolean; }; validateLocationsExist: boolean; schedule?: SchedulerServiceTaskScheduleDefinition; @@ -91,8 +91,8 @@ function readProviderConfig( const topicFilterExclude = config?.getOptionalStringArray( 'filters.topic.exclude', ); - const includeArchived = - config.getOptionalBoolean('filters.includeArchived') ?? false; + const allowArchived = + config.getOptionalBoolean('filters.allowArchived') ?? false; const validateLocationsExist = config?.getOptionalBoolean('validateLocationsExist') ?? false; @@ -135,7 +135,7 @@ function readProviderConfig( exclude: topicFilterExclude, }, visibility: visibilityFilterInclude, - includeArchived, + allowArchived, }, schedule, validateLocationsExist, From 60d118891c3b500a39df4336758f5bc1ace5adad Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 6 May 2025 15:35:34 +0100 Subject: [PATCH 089/143] Add API report change Signed-off-by: Daniel --- plugins/home/report-alpha.api.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/home/report-alpha.api.md b/plugins/home/report-alpha.api.md index 6033cb47f8..5e43163e31 100644 --- a/plugins/home/report-alpha.api.md +++ b/plugins/home/report-alpha.api.md @@ -13,7 +13,9 @@ import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) const _default: FrontendPlugin< - {}, + { + root: RouteRef; + }, {}, { 'page:home': ExtensionDefinition<{ From 43dbd5672e292326fe76254e5a60cdf00fa15d85 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 20:16:21 +0000 Subject: [PATCH 090/143] Update dependency @types/cors to v2.8.18 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 7d0eb5b1f7..56dba773b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20154,11 +20154,11 @@ __metadata: linkType: hard "@types/cors@npm:^2.8.6": - version: 2.8.17 - resolution: "@types/cors@npm:2.8.17" + version: 2.8.18 + resolution: "@types/cors@npm:2.8.18" dependencies: "@types/node": "npm:*" - checksum: 10/469bd85e29a35977099a3745c78e489916011169a664e97c4c3d6538143b0a16e4cc72b05b407dc008df3892ed7bf595f9b7c0f1f4680e169565ee9d64966bde + checksum: 10/6e49b741345e67834cd19d766228509e4b37d6d5c272355bb059502b4787f5adf58776d9114ac5f0f407966e0347ae8d1f995d7ea41e6a24f716d36b3010401b languageName: node linkType: hard From 4f809d2330dccb9d54a19fba53c927ab995a2f0f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 20:17:00 +0000 Subject: [PATCH 091/143] Update dependency eventsource to v3.0.7 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 7d0eb5b1f7..290bf38082 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29724,11 +29724,11 @@ __metadata: linkType: hard "eventsource@npm:^3.0.6": - version: 3.0.6 - resolution: "eventsource@npm:3.0.6" + version: 3.0.7 + resolution: "eventsource@npm:3.0.7" dependencies: eventsource-parser: "npm:^3.0.1" - checksum: 10/ac08c7d1b21e454c7685693fe4ace53fc0b84f3cf752699a556876f2a7f33b7a12972ae33d1c407fb920d6d4aed10de52fdf0dd01902ccdf45cd5da8d55e7f88 + checksum: 10/e034915bc97068d1d38617951afd798e6776d6a3a78e36a7569c235b177c7afc2625c9fe82656f7341ab72c7eeecb3fd507b7f88e9328f2448872ff9c4742bb6 languageName: node linkType: hard From d3e0e78b7377e5046fcf9542d9de6b09cb980372 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 21:41:28 +0000 Subject: [PATCH 092/143] Update dependency humanize-duration to v3.32.2 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 007f0b34a4..ca2b222406 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32614,9 +32614,9 @@ __metadata: linkType: hard "humanize-duration@npm:^3.25.1": - version: 3.32.1 - resolution: "humanize-duration@npm:3.32.1" - checksum: 10/5909107485c33d0c025e5d15a45b2700f91c9efc1e88510867926b3d1ef24d2d0c8bf31f52abef92da53b29e69410c5acb3a4d6d72429bd8b61d82ac25739ce4 + version: 3.32.2 + resolution: "humanize-duration@npm:3.32.2" + checksum: 10/2dfe847085c7586d2cc83613b8643a4cca70966a16522e3786be07f0283087502e5340e98a79867c7b019ea22ae85c3fa9d1ca1be587eb19ccf03710c986d41d languageName: node linkType: hard From 9c63bb9b2c070d898416ab5e483149866e439c56 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 21:42:03 +0000 Subject: [PATCH 093/143] Update dependency semver to v7.7.2 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 007f0b34a4..8649c9b542 100644 --- a/yarn.lock +++ b/yarn.lock @@ -44303,11 +44303,11 @@ __metadata: linkType: hard "semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2": - version: 7.7.1 - resolution: "semver@npm:7.7.1" + version: 7.7.2 + resolution: "semver@npm:7.7.2" bin: semver: bin/semver.js - checksum: 10/4cfa1eb91ef3751e20fc52e47a935a0118d56d6f15a837ab814da0c150778ba2ca4f1a4d9068b33070ea4273629e615066664c2cfcd7c272caf7a8a0f6518b2c + checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda languageName: node linkType: hard From ea6beb11e44180a710921c792cdb5db05449f266 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 22:27:39 +0000 Subject: [PATCH 094/143] Update dependency supertest to v7.1.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 68df0f9610..d595d4a926 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30881,7 +30881,7 @@ __metadata: languageName: node linkType: hard -"formidable@npm:^3.5.1": +"formidable@npm:^3.5.4": version: 3.5.4 resolution: "formidable@npm:3.5.4" dependencies: @@ -45924,30 +45924,30 @@ __metadata: languageName: node linkType: hard -"superagent@npm:^9.0.1": - version: 9.0.2 - resolution: "superagent@npm:9.0.2" +"superagent@npm:^10.2.1": + version: 10.2.1 + resolution: "superagent@npm:10.2.1" dependencies: component-emitter: "npm:^1.3.0" cookiejar: "npm:^2.1.4" debug: "npm:^4.3.4" fast-safe-stringify: "npm:^2.1.1" form-data: "npm:^4.0.0" - formidable: "npm:^3.5.1" + formidable: "npm:^3.5.4" methods: "npm:^1.1.2" mime: "npm:2.6.0" qs: "npm:^6.11.0" - checksum: 10/d3c0c9051ceec84d5b431eaa410ad81bcd53255cea57af1fc66d683a24c34f3ba4761b411072a9bf489a70e3d5b586a78a0e6f2eac6a561067e7d196ddab0907 + checksum: 10/fb91785361955e45d3be7d69f11b64b072678385acbd50ae38f713d6f4862384f138bd9842aff96f475c139b3afda96ea6b016dd544e9a984cf0bcc9e0c103b7 languageName: node linkType: hard "supertest@npm:^7.0.0": - version: 7.1.0 - resolution: "supertest@npm:7.1.0" + version: 7.1.1 + resolution: "supertest@npm:7.1.1" dependencies: methods: "npm:^1.1.2" - superagent: "npm:^9.0.1" - checksum: 10/20069f739a44821dfa4f7f397b9086ef31a358366331138f97945eedb2e231796e7c55b032125d3bd12f9839f089fbb809893dbc0f98edc57e12333b9f42b726 + superagent: "npm:^10.2.1" + checksum: 10/17e2db5d7aef36599f7fe526972e86ceccf3f52300d5d5ba56770a79a85b55172662d80b88591c6d7468e2018b4b75c418c4ffcd9a16d08645ce8f8ddf5f0c90 languageName: node linkType: hard From 2509abc978758451c13088956cb7c42dccc399d2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 23:15:54 +0000 Subject: [PATCH 095/143] Update dependency @apidevtools/json-schema-ref-parser to v11.9.3 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 d595d4a926..91c2126f7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -204,13 +204,13 @@ __metadata: linkType: hard "@apidevtools/json-schema-ref-parser@npm:^11.0.0, @apidevtools/json-schema-ref-parser@npm:^11.7.0": - version: 11.7.3 - resolution: "@apidevtools/json-schema-ref-parser@npm:11.7.3" + version: 11.9.3 + resolution: "@apidevtools/json-schema-ref-parser@npm:11.9.3" dependencies: "@jsdevtools/ono": "npm:^7.1.3" "@types/json-schema": "npm:^7.0.15" js-yaml: "npm:^4.1.0" - checksum: 10/ab496d84f8deca4e5e3ab4adb28825fb1e90655561cf7b70b6dc7b8cf95e49ea9fa3440c265d1d115a43e673b94a79005af05b5d76f77a8934ed1c2fae6762c9 + checksum: 10/3d3618dbb611d1296b99bdee4ff0dde664dad47632d30e0310c6d10de8081f6378ccb58329ea4e03103eca9347d5143671d03f0527b1c3f0916d95f8c09215e2 languageName: node linkType: hard From 1c0da97f2e955f1dff3eb1bbd41e193bd91c7a2b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 00:04:22 +0000 Subject: [PATCH 096/143] Update dependency @asyncapi/react-component to v2.6.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 91c2126f7c..7ceafcd401 100644 --- a/yarn.lock +++ b/yarn.lock @@ -324,25 +324,25 @@ __metadata: languageName: node linkType: hard -"@asyncapi/protobuf-schema-parser@npm:^3.4.0": - version: 3.4.0 - resolution: "@asyncapi/protobuf-schema-parser@npm:3.4.0" +"@asyncapi/protobuf-schema-parser@npm:^3.5.1": + version: 3.5.1 + resolution: "@asyncapi/protobuf-schema-parser@npm:3.5.1" dependencies: "@asyncapi/parser": "npm:^3.4.0" "@types/protocol-buffers-schema": "npm:^3.4.3" protobufjs: "npm:^7.4.0" - checksum: 10/e04ab346e0145d735a4d4238d7adc74ea469b588be10507363e6e216822b3501b786f2c33d0451ace20ac9e6dace411458b6b8045388bed0300278e7fa2e3822 + checksum: 10/dbef0c14080f0894e2d2ca1f5f233485e3cce3f37bf82e3412be50322bd16366812ab933f35e38c35ee453a29ae20e2d8a811a6921fc5631cb5caf0b59fd839a languageName: node linkType: hard "@asyncapi/react-component@npm:^2.3.3": - version: 2.5.1 - resolution: "@asyncapi/react-component@npm:2.5.1" + version: 2.6.3 + resolution: "@asyncapi/react-component@npm:2.6.3" dependencies: "@asyncapi/avro-schema-parser": "npm:^3.0.24" "@asyncapi/openapi-schema-parser": "npm:^3.0.24" "@asyncapi/parser": "npm:^3.3.0" - "@asyncapi/protobuf-schema-parser": "npm:^3.4.0" + "@asyncapi/protobuf-schema-parser": "npm:^3.5.1" highlight.js: "npm:^10.7.2" isomorphic-dompurify: "npm:^2.14.0" marked: "npm:^4.0.14" @@ -352,7 +352,7 @@ __metadata: peerDependencies: react: ">=18.0.0" react-dom: ">=18.0.0" - checksum: 10/590b9e8e4326a803149bd5c99662cd75acf4e469cb3c829588f2b8a2b2b85bf3d342a81daccf3f974d9fbdb89e30a6bfed2d870826abaf7366b1017389dbd5c5 + checksum: 10/7105385f8f806200638f10b799ff1a5d1838041d20d14c6e64b1e1a411933727b91cd3957c2057bc7946524be01c8ab7bb03946886534b15f4767c277da38445 languageName: node linkType: hard From 704d94ba03ca9d35ad453379bc7edfe5262d1925 Mon Sep 17 00:00:00 2001 From: Vinnie McGuinness Date: Mon, 12 May 2025 11:18:20 +0100 Subject: [PATCH 097/143] Resloving initial feadback comments Signed-off-by: Vinnie McGuinness --- .github/CODEOWNERS | 2 +- docs/integrations/gitea/discovery.md | 5 -- .../catalog-backend-module-gitea/config.d.ts | 58 ++++++++++++++++ .../catalog-backend-module-gitea/package.json | 4 +- .../src/providers/GiteaEntityProvider.test.ts | 66 +------------------ .../src/providers/GiteaEntityProvider.ts | 8 +-- yarn.lock | 1 - 7 files changed, 67 insertions(+), 77 deletions(-) create mode 100644 plugins/catalog-backend-module-gitea/config.d.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f5c6f49617..16d55c29dd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -51,7 +51,7 @@ yarn.lock @backstage/maintainers @backst /plugins/catalog-backend-module-aws @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-bitbucket-cloud @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-backstage-openapi @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers -/plugins/catalog-backend-module-gitea @backstage/maintainers @backstage/reviewers @vinnie-jog-on +/plugins/catalog-backend-module-gitea @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers /plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-puppetdb @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers /plugins/catalog-graph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @backstage/sda-se-reviewers diff --git a/docs/integrations/gitea/discovery.md b/docs/integrations/gitea/discovery.md index c01ea52edf..6cae169b58 100644 --- a/docs/integrations/gitea/discovery.md +++ b/docs/integrations/gitea/discovery.md @@ -2,14 +2,9 @@ id: discovery title: Gitea Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from Gitea repositories --- -:::info -This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). -::: - The Gitea integration has a special entity provider for discovering catalog entities from Gitea repositories. The provider uses the "List Projects" API in Gitea to get a list of repositories and will automatically ingest all `catalog-info.yaml` files diff --git a/plugins/catalog-backend-module-gitea/config.d.ts b/plugins/catalog-backend-module-gitea/config.d.ts new file mode 100644 index 0000000000..bbb1a0ee4f --- /dev/null +++ b/plugins/catalog-backend-module-gitea/config.d.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugin-api'; + +export interface Config { + catalog?: { + /** + * List of provider-specific options and attributes + */ + providers?: { + /** + * GiteaEntityProvider configuration + * + * Maps provider id with configuration. + */ + gitea?: { + [name: string]: { + /** + * (Required) The host of the Gitea integration to use. + */ + host: string; + /** + * (Required) Name of your organization account/workspace. + */ + organization: string; + /** + * (Optional) Branch. + * The branch where the provider will try to find entities. Uses the default to "main". + */ + branch?: string; + /** + * (Optional) Path where the catalog YAML manifest file is expected in the repository. + * Defaults to "catalog-info.yaml". + */ + catalogPath?: string; + /** + * (Optional) TaskScheduleDefinition for the discovery. + */ + schedule?: SchedulerServiceTaskScheduleDefinition; + }; + }; + }; + }; +} diff --git a/plugins/catalog-backend-module-gitea/package.json b/plugins/catalog-backend-module-gitea/package.json index fbba66a039..b35f0b6b77 100644 --- a/plugins/catalog-backend-module-gitea/package.json +++ b/plugins/catalog-backend-module-gitea/package.json @@ -1,8 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitea", - "version": "0.1.0", + "version": "0.0.0", "license": "Apache-2.0", - "private": true, "description": "The gitea backend module for the catalog plugin.", "main": "src/index.ts", "types": "src/index.ts", @@ -41,7 +40,6 @@ "uuid": "^11.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.25.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" }, diff --git a/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts index c17b3bc20e..d6a31899f1 100644 --- a/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts +++ b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.test.ts @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { LoggerService } from '@backstage/backend-plugin-api'; +import { mockServices } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; import { GiteaEntityProvider } from './GiteaEntityProvider'; @@ -28,7 +27,8 @@ jest.mock('./core'); jest.mock('uuid'); describe('GiteaEntityProvider', () => { - const logger = getVoidLogger() as unknown as LoggerService; + const logger = mockServices.logger.mock(); + const mockScheduler = { createScheduledTaskRunner: jest.fn(), triggerTask: jest.fn(), @@ -285,66 +285,6 @@ describe('GiteaEntityProvider', () => { fn: expect.any(Function), }); }); - - it('should run the scheduled refresh function', async () => { - await provider.connect(mockConnection); - - // Extract and call the scheduled function - const runArgument = mockTaskRunner.run.mock.calls[0][0]; - const refreshFn = runArgument.fn; - - // Mock the refresh behavior - (global.fetch as jest.Mock).mockImplementation(async (url: string) => { - if (url.includes('/orgs/test-org/repos')) { - if (url.includes('page=1')) { - return { - ok: true, - json: async () => [ - { - name: 'repo1', - html_url: 'https://gitea.example.com/test-org/repo1', - empty: false, - }, - { - name: 'repo2', - html_url: 'https://gitea.example.com/test-org/repo2', - empty: false, - }, - ], - }; - } - return { - ok: true, - json: async () => [], - }; - } else if (url.includes('/contents/catalog-info.yaml')) { - if (url.includes('repo1')) { - return { ok: true }; - } - } - return { ok: false }; - }); - - const abortController = new AbortController(); - await refreshFn(abortController.signal); - - expect(mockConnection.applyMutation).toHaveBeenCalledWith({ - type: 'full', - entities: [ - { - locationKey: 'gitea-provider:test-provider', - entity: expect.objectContaining({ - metadata: expect.objectContaining({ - annotations: expect.objectContaining({ - 'backstage.io/managed-by-location': - 'url:https://gitea.example.com/test-org/repo1/src/branch/main/catalog-info.yaml', - }), - }), - }), - }, - ], - }); - }); }); describe('refresh', () => { diff --git a/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts index 7097edf2ca..2f9475af26 100644 --- a/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts +++ b/plugins/catalog-backend-module-gitea/src/providers/GiteaEntityProvider.ts @@ -164,7 +164,7 @@ export class GiteaEntityProvider implements EntityProvider { let allRepos: any[] = []; try { - // Step 1: Fetch all repos for an organization + // Fetch all repos for an organization const OrgRepoApiUrl = `${getGiteaApiUrl(this.integration.config)}orgs/${ this.config.organization }/repos`; @@ -201,7 +201,7 @@ export class GiteaEntityProvider implements EntityProvider { ); } - // Step 2: Filter for repos that have catalog-info.yaml at root + // Filter for repos that have catalog-info.yaml at root const { default: pLimit } = await import('p-limit'); const limit = pLimit(5); const validRepos: string[] = []; @@ -234,11 +234,11 @@ export class GiteaEntityProvider implements EntityProvider { }), ), ); - // Step 3: create location specs for each valid repo + // Create location specs for each valid repo const locations = await Promise.all( validRepos.map(repo => limit(() => this.createLocationSpec(repo))), ); - // Step 4: Apply the locations to the catalog + // Apply the locations to the catalog try { const providerName: string = this.getProviderName(); const entities = locations.map(location => ({ diff --git a/yarn.lock b/yarn.lock index 6fa02a3a52..8ed49c2325 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5946,7 +5946,6 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-gitea@workspace:plugins/catalog-backend-module-gitea" dependencies: - "@backstage/backend-common": "npm:^0.25.0" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" From ab53e6fed475e203791f1654e51d43e1cec52c1f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 13 May 2025 12:03:29 +0200 Subject: [PATCH 098/143] changesets: split changeset for new dangerousEntityRefFallback option Signed-off-by: Patrik Oldsberg --- .changeset/tall-suits-share-auth-backend.md | 5 +++ .changeset/tall-suits-share-auth-node.md | 38 +++++++++++++++++++++ .changeset/tall-suits-share.md | 4 +-- 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 .changeset/tall-suits-share-auth-backend.md create mode 100644 .changeset/tall-suits-share-auth-node.md diff --git a/.changeset/tall-suits-share-auth-backend.md b/.changeset/tall-suits-share-auth-backend.md new file mode 100644 index 0000000000..3f5230c4e3 --- /dev/null +++ b/.changeset/tall-suits-share-auth-backend.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Added support for the new `dangerousEntityRefFallback` option for `signInWithCatalogUser` in `AuthResolverContext`. diff --git a/.changeset/tall-suits-share-auth-node.md b/.changeset/tall-suits-share-auth-node.md new file mode 100644 index 0000000000..cccd3537f7 --- /dev/null +++ b/.changeset/tall-suits-share-auth-node.md @@ -0,0 +1,38 @@ +--- +'@backstage/plugin-auth-node': patch +--- + +Added a new `dangerousEntityRefFallback` option to the `signInWithCatalogUser` method in `AuthResolverContext`. The option will cause the provided entity reference to be used as a fallback in case the user is not found in the catalog. It is up to the caller to provide the fallback entity reference. + +Auth providers that include pre-defined sign-in resolvers are encouraged to define a flag named `dangerouslyAllowSignInWithoutUserInCatalog` in their config, which in turn enables use of the `dangerousEntityRefFallback` option. For example: + +```ts +export const usernameMatchingUserEntityName = createSignInResolverFactory({ + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { username } = info.result.fullProfile; + if (!username) { + throw new Error('User profile does not contain a username'); + } + + return ctx.signInWithCatalogUser( + { entityRef: { name: username } }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { entityRef: { name: username } } + : undefined, + }, + ); + }; + }, +}); +``` diff --git a/.changeset/tall-suits-share.md b/.changeset/tall-suits-share.md index b7c5d1ccfe..05b74bc277 100644 --- a/.changeset/tall-suits-share.md +++ b/.changeset/tall-suits-share.md @@ -16,8 +16,6 @@ '@backstage/plugin-auth-backend-module-oauth2-provider': patch '@backstage/plugin-auth-backend-module-oidc-provider': patch '@backstage/plugin-auth-backend-module-okta-provider': patch -'@backstage/plugin-auth-backend': patch -'@backstage/plugin-auth-node': patch --- -introduce dangerouslyAllowSignInWithoutUserInCatalog auth resolver config +Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. From 7c954a44da9ee985e8a9f6cde3168ff691e9996c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 10:05:54 +0000 Subject: [PATCH 099/143] chore(deps): update dependency msw to v2.8.2 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 91c2126f7c..081f568c39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38275,8 +38275,8 @@ __metadata: linkType: hard "msw@npm:^2.0.0, msw@npm:^2.0.8": - version: 2.7.6 - resolution: "msw@npm:2.7.6" + version: 2.8.2 + resolution: "msw@npm:2.8.2" dependencies: "@bundled-es-modules/cookie": "npm:^2.0.1" "@bundled-es-modules/statuses": "npm:^1.0.1" @@ -38303,7 +38303,7 @@ __metadata: optional: true bin: msw: cli/index.js - checksum: 10/23f3907b487102b395e2405ab8ae69c8cc74413485805a1039e1a3ab0b54b56947aa77b5ef5a15befad02a69aaa21a204ecfafd2e81d4fb1fd284cb99dfe2c0b + checksum: 10/7579a8dccb8cc8eb0f13d0bf3a232a3d50a478511d95bc2a4b70778e78ffa28fd0949a855fbceb6ec381bbf76f6331a6d36fcb4a3197ff5bf55d0f14a7f3b35c languageName: node linkType: hard From ec1657982027631eee03a5c398f94a79d0f09fc8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 13 May 2025 13:27:56 +0200 Subject: [PATCH 100/143] CODEOWNERS: joint ownership of /microsite/static Signed-off-by: Patrik Oldsberg --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 41f409a651..687044537f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -25,6 +25,7 @@ yarn.lock @backstage/maintainers @backst /docs/tooling @backstage/tooling-maintainers /microsite @backstage/documentation-maintainers /microsite/data/plugins @backstage/maintainers +/microsite/static @backstage/maintainers @backstage/documentation-maintainers /packages @backstage/framework-maintainers /packages/backend-openapi-utils @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers /packages/canon @backstage/design-system-maintainers From 674def926408995e0b589badb74f848a3ddef174 Mon Sep 17 00:00:00 2001 From: JounQin Date: Thu, 8 May 2025 11:41:35 +0800 Subject: [PATCH 101/143] fix: enable `lazyCompilation` and `refreshOptions` for rspack Signed-off-by: JounQin --- .changeset/clean-otters-allow.md | 5 + .gitignore | 2 +- packages/cli/package.json | 8 +- .../src/modules/build/lib/bundler/config.ts | 22 ++-- yarn.lock | 102 +++++++++--------- 5 files changed, 72 insertions(+), 67 deletions(-) create mode 100644 .changeset/clean-otters-allow.md diff --git a/.changeset/clean-otters-allow.md b/.changeset/clean-otters-allow.md new file mode 100644 index 0000000000..5e0aeb598f --- /dev/null +++ b/.changeset/clean-otters-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +fix: enable `lazyCompilation` and `refreshOptions` for rspack diff --git a/.gitignore b/.gitignore index 25280b40b0..fa4184ecf2 100644 --- a/.gitignore +++ b/.gitignore @@ -183,4 +183,4 @@ knip.json # Typedocs temporary files type-docs docs.json -tsconfig.typedoc.tmp.json \ No newline at end of file +tsconfig.typedoc.tmp.json diff --git a/packages/cli/package.json b/packages/cli/package.json index 616556b5b6..96fcdd6923 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -180,9 +180,9 @@ "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", - "@rspack/core": "^1.0.10", - "@rspack/dev-server": "^1.0.9", - "@rspack/plugin-react-refresh": "^1.0.0", + "@rspack/core": "^1.3.9", + "@rspack/dev-server": "^1.1.1", + "@rspack/plugin-react-refresh": "^1.4.2", "@types/cross-spawn": "^6.0.2", "@types/ejs": "^3.1.3", "@types/express": "^4.17.6", @@ -204,7 +204,7 @@ "nodemon": "^3.0.1" }, "peerDependencies": { - "@rspack/core": "^1.0.10", + "@rspack/core": "^1.2.8", "@rspack/dev-server": "^1.0.9", "@rspack/plugin-react-refresh": "^1.0.0" }, diff --git a/packages/cli/src/modules/build/lib/bundler/config.ts b/packages/cli/src/modules/build/lib/bundler/config.ts index 6b7b6543ae..d7c824e3fa 100644 --- a/packages/cli/src/modules/build/lib/bundler/config.ts +++ b/packages/cli/src/modules/build/lib/bundler/config.ts @@ -142,19 +142,19 @@ export async function createConfig( options.moduleFederation, ); + const refreshOptions = { + overlay: { + sockProtocol: 'ws', + sockHost: host, + sockPort: port, + }, + } as const; + if (rspack) { const RspackReactRefreshPlugin = require('@rspack/plugin-react-refresh'); - plugins.push(new RspackReactRefreshPlugin()); + plugins.push(new RspackReactRefreshPlugin(refreshOptions)); } else { - plugins.push( - new ReactRefreshPlugin({ - overlay: { - sockProtocol: 'ws', - sockHost: host, - sockPort: port, - }, - }), - ); + plugins.push(new ReactRefreshPlugin(refreshOptions)); } } @@ -466,7 +466,7 @@ export async function createConfig( : {}), }, experiments: { - lazyCompilation: !rspack && yn(process.env.EXPERIMENTAL_LAZY_COMPILATION), + lazyCompilation: yn(process.env.EXPERIMENTAL_LAZY_COMPILATION), ...(rspack && { // We're still using `style-loader` for custom `insert` option css: false, diff --git a/yarn.lock b/yarn.lock index 54fe8e9f2f..41a7a8b732 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3944,9 +3944,9 @@ __metadata: "@rollup/plugin-json": "npm:^6.0.0" "@rollup/plugin-node-resolve": "npm:^15.0.0" "@rollup/plugin-yaml": "npm:^4.0.0" - "@rspack/core": "npm:^1.0.10" - "@rspack/dev-server": "npm:^1.0.9" - "@rspack/plugin-react-refresh": "npm:^1.0.0" + "@rspack/core": "npm:^1.3.9" + "@rspack/dev-server": "npm:^1.1.1" + "@rspack/plugin-react-refresh": "npm:^1.4.2" "@spotify/eslint-config-base": "npm:^15.0.0" "@spotify/eslint-config-react": "npm:^15.0.0" "@spotify/eslint-config-typescript": "npm:^15.0.0" @@ -4060,7 +4060,7 @@ __metadata: zod: "npm:^3.22.4" zod-validation-error: "npm:^3.4.0" peerDependencies: - "@rspack/core": ^1.0.10 + "@rspack/core": ^1.2.8 "@rspack/dev-server": ^1.0.9 "@rspack/plugin-react-refresh": ^1.0.0 peerDependenciesMeta: @@ -16581,82 +16581,82 @@ __metadata: languageName: node linkType: hard -"@rspack/binding-darwin-arm64@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-darwin-arm64@npm:1.3.9" +"@rspack/binding-darwin-arm64@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-darwin-arm64@npm:1.3.10" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-darwin-x64@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-darwin-x64@npm:1.3.9" +"@rspack/binding-darwin-x64@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-darwin-x64@npm:1.3.10" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rspack/binding-linux-arm64-gnu@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-linux-arm64-gnu@npm:1.3.9" +"@rspack/binding-linux-arm64-gnu@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-linux-arm64-gnu@npm:1.3.10" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-arm64-musl@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-linux-arm64-musl@npm:1.3.9" +"@rspack/binding-linux-arm64-musl@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-linux-arm64-musl@npm:1.3.10" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rspack/binding-linux-x64-gnu@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-linux-x64-gnu@npm:1.3.9" +"@rspack/binding-linux-x64-gnu@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-linux-x64-gnu@npm:1.3.10" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-x64-musl@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-linux-x64-musl@npm:1.3.9" +"@rspack/binding-linux-x64-musl@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-linux-x64-musl@npm:1.3.10" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rspack/binding-win32-arm64-msvc@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-win32-arm64-msvc@npm:1.3.9" +"@rspack/binding-win32-arm64-msvc@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-win32-arm64-msvc@npm:1.3.10" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-win32-ia32-msvc@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-win32-ia32-msvc@npm:1.3.9" +"@rspack/binding-win32-ia32-msvc@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-win32-ia32-msvc@npm:1.3.10" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rspack/binding-win32-x64-msvc@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding-win32-x64-msvc@npm:1.3.9" +"@rspack/binding-win32-x64-msvc@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding-win32-x64-msvc@npm:1.3.10" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rspack/binding@npm:1.3.9": - version: 1.3.9 - resolution: "@rspack/binding@npm:1.3.9" +"@rspack/binding@npm:1.3.10": + version: 1.3.10 + resolution: "@rspack/binding@npm:1.3.10" dependencies: - "@rspack/binding-darwin-arm64": "npm:1.3.9" - "@rspack/binding-darwin-x64": "npm:1.3.9" - "@rspack/binding-linux-arm64-gnu": "npm:1.3.9" - "@rspack/binding-linux-arm64-musl": "npm:1.3.9" - "@rspack/binding-linux-x64-gnu": "npm:1.3.9" - "@rspack/binding-linux-x64-musl": "npm:1.3.9" - "@rspack/binding-win32-arm64-msvc": "npm:1.3.9" - "@rspack/binding-win32-ia32-msvc": "npm:1.3.9" - "@rspack/binding-win32-x64-msvc": "npm:1.3.9" + "@rspack/binding-darwin-arm64": "npm:1.3.10" + "@rspack/binding-darwin-x64": "npm:1.3.10" + "@rspack/binding-linux-arm64-gnu": "npm:1.3.10" + "@rspack/binding-linux-arm64-musl": "npm:1.3.10" + "@rspack/binding-linux-x64-gnu": "npm:1.3.10" + "@rspack/binding-linux-x64-musl": "npm:1.3.10" + "@rspack/binding-win32-arm64-msvc": "npm:1.3.10" + "@rspack/binding-win32-ia32-msvc": "npm:1.3.10" + "@rspack/binding-win32-x64-msvc": "npm:1.3.10" dependenciesMeta: "@rspack/binding-darwin-arm64": optional: true @@ -16676,16 +16676,16 @@ __metadata: optional: true "@rspack/binding-win32-x64-msvc": optional: true - checksum: 10/bf7679a324dbf67a563e27e9d441b161b0d292b64f24c47b3955a1f12f705b4a60c215735ea09cb2c4e2bfc68cb4dfb24af88daef055a683a7369a5156a2a808 + checksum: 10/10328e405c6708f7d1eea7e8f83d7f4453bcc3e4ca77b99eb29819d9f66c51e85b8cf46daab797bea59fdafc266dab6091deb9b5e2ec3007482da11ab10dc62c languageName: node linkType: hard -"@rspack/core@npm:^1.0.10": - version: 1.3.9 - resolution: "@rspack/core@npm:1.3.9" +"@rspack/core@npm:^1.3.9": + version: 1.3.10 + resolution: "@rspack/core@npm:1.3.10" dependencies: "@module-federation/runtime-tools": "npm:0.13.1" - "@rspack/binding": "npm:1.3.9" + "@rspack/binding": "npm:1.3.10" "@rspack/lite-tapable": "npm:1.0.1" caniuse-lite: "npm:^1.0.30001717" peerDependencies: @@ -16693,11 +16693,11 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/9a4c5cdd51ba66354d27a27b23736c44a5eeac13c70729ae75589cb2bc4bbe600ceb0cf4b11cb0686f8cc96f61b3bf36827b269537c134713278a22d54eb6957 + checksum: 10/5471ced4f461936c723199006182ce9fc54a5840aa7ba46f56f137d46b1839b994a9f6e4539e1376eaaf2956cbbbe5a7846d06ab61246e38711a805f7dd56df4 languageName: node linkType: hard -"@rspack/dev-server@npm:^1.0.9": +"@rspack/dev-server@npm:^1.1.1": version: 1.1.1 resolution: "@rspack/dev-server@npm:1.1.1" dependencies: @@ -16722,7 +16722,7 @@ __metadata: languageName: node linkType: hard -"@rspack/plugin-react-refresh@npm:^1.0.0": +"@rspack/plugin-react-refresh@npm:^1.4.2": version: 1.4.3 resolution: "@rspack/plugin-react-refresh@npm:1.4.3" dependencies: From 1c0cb7be174e9c4b5cd13682c7c769c89f9497b7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 13 May 2025 13:52:18 +0000 Subject: [PATCH 102/143] Version Packages (next) --- .changeset/create-app-1747144256.md | 5 + .changeset/pre.json | 37 +- docs/releases/v1.39.0-next.3-changelog.md | 2119 +++++++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 11 + packages/app-defaults/package.json | 2 +- packages/app-next/CHANGELOG.md | 46 + packages/app-next/package.json | 2 +- packages/app/CHANGELOG.md | 42 + packages/app/package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 9 + packages/backend-app-api/package.json | 2 +- packages/backend-defaults/CHANGELOG.md | 24 + packages/backend-defaults/package.json | 2 +- .../CHANGELOG.md | 25 + .../package.json | 2 +- packages/backend-openapi-utils/CHANGELOG.md | 9 + packages/backend-openapi-utils/package.json | 2 +- packages/backend-plugin-api/CHANGELOG.md | 13 + packages/backend-plugin-api/package.json | 2 +- packages/backend-test-utils/CHANGELOG.md | 14 + packages/backend-test-utils/package.json | 2 +- packages/backend/CHANGELOG.md | 39 + packages/backend/package.json | 2 +- packages/canon/CHANGELOG.md | 6 + packages/canon/package.json | 2 +- packages/cli/CHANGELOG.md | 18 + packages/cli/package.json | 2 +- packages/core-app-api/CHANGELOG.md | 27 + packages/core-app-api/package.json | 2 +- packages/core-compat-api/CHANGELOG.md | 10 + packages/core-compat-api/package.json | 2 +- packages/create-app/CHANGELOG.md | 8 + packages/create-app/package.json | 2 +- packages/dev-utils/CHANGELOG.md | 14 + packages/dev-utils/package.json | 2 +- packages/e2e-test/CHANGELOG.md | 9 + packages/e2e-test/package.json | 2 +- packages/frontend-app-api/CHANGELOG.md | 15 + packages/frontend-app-api/package.json | 2 +- packages/frontend-defaults/CHANGELOG.md | 11 + packages/frontend-defaults/package.json | 2 +- packages/frontend-test-utils/CHANGELOG.md | 13 + packages/frontend-test-utils/package.json | 2 +- packages/integration-react/CHANGELOG.md | 9 + packages/integration-react/package.json | 2 +- packages/integration/CHANGELOG.md | 33 + packages/integration/package.json | 2 +- packages/release-manifests/CHANGELOG.md | 10 + packages/release-manifests/package.json | 2 +- packages/repo-tools/CHANGELOG.md | 13 + packages/repo-tools/package.json | 2 +- packages/scaffolder-internal/CHANGELOG.md | 8 + packages/scaffolder-internal/package.json | 2 +- .../techdocs-cli-embedded-app/CHANGELOG.md | 19 + .../techdocs-cli-embedded-app/package.json | 2 +- packages/techdocs-cli/CHANGELOG.md | 11 + packages/techdocs-cli/package.json | 2 +- packages/test-utils/CHANGELOG.md | 13 + packages/test-utils/package.json | 2 +- packages/yarn-plugin/CHANGELOG.md | 8 + packages/yarn-plugin/package.json | 2 +- plugins/api-docs/CHANGELOG.md | 15 + plugins/api-docs/package.json | 2 +- plugins/app-backend/CHANGELOG.md | 13 + plugins/app-backend/package.json | 2 +- plugins/app-node/CHANGELOG.md | 8 + plugins/app-node/package.json | 2 +- plugins/app/CHANGELOG.md | 13 + plugins/app/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/auth-backend/CHANGELOG.md | 14 + plugins/auth-backend/package.json | 2 +- plugins/auth-node/CHANGELOG.md | 47 + plugins/auth-node/package.json | 2 +- plugins/bitbucket-cloud-common/CHANGELOG.md | 7 + plugins/bitbucket-cloud-common/package.json | 2 +- .../catalog-backend-module-aws/CHANGELOG.md | 16 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 11 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../catalog-backend-module-gcp/CHANGELOG.md | 11 + .../catalog-backend-module-gcp/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../catalog-backend-module-gitea/CHANGELOG.md | 17 + .../catalog-backend-module-gitea/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 13 + .../catalog-backend-module-ldap/package.json | 2 +- .../catalog-backend-module-logs/CHANGELOG.md | 9 + .../catalog-backend-module-logs/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 20 + plugins/catalog-backend/package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 14 + plugins/catalog-graph/package.json | 2 +- plugins/catalog-import/CHANGELOG.md | 18 + plugins/catalog-import/package.json | 2 +- plugins/catalog-node/CHANGELOG.md | 14 + plugins/catalog-node/package.json | 2 +- plugins/catalog-react/CHANGELOG.md | 20 + plugins/catalog-react/package.json | 2 +- .../catalog-unprocessed-entities/CHANGELOG.md | 12 + .../catalog-unprocessed-entities/package.json | 2 +- plugins/catalog/CHANGELOG.md | 26 + plugins/catalog/package.json | 2 +- plugins/devtools-backend/CHANGELOG.md | 16 + plugins/devtools-backend/package.json | 2 +- plugins/devtools/CHANGELOG.md | 13 + plugins/devtools/package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../events-backend-module-azure/CHANGELOG.md | 8 + .../events-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../events-backend-module-gerrit/CHANGELOG.md | 8 + .../events-backend-module-gerrit/package.json | 2 +- .../events-backend-module-github/CHANGELOG.md | 11 + .../events-backend-module-github/package.json | 2 +- .../events-backend-module-gitlab/CHANGELOG.md | 9 + .../events-backend-module-gitlab/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../events-backend-test-utils/CHANGELOG.md | 7 + .../events-backend-test-utils/package.json | 2 +- plugins/events-backend/CHANGELOG.md | 12 + plugins/events-backend/package.json | 2 +- plugins/events-node/CHANGELOG.md | 9 + plugins/events-node/package.json | 2 +- .../example-todo-list-backend/CHANGELOG.md | 8 + .../example-todo-list-backend/package.json | 2 +- plugins/gateway-backend/CHANGELOG.md | 7 + plugins/gateway-backend/package.json | 2 +- plugins/home-react/CHANGELOG.md | 14 + plugins/home-react/package.json | 2 +- plugins/home/CHANGELOG.md | 27 + plugins/home/package.json | 2 +- plugins/kubernetes-backend/CHANGELOG.md | 19 + plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-cluster/CHANGELOG.md | 13 + plugins/kubernetes-cluster/package.json | 2 +- plugins/kubernetes-node/CHANGELOG.md | 10 + plugins/kubernetes-node/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 15 + plugins/kubernetes/package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 19 + .../package.json | 2 +- plugins/notifications-backend/CHANGELOG.md | 18 + plugins/notifications-backend/package.json | 2 +- plugins/notifications-node/CHANGELOG.md | 11 + plugins/notifications-node/package.json | 2 +- plugins/notifications/CHANGELOG.md | 15 + plugins/notifications/package.json | 2 +- plugins/org-react/CHANGELOG.md | 11 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 13 + plugins/org/package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/permission-backend/CHANGELOG.md | 12 + plugins/permission-backend/package.json | 2 +- plugins/permission-node/CHANGELOG.md | 11 + plugins/permission-node/package.json | 2 +- plugins/proxy-backend/CHANGELOG.md | 9 + plugins/proxy-backend/package.json | 2 +- plugins/proxy-node/CHANGELOG.md | 7 + plugins/proxy-node/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 32 + plugins/scaffolder-backend/package.json | 2 +- .../scaffolder-node-test-utils/CHANGELOG.md | 10 + .../scaffolder-node-test-utils/package.json | 2 +- plugins/scaffolder-node/CHANGELOG.md | 14 + plugins/scaffolder-node/package.json | 2 +- plugins/scaffolder-react/CHANGELOG.md | 17 + plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 24 + plugins/scaffolder/package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/search-backend-module-pg/CHANGELOG.md | 10 + plugins/search-backend-module-pg/package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- plugins/search-backend-node/CHANGELOG.md | 11 + plugins/search-backend-node/package.json | 2 +- plugins/search-backend/CHANGELOG.md | 16 + plugins/search-backend/package.json | 2 +- plugins/search-react/CHANGELOG.md | 15 + plugins/search-react/package.json | 2 +- plugins/search/CHANGELOG.md | 17 + plugins/search/package.json | 2 +- plugins/signals-backend/CHANGELOG.md | 12 + plugins/signals-backend/package.json | 2 +- plugins/signals-node/CHANGELOG.md | 11 + plugins/signals-node/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 15 + .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/CHANGELOG.md | 19 + plugins/techdocs-backend/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- plugins/techdocs-node/CHANGELOG.md | 14 + plugins/techdocs-node/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 23 + plugins/techdocs/package.json | 2 +- plugins/user-settings-backend/CHANGELOG.md | 13 + plugins/user-settings-backend/package.json | 2 +- plugins/user-settings/CHANGELOG.md | 18 + plugins/user-settings/package.json | 2 +- 314 files changed, 4427 insertions(+), 158 deletions(-) create mode 100644 .changeset/create-app-1747144256.md create mode 100644 docs/releases/v1.39.0-next.3-changelog.md create mode 100644 plugins/catalog-backend-module-gitea/CHANGELOG.md diff --git a/.changeset/create-app-1747144256.md b/.changeset/create-app-1747144256.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1747144256.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/pre.json b/.changeset/pre.json index 51d53067bd..fe254886cd 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -198,51 +198,65 @@ "@backstage/plugin-user-settings": "0.8.21", "@backstage/plugin-user-settings-backend": "0.3.1", "@backstage/plugin-user-settings-common": "0.0.1", - "@backstage/plugin-events-backend-module-google-pubsub": "0.0.0" + "@backstage/plugin-events-backend-module-google-pubsub": "0.0.0", + "@backstage/plugin-catalog-backend-module-gitea": "0.0.0" }, "changesets": [ "angry-sites-fold", "beige-kiwis-flow", "brave-donuts-sink", "brave-eggs-mate", + "brave-pandas-beam", "brave-toes-switch", "breezy-hotels-deny", "bright-moles-sort", "bumpy-showers-design", "busy-badgers-hang", "calm-toys-occur", + "chatty-months-grow", "chatty-showers-cheat", "chilly-trams-cheer", "chubby-cougars-run", "chubby-needles-vanish", + "clean-otters-allow", "cold-humans-check", "common-goats-raise", "cool-bikes-push", "cool-cities-grab", "cool-colts-float", + "cool-groups-fail", "cool-knives-design", "crazy-chefs-sin", "create-app-1745325336", "create-app-1745936753", + "create-app-1747144256", "cruel-lights-sip", "cyan-pots-appear", "deep-ties-move", "dirty-grapes-vanish", "dry-carpets-hope", + "dry-shirts-film", "dull-doodles-trade", "early-colts-accept", "early-dryers-teach", "eight-toys-feel", + "eleven-beans-relax", "eleven-ghosts-strive", + "every-bottles-grow", "famous-cities-stand", "fancy-frogs-like", "floppy-days-tell", "four-peaches-talk", + "four-snails-argue", "fruity-bags-flow", + "funny-papayas-tell", "good-islands-drive", "green-trainers-float", + "grumpy-phones-kiss", "heavy-baths-rule", "heavy-onions-swim", + "honest-states-repeat", + "honest-teams-shave", "huge-olives-do", "icy-mugs-glow", "khaki-grapes-sink", @@ -252,18 +266,26 @@ "lovely-cats-take", "mean-parents-build", "mighty-carrots-decide", + "moody-women-itch", "neat-glasses-occur", "neat-glasses-occured", "new-hands-scream", "nice-vans-vanish", + "ninety-donkeys-shop", "old-crews-serve", + "old-parents-cut", "open-ghosts-fix", "open-lands-shop", + "orange-banks-deny", + "polite-shoes-allow", "pretty-corners-speak", "pretty-seas-hug", + "proud-women-hammer", "public-socks-agree", + "puny-rice-sneeze", "real-rings-smoke", "real-sheep-chew", + "renovate-29506de", "renovate-4fc113d", "renovate-68baea0", "renovate-e32145b", @@ -280,21 +302,32 @@ "slimy-peas-post", "slow-drinks-enjoy", "small-eggs-develop", + "soft-ravens-build", + "spicy-camels-bet", "spicy-steaks-swim", "spotty-doors-design", "stale-symbols-joke", + "sweet-papayas-slide", + "tall-suits-share-auth-backend", + "tall-suits-share-auth-node", + "tall-suits-share", "tame-areas-behave", "ten-spies-explode", "ten-tables-build", "thick-hotels-rhyme", + "tidy-paths-count", "true-breads-rhyme", + "true-trains-tie", "twenty-kiwis-punch", + "violet-breads-obey", "warm-cases-bathe", "warm-llamas-return", + "wicked-clubs-dream", "wicked-dingos-stand", "wise-cobras-sink", "wise-pillows-smile", "yellow-beans-eat", - "yellow-cows-tickle" + "yellow-cows-tickle", + "young-dancers-shave" ] } diff --git a/docs/releases/v1.39.0-next.3-changelog.md b/docs/releases/v1.39.0-next.3-changelog.md new file mode 100644 index 0000000000..be45f844b8 --- /dev/null +++ b/docs/releases/v1.39.0-next.3-changelog.md @@ -0,0 +1,2119 @@ +# Release v1.39.0-next.3 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.39.0-next.3](https://backstage.github.io/upgrade-helper/?to=1.39.0-next.3) + +## @backstage/core-app-api@1.17.0-next.1 + +### Minor Changes + +- 1e0230e: Support custom `AuthConnector` for `OAuth2`. + + A user can pass their own `AuthConnector` implementation in `OAuth2` constructor. + In which case the session manager will use that instead of the `DefaultAuthConnector` to interact with the + authentication provider. + + A custom `AuthConnector` may call the authentication provider from the front-end, store and retrieve tokens + in the session storage, for example, and otherwise send custom requests to the authentication provider and + handle its responses. + + Note, that if the custom `AuthConnector` transforms scopes returned from the authentication provider, + the transformation must be the same as `OAuth2CreateOptions#scopeTransform` passed to `OAuth2` constructor. + See creating `DefaultAuthConnector` in `OAuth2#create(...)` for an example. + +### Patch Changes + +- cc119b2: Fixed an issue causing `OAuthRequestDialog` to re-render on mount. +- Updated dependencies + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/integration@1.17.0-next.3 + +### Minor Changes + +- d945206: Added support for federated credentials using managed identities in the Azure DevOps integration. Federated credentials are only available for Azure DevOps organizations that have been configured to use Entra ID for authentication. + + ```diff + integrations: + azure: + - host: dev.azure.com + credentials: + + - clientId: ${APP_REGISTRATION_CLIENT_ID} + + managedIdentityClientId: system-assigned + + tenantId: ${AZURE_TENANT_ID} + ``` + + This also adds support for automatically using the system-assigned managed identity of an Azure resource by specifying `system-assigned` as the client ID of the managed identity. + + ```diff + integrations: + azure: + - host: dev.azure.com + credentials: + - - clientId: ${AZURE_CLIENT_ID} + + - clientId: system-assigned + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-catalog@1.30.0-next.3 + +### Minor Changes + +- 970cb48: Show the pagination text for the offset-paginated catalog table, and remove the pagination bar from the top of the `CatalogTable` when pagination is enabled. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.0-next.0 + +### Minor Changes + +- e4dabc6: add new gitea provider module + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/app-defaults@1.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/backend-app-api@1.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/backend-defaults@0.10.0-next.3 + +### Patch Changes + +- 1e06afd: `GithubUrlReader`'s search detects glob-patterns supported by `minimatch`, instead of just detecting + `*` and `?` characters. + + For example, this allows to search for patterns like `{C,c}atalog-info.yaml`. + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-app-api@1.2.3-next.2 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/backend-dynamic-feature-service@0.7.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.33-next.2 + - @backstage/plugin-events-backend@0.5.2-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/backend-openapi-utils@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/backend-plugin-api@1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/backend-test-utils@1.5.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-app-api@1.2.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/canon@0.4.0-next.3 + +### Patch Changes + +- c8f32db: Use correct colour token for TextField clear button icon, prevent layout shift whenever it is hidden or shown and properly size focus area around it. Also stop leading icon shrinking when used together with clear button. + +## @backstage/cli@0.32.1-next.3 + +### Patch Changes + +- 674def9: fix: enable `lazyCompilation` and `refreshOptions` for rspack +- 19a4e7c: Internal refactor to move things closer to home +- Updated dependencies + - @backstage/release-manifests@0.0.13-next.0 + - @backstage/integration@1.17.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.1.10 + - @backstage/types@1.2.1 + +## @backstage/core-compat-api@0.4.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/create-app@0.6.2-next.3 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + +## @backstage/dev-utils@1.1.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + +## @backstage/frontend-app-api@0.11.2-next.3 + +### Patch Changes + +- 1f04491: Added the ability to ignore unknown extension config by passing `{ flags: { allowUnknownExtensionConfig: true } }` to `createSpecializedApp`. +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-defaults@0.2.2-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-defaults@0.2.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-app@0.1.9-next.3 + +## @backstage/frontend-test-utils@0.3.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/test-utils@1.7.8-next.2 + - @backstage/config@1.3.2 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-app@0.1.9-next.3 + +## @backstage/integration-react@1.2.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + +## @backstage/release-manifests@0.0.13-next.0 + +### Patch Changes + +- 163f3da: This expands the configurability of `release-manifests` to pave the road for more configuration options in the `cli`. + + Specifically it allows the specification of mirrored, proxied, or air-gapped hosts when upgrading across releases when + working in restricted or heavily governed development environments (common in large enterprises and government + entities). + +## @backstage/repo-tools@0.13.3-next.3 + +### Patch Changes + +- 659f2ce: Updated dependency `typedoc` to `^0.28.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + +## @techdocs/cli@1.9.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/plugin-techdocs-node@1.13.3-next.3 + +## @backstage/test-utils@1.7.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-api-docs@0.12.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-app@0.1.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-app-backend@0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.33-next.2 + +## @backstage/plugin-app-node@0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config-loader@1.10.1-next.0 + +## @backstage/plugin-auth-backend@0.25.0-next.2 + +### Patch Changes + +- ab53e6f: Added support for the new `dangerousEntityRefFallback` option for `signInWithCatalogUser` in `AuthResolverContext`. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.0-next.2 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.8-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.8-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.0-next.2 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + +## @backstage/plugin-auth-node@0.6.3-next.2 + +### Patch Changes + +- ab53e6f: Added a new `dangerousEntityRefFallback` option to the `signInWithCatalogUser` method in `AuthResolverContext`. The option will cause the provided entity reference to be used as a fallback in case the user is not found in the catalog. It is up to the caller to provide the fallback entity reference. + + Auth providers that include pre-defined sign-in resolvers are encouraged to define a flag named `dangerouslyAllowSignInWithoutUserInCatalog` in their config, which in turn enables use of the `dangerousEntityRefFallback` option. For example: + + ```ts + export const usernameMatchingUserEntityName = createSignInResolverFactory({ + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { username } = info.result.fullProfile; + if (!username) { + throw new Error('User profile does not contain a username'); + } + + return ctx.signInWithCatalogUser( + { entityRef: { name: username } }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { entityRef: { name: username } } + : undefined, + }, + ); + }; + }, + }); + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + +## @backstage/plugin-catalog-backend@2.0.0-next.3 + +### Patch Changes + +- 8e0f15f: "Added a note clarifying that `entity-fetch` audit events are not visible by default in the logs and are only displayed when the log severity level is adjusted." +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/plugin-catalog-backend-module-aws@0.4.11-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.3.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.4.8-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.4.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-github@0.9.0-next.3 + +### Patch Changes + +- ee9f59f: Added filter to include archived repositories +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-github@0.9.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-gitlab@0.6.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-catalog-backend-module-gitlab@0.6.6-next.3 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.11.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-logs@0.1.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.7.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.8-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + +## @backstage/plugin-catalog-graph@0.4.19-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-import@0.13.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/plugin-catalog-common@1.1.4-next.0 + +## @backstage/plugin-catalog-node@1.17.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/plugin-catalog-react@1.18.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/frontend-test-utils@0.3.2-next.3 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.17-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + +## @backstage/plugin-devtools@0.1.27-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-devtools-common@0.1.16-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-devtools-backend@0.5.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-devtools-common@0.1.16-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/plugin-events-backend@0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-azure@0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-gerrit@0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-github@0.4.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-gitlab@0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-backend-test-utils@0.1.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-events-node@0.4.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-gateway-backend@1.0.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-home@0.8.8-next.3 + +### Patch Changes + +- f7ca0fe: Added the Catalog presentation API to the HomePageRecentlyVisited and HomePageTopVisited components + +- eddd96c: Added optional title prop to `customHomePageGrid` + +- 16eb4bf: Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. + Renamed `CatalogReactComponentsNameToClassKey` to `PluginHomeComponentsNameToClassKey` in `overridableComponents.ts` + + Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. + Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. + +- 195323f: Export root page route from the home plugin to enable adding links/nav to it from outside the plugin + +- d710d74: docs: Update default for `preventCollision` prop + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/plugin-home-react@0.1.26-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + +## @backstage/plugin-home-react@0.1.26-next.2 + +### Patch Changes + +- 16eb4bf: Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. + Renamed `CatalogReactComponentsNameToClassKey` to `PluginHomeComponentsNameToClassKey` in `overridableComponents.ts` + + Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. + Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + +## @backstage/plugin-kubernetes@0.12.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-kubernetes-react@0.5.7-next.1 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-kubernetes-backend@0.19.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + - @backstage/plugin-kubernetes-node@0.3.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/plugin-kubernetes-cluster@0.0.25-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-kubernetes-react@0.5.7-next.1 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + +## @backstage/plugin-kubernetes-node@0.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + +## @backstage/plugin-notifications@0.5.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-signals-react@0.0.13-next.0 + +## @backstage/plugin-notifications-backend@0.5.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + - @backstage/plugin-signals-node@0.1.20-next.2 + +## @backstage/plugin-notifications-backend-module-email@0.3.9-next.3 + +### Patch Changes + +- aa3a63a: Enable the ability to configure the endpoint for the SES connection used in the notifications email module. This enables the configuration of alternate endpoints as required, for example for local testing or alternative stacks. +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + +## @backstage/plugin-notifications-backend-module-slack@0.1.1-next.3 + +### Patch Changes + +- f6480c7: Fix dataloader caching, and use the proper catalog service ref + +- e099d0a: Notifications which mention user entity refs are now replaced with Slack compatible mentions. + + Example: `Welcome <@user:default/billy>!` -> `Welcome <@U123456890>!` + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + +## @backstage/plugin-notifications-node@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-signals-node@0.1.20-next.2 + +## @backstage/plugin-org@0.6.39-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + +## @backstage/plugin-org-react@0.1.38-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + +## @backstage/plugin-permission-backend@0.7.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + +## @backstage/plugin-permission-node@0.10.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0-next.0 + +## @backstage/plugin-proxy-backend@0.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/types@1.2.1 + - @backstage/plugin-proxy-node@0.1.4-next.2 + +## @backstage/plugin-proxy-node@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + +## @backstage/plugin-scaffolder@1.31.0-next.3 + +### Patch Changes + +- a274e0a: Migrate custom fields to new schema factory function; + standardize field descriptions to prefer ui:description and present consistently, + utilizing ScaffolderField component where possible. +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + +## @backstage/plugin-scaffolder-backend@1.33.0-next.3 + +### Patch Changes + +- ec42f8e: Generating new tokens on each Scaffolder Task Retry +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.1-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.2 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.10-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.3 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.3 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-node-test-utils@0.2.2-next.3 + +## @backstage/plugin-scaffolder-node@0.8.2-next.3 + +### Patch Changes + +- 16e2e9c: trim leading and trailing slashes from parseRepoUrl query parameters +- ec42f8e: Generating new tokens on each Scaffolder Task Retry +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + +## @backstage/plugin-scaffolder-node-test-utils@0.2.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/backend-test-utils@1.5.0-next.3 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-react@1.16.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + +## @backstage/plugin-search@1.4.26-next.3 + +### Patch Changes + +- fa48594: search plugin support i18n +- Updated dependencies + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend@2.0.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend-module-catalog@0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.2-next.3 + +### Patch Changes + +- 01f772c: Fixed an issue where the `search.elasticsearch.queryOptions` config were not picked up by the `ElasticSearchSearchEngine`. +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend-module-explore@0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend-module-pg@0.5.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-backend-module-techdocs@0.4.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-node@1.13.3-next.3 + +## @backstage/plugin-search-backend-node@1.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-search-react@1.9.0-next.2 + +### Patch Changes + +- 2c76614: Fix memoization of `filterValue` in `SearchFilter.Autocomplete` to prevent unintended resets +- fa48594: search plugin support i18n +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18-next.0 + +## @backstage/plugin-signals-backend@0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-signals-node@0.1.20-next.2 + +## @backstage/plugin-signals-node@0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + +## @backstage/plugin-techdocs@1.12.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-auth-react@0.1.15-next.1 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-common@0.1.0 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.48-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/test-utils@1.7.8-next.2 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + +## @backstage/plugin-techdocs-backend@2.0.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.2-next.3 + - @backstage/plugin-techdocs-common@0.1.0 + - @backstage/plugin-techdocs-node@1.13.3-next.3 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.24-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + +## @backstage/plugin-techdocs-node@1.13.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-common@0.1.0 + +## @backstage/plugin-user-settings@0.8.22-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.13-next.0 + - @backstage/plugin-user-settings-common@0.0.1 + +## @backstage/plugin-user-settings-backend@0.3.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-node@0.1.20-next.2 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.109-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/canon@0.4.0-next.3 + - @backstage/cli@0.32.1-next.3 + - @backstage/plugin-home@0.8.8-next.3 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/plugin-scaffolder@1.31.0-next.3 + - @backstage/plugin-search@1.4.26-next.3 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-api-docs@0.12.7-next.3 + - @backstage/plugin-catalog-graph@0.4.19-next.3 + - @backstage/plugin-catalog-import@0.13.0-next.3 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-notifications@0.5.5-next.3 + - @backstage/plugin-org@0.6.39-next.3 + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/plugin-signals@0.0.19-next.1 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/plugin-user-settings@0.8.22-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-auth-react@0.1.15-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.17-next.3 + - @backstage/plugin-devtools@0.1.27-next.3 + - @backstage/plugin-kubernetes@0.12.7-next.3 + - @backstage/plugin-kubernetes-cluster@0.0.25-next.3 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.24-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + +## example-app-next@0.0.23-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/canon@0.4.0-next.3 + - @backstage/cli@0.32.1-next.3 + - @backstage/plugin-home@0.8.8-next.3 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/plugin-scaffolder@1.31.0-next.3 + - @backstage/plugin-search@1.4.26-next.3 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-api-docs@0.12.7-next.3 + - @backstage/plugin-catalog-graph@0.4.19-next.3 + - @backstage/plugin-catalog-import@0.13.0-next.3 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-notifications@0.5.5-next.3 + - @backstage/plugin-org@0.6.39-next.3 + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/plugin-signals@0.0.19-next.1 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/plugin-user-settings@0.8.22-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/frontend-defaults@0.2.2-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-app@0.1.9-next.3 + - @backstage/plugin-app-visualizer@0.1.19-next.1 + - @backstage/plugin-auth-react@0.1.15-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.17-next.3 + - @backstage/plugin-kubernetes@0.12.7-next.3 + - @backstage/plugin-kubernetes-cluster@0.0.25-next.3 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.24-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + +## example-backend@0.0.38-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/plugin-auth-backend@0.25.0-next.2 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/plugin-auth-backend-module-github-provider@0.3.3-next.2 + - @backstage/plugin-scaffolder-backend@1.33.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-app-backend@0.5.2-next.2 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.8-next.2 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.2-next.2 + - @backstage/plugin-catalog-backend-module-openapi@0.2.10-next.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.0-next.2 + - @backstage/plugin-devtools-backend@0.5.5-next.3 + - @backstage/plugin-events-backend@0.5.2-next.2 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.0-next.2 + - @backstage/plugin-kubernetes-backend@0.19.6-next.3 + - @backstage/plugin-notifications-backend@0.5.6-next.2 + - @backstage/plugin-permission-backend@0.7.0-next.2 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.8-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-proxy-backend@0.6.2-next.2 + - @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.3 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.10-next.3 + - @backstage/plugin-search-backend@2.0.2-next.3 + - @backstage/plugin-search-backend-module-catalog@0.3.4-next.2 + - @backstage/plugin-search-backend-module-explore@0.3.2-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.4.2-next.3 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-signals-backend@0.3.4-next.2 + - @backstage/plugin-techdocs-backend@2.0.2-next.3 + +## e2e-test@0.2.28-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.6.2-next.3 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## @internal/scaffolder@0.0.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + +## techdocs-cli-embedded-app@0.2.108-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/cli@0.32.1-next.3 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/test-utils@1.7.8-next.2 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + +## yarn-plugin-backstage@0.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/release-manifests@0.0.13-next.0 + - @backstage/cli-common@0.1.15 + +## @internal/plugin-todo-list-backend@1.0.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 diff --git a/package.json b/package.json index be4ad52087..5f8bf49205 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.39.0-next.2", + "version": "1.39.0-next.3", "backstage": { "cli": { "new": { diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index d130df1b26..e15b844a8d 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 1.6.2-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index b2cc639068..18a5106385 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/app-defaults", - "version": "1.6.2-next.1", + "version": "1.6.2-next.2", "description": "Provides the default wiring of a Backstage App", "backstage": { "role": "web-library" diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 5cb9e8581e..c7f21def01 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,51 @@ # example-app-next +## 0.0.23-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/canon@0.4.0-next.3 + - @backstage/cli@0.32.1-next.3 + - @backstage/plugin-home@0.8.8-next.3 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/plugin-scaffolder@1.31.0-next.3 + - @backstage/plugin-search@1.4.26-next.3 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-api-docs@0.12.7-next.3 + - @backstage/plugin-catalog-graph@0.4.19-next.3 + - @backstage/plugin-catalog-import@0.13.0-next.3 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-notifications@0.5.5-next.3 + - @backstage/plugin-org@0.6.39-next.3 + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/plugin-signals@0.0.19-next.1 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/plugin-user-settings@0.8.22-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/frontend-defaults@0.2.2-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-app@0.1.9-next.3 + - @backstage/plugin-app-visualizer@0.1.19-next.1 + - @backstage/plugin-auth-react@0.1.15-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.17-next.3 + - @backstage/plugin-kubernetes@0.12.7-next.3 + - @backstage/plugin-kubernetes-cluster@0.0.25-next.3 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.24-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + ## 0.0.23-next.2 ### Patch Changes diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 0f56c433dd..66e6d1ffc5 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.23-next.2", + "version": "0.0.23-next.3", "backstage": { "role": "frontend" }, diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index ff42b42cc8..add9e984a7 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,47 @@ # example-app +## 0.2.109-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/canon@0.4.0-next.3 + - @backstage/cli@0.32.1-next.3 + - @backstage/plugin-home@0.8.8-next.3 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/plugin-scaffolder@1.31.0-next.3 + - @backstage/plugin-search@1.4.26-next.3 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-api-docs@0.12.7-next.3 + - @backstage/plugin-catalog-graph@0.4.19-next.3 + - @backstage/plugin-catalog-import@0.13.0-next.3 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-notifications@0.5.5-next.3 + - @backstage/plugin-org@0.6.39-next.3 + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/plugin-signals@0.0.19-next.1 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/plugin-user-settings@0.8.22-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-auth-react@0.1.15-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.17-next.3 + - @backstage/plugin-devtools@0.1.27-next.3 + - @backstage/plugin-kubernetes@0.12.7-next.3 + - @backstage/plugin-kubernetes-cluster@0.0.25-next.3 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.24-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + ## 0.2.109-next.2 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index b988bf460d..2211307884 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.109-next.2", + "version": "0.2.109-next.3", "backstage": { "role": "frontend" }, diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 2d49092405..efb30c1d7c 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-app-api +## 1.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 1.2.3-next.1 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 01812f903c..296630a1f6 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-app-api", - "version": "1.2.3-next.1", + "version": "1.2.3-next.2", "description": "Core API used by Backstage backend apps", "backstage": { "role": "node-library" diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index b66cdb5ac7..8487aa29f9 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-defaults +## 0.10.0-next.3 + +### Patch Changes + +- 1e06afd: `GithubUrlReader`'s search detects glob-patterns supported by `minimatch`, instead of just detecting + `*` and `?` characters. + + For example, this allows to search for patterns like `{C,c}atalog-info.yaml`. + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-app-api@1.2.3-next.2 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 0.10.0-next.2 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index c865f66067..b3ff563e17 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-defaults", - "version": "0.10.0-next.2", + "version": "0.10.0-next.3", "description": "Backend defaults used by Backstage backend apps", "backstage": { "role": "node-library" diff --git a/packages/backend-dynamic-feature-service/CHANGELOG.md b/packages/backend-dynamic-feature-service/CHANGELOG.md index 8ad2f1e0cf..bf49582494 100644 --- a/packages/backend-dynamic-feature-service/CHANGELOG.md +++ b/packages/backend-dynamic-feature-service/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/backend-dynamic-feature-service +## 0.7.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.33-next.2 + - @backstage/plugin-events-backend@0.5.2-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 0.7.0-next.2 ### Patch Changes diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index 54ea6c8986..aec40551a4 100644 --- a/packages/backend-dynamic-feature-service/package.json +++ b/packages/backend-dynamic-feature-service/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dynamic-feature-service", - "version": "0.7.0-next.2", + "version": "0.7.0-next.3", "description": "Backstage dynamic feature service", "backstage": { "role": "node-library" diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index f24aa49ae8..31b3497a33 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-openapi-utils +## 0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.5.3-next.1 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index f9ea9294bb..6dc909925a 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-openapi-utils", - "version": "0.5.3-next.1", + "version": "0.5.3-next.2", "description": "OpenAPI typescript support.", "backstage": { "role": "node-library" diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 8314ec21b3..d627deabf6 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/backend-plugin-api +## 1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 1.3.1-next.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 906b6ebeb4..2c56ac85bf 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-plugin-api", - "version": "1.3.1-next.1", + "version": "1.3.1-next.2", "description": "Core API used by Backstage backend plugins", "backstage": { "role": "node-library" diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 5cf584fc9f..33e7ce200e 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/backend-test-utils +## 1.5.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-app-api@1.2.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 1.5.0-next.2 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index bcd3ef014c..89fa65b09c 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-test-utils", - "version": "1.5.0-next.2", + "version": "1.5.0-next.3", "description": "Test helpers library for Backstage backends", "backstage": { "role": "node-library" diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index b7d8283cd1..cc5809695e 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,44 @@ # example-backend +## 0.0.38-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/plugin-auth-backend@0.25.0-next.2 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/plugin-auth-backend-module-github-provider@0.3.3-next.2 + - @backstage/plugin-scaffolder-backend@1.33.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-app-backend@0.5.2-next.2 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.8-next.2 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.2-next.2 + - @backstage/plugin-catalog-backend-module-openapi@0.2.10-next.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.0-next.2 + - @backstage/plugin-devtools-backend@0.5.5-next.3 + - @backstage/plugin-events-backend@0.5.2-next.2 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.0-next.2 + - @backstage/plugin-kubernetes-backend@0.19.6-next.3 + - @backstage/plugin-notifications-backend@0.5.6-next.2 + - @backstage/plugin-permission-backend@0.7.0-next.2 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.8-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-proxy-backend@0.6.2-next.2 + - @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.3 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.10-next.3 + - @backstage/plugin-search-backend@2.0.2-next.3 + - @backstage/plugin-search-backend-module-catalog@0.3.4-next.2 + - @backstage/plugin-search-backend-module-explore@0.3.2-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.4.2-next.3 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-signals-backend@0.3.4-next.2 + - @backstage/plugin-techdocs-backend@2.0.2-next.3 + ## 0.0.38-next.2 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 70a47f794c..c6675f7e38 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.0.38-next.2", + "version": "0.0.38-next.3", "backstage": { "role": "backend" }, diff --git a/packages/canon/CHANGELOG.md b/packages/canon/CHANGELOG.md index cca1758025..dea67aa06c 100644 --- a/packages/canon/CHANGELOG.md +++ b/packages/canon/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/canon +## 0.4.0-next.3 + +### Patch Changes + +- c8f32db: Use correct colour token for TextField clear button icon, prevent layout shift whenever it is hidden or shown and properly size focus area around it. Also stop leading icon shrinking when used together with clear button. + ## 0.4.0-next.2 ### Patch Changes diff --git a/packages/canon/package.json b/packages/canon/package.json index c63e307453..78ee3f545b 100644 --- a/packages/canon/package.json +++ b/packages/canon/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/canon", - "version": "0.4.0-next.2", + "version": "0.4.0-next.3", "backstage": { "role": "web-library" }, diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index faddf38926..fb537faff4 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/cli +## 0.32.1-next.3 + +### Patch Changes + +- 674def9: fix: enable `lazyCompilation` and `refreshOptions` for rspack +- 19a4e7c: Internal refactor to move things closer to home +- Updated dependencies + - @backstage/release-manifests@0.0.13-next.0 + - @backstage/integration@1.17.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.1.10 + - @backstage/types@1.2.1 + ## 0.32.1-next.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 96fcdd6923..7afa1637b8 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli", - "version": "0.32.1-next.2", + "version": "0.32.1-next.3", "description": "CLI for developing Backstage plugins and apps", "backstage": { "role": "cli" diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 39a4f5b63b..7e874a1774 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/core-app-api +## 1.17.0-next.1 + +### Minor Changes + +- 1e0230e: Support custom `AuthConnector` for `OAuth2`. + + A user can pass their own `AuthConnector` implementation in `OAuth2` constructor. + In which case the session manager will use that instead of the `DefaultAuthConnector` to interact with the + authentication provider. + + A custom `AuthConnector` may call the authentication provider from the front-end, store and retrieve tokens + in the session storage, for example, and otherwise send custom requests to the authentication provider and + handle its responses. + + Note, that if the custom `AuthConnector` transforms scopes returned from the authentication provider, + the transformation must be the same as `OAuth2CreateOptions#scopeTransform` passed to `OAuth2` constructor. + See creating `DefaultAuthConnector` in `OAuth2#create(...)` for an example. + +### Patch Changes + +- cc119b2: Fixed an issue causing `OAuthRequestDialog` to re-render on mount. +- Updated dependencies + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + ## 1.16.2-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index be8f0592eb..2eb53d7d87 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-app-api", - "version": "1.16.2-next.0", + "version": "1.17.0-next.1", "description": "Core app API used by Backstage apps", "backstage": { "role": "web-library" diff --git a/packages/core-compat-api/CHANGELOG.md b/packages/core-compat-api/CHANGELOG.md index e06676f2e3..430117e719 100644 --- a/packages/core-compat-api/CHANGELOG.md +++ b/packages/core-compat-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-compat-api +## 0.4.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/version-bridge@1.0.11 + ## 0.4.2-next.2 ### Patch Changes diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 6f20d04c5f..77650e4196 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-compat-api", - "version": "0.4.2-next.2", + "version": "0.4.2-next.3", "backstage": { "role": "web-library" }, diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 004799767d..14c327f183 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.6.2-next.3 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + ## 0.6.2-next.2 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 55432ddc6b..20981dc781 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/create-app", - "version": "0.6.2-next.2", + "version": "0.6.2-next.3", "description": "A CLI that helps you create your own Backstage app", "backstage": { "role": "cli" diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 1481726448..d1c08c394e 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/dev-utils +## 1.1.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + ## 1.1.10-next.2 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 8e68e50aed..e71af05c9a 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/dev-utils", - "version": "1.1.10-next.2", + "version": "1.1.10-next.3", "description": "Utilities for developing Backstage plugins.", "backstage": { "role": "web-library" diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 487eb771f1..b760a4d651 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,14 @@ # e2e-test +## 0.2.28-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.6.2-next.3 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + ## 0.2.28-next.2 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 7287232a01..7e37bb477d 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,6 +1,6 @@ { "name": "e2e-test", - "version": "0.2.28-next.2", + "version": "0.2.28-next.3", "description": "E2E test for verifying Backstage packages", "backstage": { "role": "cli" diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index 3e119d7b2f..84fb2dbaa1 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/frontend-app-api +## 0.11.2-next.3 + +### Patch Changes + +- 1f04491: Added the ability to ignore unknown extension config by passing `{ flags: { allowUnknownExtensionConfig: true } }` to `createSpecializedApp`. +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-defaults@0.2.2-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + ## 0.11.2-next.2 ### Patch Changes diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index ea086e29ee..6cfbccf639 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-app-api", - "version": "0.11.2-next.2", + "version": "0.11.2-next.3", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-defaults/CHANGELOG.md b/packages/frontend-defaults/CHANGELOG.md index df3f24050b..e9f64904c5 100644 --- a/packages/frontend-defaults/CHANGELOG.md +++ b/packages/frontend-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/frontend-defaults +## 0.2.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-app@0.1.9-next.3 + ## 0.2.2-next.2 ### Patch Changes diff --git a/packages/frontend-defaults/package.json b/packages/frontend-defaults/package.json index b1b85f3eb1..5525daa3bb 100644 --- a/packages/frontend-defaults/package.json +++ b/packages/frontend-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-defaults", - "version": "0.2.2-next.2", + "version": "0.2.2-next.3", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-test-utils/CHANGELOG.md b/packages/frontend-test-utils/CHANGELOG.md index 3534a15653..fba6e9afb5 100644 --- a/packages/frontend-test-utils/CHANGELOG.md +++ b/packages/frontend-test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/frontend-test-utils +## 0.3.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.11.2-next.3 + - @backstage/test-utils@1.7.8-next.2 + - @backstage/config@1.3.2 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-app@0.1.9-next.3 + ## 0.3.2-next.2 ### Patch Changes diff --git a/packages/frontend-test-utils/package.json b/packages/frontend-test-utils/package.json index b065490006..833030129f 100644 --- a/packages/frontend-test-utils/package.json +++ b/packages/frontend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-test-utils", - "version": "0.3.2-next.2", + "version": "0.3.2-next.3", "backstage": { "role": "web-library" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 58fe14bfb1..fb44067948 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/integration-react +## 1.2.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + ## 1.2.7-next.2 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index bf99892817..529f5011db 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration-react", - "version": "1.2.7-next.2", + "version": "1.2.7-next.3", "description": "Frontend package for managing integrations towards external systems", "backstage": { "role": "web-library" diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 6a67d797c8..832f45e230 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/integration +## 1.17.0-next.3 + +### Minor Changes + +- d945206: Added support for federated credentials using managed identities in the Azure DevOps integration. Federated credentials are only available for Azure DevOps organizations that have been configured to use Entra ID for authentication. + + ```diff + integrations: + azure: + - host: dev.azure.com + credentials: + + - clientId: ${APP_REGISTRATION_CLIENT_ID} + + managedIdentityClientId: system-assigned + + tenantId: ${AZURE_TENANT_ID} + ``` + + This also adds support for automatically using the system-assigned managed identity of an Azure resource by specifying `system-assigned` as the client ID of the managed identity. + + ```diff + integrations: + azure: + - host: dev.azure.com + credentials: + - - clientId: ${AZURE_CLIENT_ID} + + - clientId: system-assigned + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 1.17.0-next.2 ### Minor Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 053a3e793a..142f17c74a 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration", - "version": "1.17.0-next.2", + "version": "1.17.0-next.3", "description": "Helpers for managing integrations towards external systems", "backstage": { "role": "common-library" diff --git a/packages/release-manifests/CHANGELOG.md b/packages/release-manifests/CHANGELOG.md index e88324250f..a7f41cbdf8 100644 --- a/packages/release-manifests/CHANGELOG.md +++ b/packages/release-manifests/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/release-manifests +## 0.0.13-next.0 + +### Patch Changes + +- 163f3da: This expands the configurability of `release-manifests` to pave the road for more configuration options in the `cli`. + + Specifically it allows the specification of mirrored, proxied, or air-gapped hosts when upgrading across releases when + working in restricted or heavily governed development environments (common in large enterprises and government + entities). + ## 0.0.12 ### Patch Changes diff --git a/packages/release-manifests/package.json b/packages/release-manifests/package.json index 0b24a93c6a..ec67298ec2 100644 --- a/packages/release-manifests/package.json +++ b/packages/release-manifests/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/release-manifests", - "version": "0.0.12", + "version": "0.0.13-next.0", "description": "Helper library for receiving release manifests", "backstage": { "role": "common-library" diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 917b364d2e..ed05f6dc0e 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/repo-tools +## 0.13.3-next.3 + +### Patch Changes + +- 659f2ce: Updated dependency `typedoc` to `^0.28.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + ## 0.13.3-next.2 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 77783ff1dc..2aa4e1d80d 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/repo-tools", - "version": "0.13.3-next.2", + "version": "0.13.3-next.3", "description": "CLI for Backstage repo tooling ", "backstage": { "role": "cli" diff --git a/packages/scaffolder-internal/CHANGELOG.md b/packages/scaffolder-internal/CHANGELOG.md index 9ba8836fff..01824c4df6 100644 --- a/packages/scaffolder-internal/CHANGELOG.md +++ b/packages/scaffolder-internal/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/scaffolder +## 0.0.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + ## 0.0.9-next.2 ### Patch Changes diff --git a/packages/scaffolder-internal/package.json b/packages/scaffolder-internal/package.json index 6dda7d0b41..dc727b99d3 100644 --- a/packages/scaffolder-internal/package.json +++ b/packages/scaffolder-internal/package.json @@ -1,6 +1,6 @@ { "name": "@internal/scaffolder", - "version": "0.0.9-next.2", + "version": "0.0.9-next.3", "backstage": { "role": "web-library", "inline": true diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 8afd99d6fb..4e504b8f60 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.108-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/cli@0.32.1-next.3 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/app-defaults@1.6.2-next.2 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/test-utils@1.7.8-next.2 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + ## 0.2.108-next.2 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index cd95f9e37e..0683378df9 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.108-next.2", + "version": "0.2.108-next.3", "backstage": { "role": "frontend" }, diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index e9a719087e..3ce409bbc4 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @techdocs/cli +## 1.9.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/plugin-techdocs-node@1.13.3-next.3 + ## 1.9.3-next.2 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index e44b6fb107..3034be2715 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,6 +1,6 @@ { "name": "@techdocs/cli", - "version": "1.9.3-next.2", + "version": "1.9.3-next.3", "description": "Utility CLI for managing TechDocs sites in Backstage.", "backstage": { "role": "cli" diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 2561b80f57..e8acf8edd1 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.7.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/config@1.3.2 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 1.7.8-next.1 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 0839e44b69..0824422425 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/test-utils", - "version": "1.7.8-next.1", + "version": "1.7.8-next.2", "description": "Utilities to test Backstage plugins and apps.", "backstage": { "role": "web-library" diff --git a/packages/yarn-plugin/CHANGELOG.md b/packages/yarn-plugin/CHANGELOG.md index 41ebade0a3..7a05151bb0 100644 --- a/packages/yarn-plugin/CHANGELOG.md +++ b/packages/yarn-plugin/CHANGELOG.md @@ -1,5 +1,13 @@ # yarn-plugin-backstage +## 0.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/release-manifests@0.0.13-next.0 + - @backstage/cli-common@0.1.15 + ## 0.0.5-next.0 ### Patch Changes diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index 78d34c2788..7de8d140bb 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -1,6 +1,6 @@ { "name": "yarn-plugin-backstage", - "version": "0.0.5-next.0", + "version": "0.0.5-next.1", "description": "Yarn plugin for working with Backstage monorepos", "backstage": { "role": "node-library" diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index ea622deaba..e126781b9c 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-api-docs +## 0.12.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 0.12.7-next.2 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 4854695e23..db9b774cc0 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.12.7-next.2", + "version": "0.12.7-next.3", "description": "A Backstage plugin that helps represent API entities in the frontend", "backstage": { "role": "frontend-plugin", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 966860f088..2230b0ed43 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-app-backend +## 0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.33-next.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 432e17151a..82cbcf2e94 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-backend", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "description": "A Backstage backend plugin that serves the Backstage frontend app", "backstage": { "role": "backend-plugin", diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index 6d1e1a2368..9b85efb09a 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-app-node +## 0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config-loader@1.10.1-next.0 + ## 0.1.33-next.1 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index b92d045fd8..aec12abb23 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-node", - "version": "0.1.33-next.1", + "version": "0.1.33-next.2", "description": "Node.js library for the app plugin", "backstage": { "role": "node-library", diff --git a/plugins/app/CHANGELOG.md b/plugins/app/CHANGELOG.md index 790b735bb1..4c96752e76 100644 --- a/plugins/app/CHANGELOG.md +++ b/plugins/app/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-app +## 0.1.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 0.1.9-next.2 ### Patch Changes diff --git a/plugins/app/package.json b/plugins/app/package.json index fed1f47f4c..c1759b138b 100644 --- a/plugins/app/package.json +++ b/plugins/app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app", - "version": "0.1.9-next.2", + "version": "0.1.9-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "app", diff --git a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md index 2ce29207f7..fa0658554a 100644 --- a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-atlassian-provider +## 0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-atlassian-provider/package.json b/plugins/auth-backend-module-atlassian-provider/package.json index 54c109c737..fe708925bd 100644 --- a/plugins/auth-backend-module-atlassian-provider/package.json +++ b/plugins/auth-backend-module-atlassian-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-atlassian-provider", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "description": "The atlassian-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-auth0-provider/CHANGELOG.md b/plugins/auth-backend-module-auth0-provider/CHANGELOG.md index c14a7d28bd..c9ccfe7d41 100644 --- a/plugins/auth-backend-module-auth0-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-auth0-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-auth0-provider +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-auth0-provider/package.json b/plugins/auth-backend-module-auth0-provider/package.json index 8a8b878ff2..ce5d1b6cb1 100644 --- a/plugins/auth-backend-module-auth0-provider/package.json +++ b/plugins/auth-backend-module-auth0-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-auth0-provider", - "version": "0.2.3-next.1", + "version": "0.2.3-next.2", "description": "The auth0-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md b/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md index 687bd3a63f..cb47375143 100644 --- a/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-auth-backend-module-aws-alb-provider +## 0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.0-next.2 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-aws-alb-provider/package.json b/plugins/auth-backend-module-aws-alb-provider/package.json index c7deb8283d..b418c74bc1 100644 --- a/plugins/auth-backend-module-aws-alb-provider/package.json +++ b/plugins/auth-backend-module-aws-alb-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-aws-alb-provider", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "description": "The aws-alb provider module for the Backstage auth backend.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md b/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md index da8c7e6e81..4c41c3f427 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-auth-backend-module-azure-easyauth-provider +## 0.2.8-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-azure-easyauth-provider/package.json b/plugins/auth-backend-module-azure-easyauth-provider/package.json index e999bf8895..51ded2f229 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/package.json +++ b/plugins/auth-backend-module-azure-easyauth-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-azure-easyauth-provider", - "version": "0.2.8-next.1", + "version": "0.2.8-next.2", "description": "The azure-easyauth-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md b/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md index fe706216c2..b8fb09bac0 100644 --- a/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-bitbucket-provider +## 0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-bitbucket-provider/package.json b/plugins/auth-backend-module-bitbucket-provider/package.json index d73deac57c..2a4630e623 100644 --- a/plugins/auth-backend-module-bitbucket-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-bitbucket-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "The bitbucket-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md b/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md index e4fc051072..486e011126 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-bitbucket-server-provider +## 0.2.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-bitbucket-server-provider/package.json b/plugins/auth-backend-module-bitbucket-server-provider/package.json index 6653b6c499..c61880fbe9 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-server-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-bitbucket-server-provider", - "version": "0.2.3-next.1", + "version": "0.2.3-next.2", "description": "The bitbucket-server-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md b/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md index 1495904a13..168292d2f8 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-auth-backend-module-cloudflare-access-provider +## 0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-cloudflare-access-provider/package.json b/plugins/auth-backend-module-cloudflare-access-provider/package.json index 3cdda0a379..cd4b800bfc 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/package.json +++ b/plugins/auth-backend-module-cloudflare-access-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-cloudflare-access-provider", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "description": "The cloudflare-access-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index 6af6a5844b..a280efab1a 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 9c0db22b19..6366642ec8 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "description": "A GCP IAP auth provider module for the Backstage auth backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index dc2635956e..93a0865d63 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index 4051fc5a2c..bf6529a971 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-github-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "The github-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md index 6ecb16c14a..4001ca4ac0 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index 574a4f05e1..677bac514e 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "The gitlab-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index 6271e93dec..08ba55f539 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index 8faab0b322..69f95614f6 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "A Google auth provider module for the Backstage auth backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-guest-provider/CHANGELOG.md b/plugins/auth-backend-module-guest-provider/CHANGELOG.md index 3bb742c6ef..dd906358c1 100644 --- a/plugins/auth-backend-module-guest-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-guest-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-guest-provider +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-guest-provider/package.json b/plugins/auth-backend-module-guest-provider/package.json index 80fe709602..1562ea78fb 100644 --- a/plugins/auth-backend-module-guest-provider/package.json +++ b/plugins/auth-backend-module-guest-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-guest-provider", - "version": "0.2.8-next.1", + "version": "0.2.8-next.2", "description": "The guest-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md index 2375a09efd..a84516bb02 100644 --- a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-microsoft-provider +## 0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index f1dee13ac3..2e04eb41e5 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-microsoft-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "The microsoft-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index e8359616eb..34a3ea522b 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index 65b5171d12..8061de65b6 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "description": "The oauth2-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md index a4ed6a4989..f64ab78eaa 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-oauth2-proxy-provider +## 0.2.8-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/package.json b/plugins/auth-backend-module-oauth2-proxy-provider/package.json index 18c247e1a0..b77acc0055 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/package.json +++ b/plugins/auth-backend-module-oauth2-proxy-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-proxy-provider", - "version": "0.2.8-next.1", + "version": "0.2.8-next.2", "description": "The oauth2-proxy-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oidc-provider/CHANGELOG.md b/plugins/auth-backend-module-oidc-provider/CHANGELOG.md index 33520a8bde..f1d17a579d 100644 --- a/plugins/auth-backend-module-oidc-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oidc-provider/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-auth-backend-module-oidc-provider +## 0.4.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.0-next.2 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-oidc-provider/package.json b/plugins/auth-backend-module-oidc-provider/package.json index 721a1ab3dd..33f323c335 100644 --- a/plugins/auth-backend-module-oidc-provider/package.json +++ b/plugins/auth-backend-module-oidc-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-oidc-provider", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "description": "The oidc-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-okta-provider/CHANGELOG.md b/plugins/auth-backend-module-okta-provider/CHANGELOG.md index 3f7838609e..79660f330f 100644 --- a/plugins/auth-backend-module-okta-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-okta-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-okta-provider +## 0.2.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-okta-provider/package.json b/plugins/auth-backend-module-okta-provider/package.json index 9993b32ece..70d8defb25 100644 --- a/plugins/auth-backend-module-okta-provider/package.json +++ b/plugins/auth-backend-module-okta-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-okta-provider", - "version": "0.2.3-next.1", + "version": "0.2.3-next.2", "description": "The okta-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md b/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md index 410f2eda91..c6e5d2944a 100644 --- a/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-onelogin-provider +## 0.3.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-onelogin-provider/package.json b/plugins/auth-backend-module-onelogin-provider/package.json index 7ced50dc61..6867251e54 100644 --- a/plugins/auth-backend-module-onelogin-provider/package.json +++ b/plugins/auth-backend-module-onelogin-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-onelogin-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "The onelogin-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md index 7c1ee827b6..865f494229 100644 --- a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-pinniped-provider +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json index 940443cf7e..8c0569dbb4 100644 --- a/plugins/auth-backend-module-pinniped-provider/package.json +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-pinniped-provider", - "version": "0.3.3-next.1", + "version": "0.3.3-next.2", "description": "The pinniped-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md index fc085d8c31..62f2a9373d 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-vmware-cloud-provider +## 0.5.3-next.2 + +### Patch Changes + +- 5cc1f7f: Introduce `dangerouslyAllowSignInWithoutUserInCatalog` auth resolver config. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + ## 0.5.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-vmware-cloud-provider/package.json b/plugins/auth-backend-module-vmware-cloud-provider/package.json index bf209f69fd..7f3c77a1e4 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/package.json +++ b/plugins/auth-backend-module-vmware-cloud-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-vmware-cloud-provider", - "version": "0.5.3-next.1", + "version": "0.5.3-next.2", "description": "The vmware-cloud-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 8f12cd8305..ebf41fff38 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-auth-backend +## 0.25.0-next.2 + +### Patch Changes + +- ab53e6f: Added support for the new `dangerousEntityRefFallback` option for `signInWithCatalogUser` in `AuthResolverContext`. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.25.0-next.1 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 3fce660aa5..ce99f85b08 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.25.0-next.1", + "version": "0.25.0-next.2", "description": "A Backstage backend plugin that handles authentication", "backstage": { "role": "backend-plugin", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 7fd817c2aa..5e60a40cd3 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-auth-node +## 0.6.3-next.2 + +### Patch Changes + +- ab53e6f: Added a new `dangerousEntityRefFallback` option to the `signInWithCatalogUser` method in `AuthResolverContext`. The option will cause the provided entity reference to be used as a fallback in case the user is not found in the catalog. It is up to the caller to provide the fallback entity reference. + + Auth providers that include pre-defined sign-in resolvers are encouraged to define a flag named `dangerouslyAllowSignInWithoutUserInCatalog` in their config, which in turn enables use of the `dangerousEntityRefFallback` option. For example: + + ```ts + export const usernameMatchingUserEntityName = createSignInResolverFactory({ + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { username } = info.result.fullProfile; + if (!username) { + throw new Error('User profile does not contain a username'); + } + + return ctx.signInWithCatalogUser( + { entityRef: { name: username } }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { entityRef: { name: username } } + : undefined, + }, + ); + }; + }, + }); + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.6.3-next.1 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 744bff38ef..2c9e8c007d 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.6.3-next.1", + "version": "0.6.3-next.2", "backstage": { "role": "node-library", "pluginId": "auth", diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index 5cff146b61..4b6241bb7b 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.3.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + ## 0.3.0-next.2 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 7b336e3455..40006fc8d7 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", - "version": "0.3.0-next.2", + "version": "0.3.0-next.3", "description": "Common functionalities for bitbucket-cloud plugins", "backstage": { "role": "common-library", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 600a4f7e93..d22346d163 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.4.11-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + ## 0.4.11-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 157fe665b0..a3cb716c29 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", - "version": "0.4.11-next.2", + "version": "0.4.11-next.3", "description": "A Backstage catalog backend module that helps integrate towards AWS", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 9ce4ec3f4e..3e9a4c6aad 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.3.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.3.5-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 5fc27e581d..7f1d5453d7 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", - "version": "0.3.5-next.2", + "version": "0.3.5-next.3", "description": "A Backstage catalog backend module that helps integrate towards Azure", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md index 3bffb1d42e..5160254a3a 100644 --- a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-backstage-openapi +## 0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index de8dc971e5..a7f4f1aca2 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-backstage-openapi", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index f562d20651..06202b5624 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.4.8-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.4.8-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 8d73b5fd74..48ff0b17d4 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", - "version": "0.4.8-next.2", + "version": "0.4.8-next.3", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index ecd451bd5a..8b6ff29b28 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.4.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.4.1-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 9dd5e16e55..ca241c615a 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.4.1-next.2", + "version": "0.4.1-next.3", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index 3ccb395b27..215f5c16bc 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.3.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + ## 0.3.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index 8b70f03bf0..7be8d3f195 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", - "version": "0.3.8-next.1", + "version": "0.3.8-next.2", "description": "A Backstage catalog backend module that helps integrate towards GCP", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index e207e24dcf..d74fad602d 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.3.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.3.2-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 9d176a1a9d..a34a769b3c 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.3.2-next.2", + "version": "0.3.2-next.3", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gitea/CHANGELOG.md b/plugins/catalog-backend-module-gitea/CHANGELOG.md new file mode 100644 index 0000000000..35e32e6169 --- /dev/null +++ b/plugins/catalog-backend-module-gitea/CHANGELOG.md @@ -0,0 +1,17 @@ +# @backstage/plugin-catalog-backend-module-gitea + +## 0.1.0-next.0 + +### Minor Changes + +- e4dabc6: add new gitea provider module + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 diff --git a/plugins/catalog-backend-module-gitea/package.json b/plugins/catalog-backend-module-gitea/package.json index b35f0b6b77..22f4dc5460 100644 --- a/plugins/catalog-backend-module-gitea/package.json +++ b/plugins/catalog-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitea", - "version": "0.0.0", + "version": "0.1.0-next.0", "license": "Apache-2.0", "description": "The gitea backend module for the catalog plugin.", "main": "src/index.ts", diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index 14fb414c48..a3ac67d24d 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.3.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-github@0.9.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.3.10-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index ce47411b0a..ebe2e4582b 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", - "version": "0.3.10-next.2", + "version": "0.3.10-next.3", "description": "The github-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 51e1498de5..0c3b3e2a63 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-github +## 0.9.0-next.3 + +### Patch Changes + +- ee9f59f: Added filter to include archived repositories +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.9.0-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index bb2e436804..a0b29c1c9e 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github", - "version": "0.9.0-next.2", + "version": "0.9.0-next.3", "description": "A Backstage catalog backend module that helps integrate towards GitHub", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md index 7d5701a31d..61983705d7 100644 --- a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-backend-module-gitlab-org +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-catalog-backend-module-gitlab@0.6.6-next.3 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index 44015c6c16..44480b3cc9 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab-org", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The gitlab-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 76e67018cf..b2cc0ee53c 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.6.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.6.6-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index e129b83cd9..108d05023e 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", - "version": "0.6.6-next.2", + "version": "0.6.6-next.3", "description": "A Backstage catalog backend module that helps integrate towards GitLab", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 98efe68781..707a61f0d2 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.7.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + ## 0.7.0-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 60b3873e0b..074966b7a3 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", - "version": "0.7.0-next.2", + "version": "0.7.0-next.3", "description": "An entity provider for streaming large asset sources into the catalog", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 431a672828..db8ec2bec7 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.11.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.11.5-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 4d9888ac6d..79919b8d54 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", - "version": "0.11.5-next.2", + "version": "0.11.5-next.3", "description": "A Backstage catalog backend module that helps integrate towards LDAP", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-logs/CHANGELOG.md b/plugins/catalog-backend-module-logs/CHANGELOG.md index a7e0d37921..d7c498bad0 100644 --- a/plugins/catalog-backend-module-logs/CHANGELOG.md +++ b/plugins/catalog-backend-module-logs/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-logs +## 0.1.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json index a6f748e4ca..857be5ed67 100644 --- a/plugins/catalog-backend-module-logs/package.json +++ b/plugins/catalog-backend-module-logs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-logs", - "version": "0.1.10-next.2", + "version": "0.1.10-next.3", "description": "A module that subscribes to catalog related events and logs them.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index f4ea154223..9d6ca9759d 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.7.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.7.0-next.1 ### Minor Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index ae116ca435..606bf9fd51 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", - "version": "0.7.0-next.1", + "version": "0.7.0-next.2", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index c6b53d288d..c0acf65480 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.2.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.2.10-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 5f0c106b0d..13c4e7200a 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", - "version": "0.2.10-next.2", + "version": "0.2.10-next.3", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index 324a091dc4..f650e83545 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + ## 0.2.10-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index fc830eb66e..c354a7c791 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", - "version": "0.2.10-next.1", + "version": "0.2.10-next.2", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index af44065886..4d8d4817d2 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index dc32af8cef..06c35eba9f 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", - "version": "0.2.8-next.1", + "version": "0.2.8-next.2", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index a2341a7e40..74e023e6a1 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.8-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + ## 0.6.0-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index 98e2ba8f08..c7291b57df 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", - "version": "0.6.0-next.1", + "version": "0.6.0-next.2", "description": "Backstage Catalog module to view unprocessed entities", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 1f9802a3e8..f1023af433 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend +## 2.0.0-next.3 + +### Patch Changes + +- 8e0f15f: "Added a note clarifying that `entity-fetch` audit events are not visible by default in the logs and are only displayed when the log severity level is adjusted." +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 2.0.0-next.2 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 3b548a9f67..ad2aa6b6fd 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "2.0.0-next.2", + "version": "2.0.0-next.3", "description": "The Backstage backend plugin that provides the Backstage catalog", "backstage": { "role": "backend-plugin", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 7f669774f8..6edba7a4fd 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-graph +## 0.4.19-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + ## 0.4.19-next.2 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index d674ca6f95..8319e40ec9 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.4.19-next.2", + "version": "0.4.19-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "catalog-graph", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 3722f55f86..42bdd25b75 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-import +## 0.13.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/plugin-catalog-common@1.1.4-next.0 + ## 0.13.0-next.2 ### Minor Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index cb046ecfb4..a9f5c79f05 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.13.0-next.2", + "version": "0.13.0-next.3", "description": "A Backstage plugin the helps you import entities into your catalog", "backstage": { "role": "frontend-plugin", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index ebffdcd296..c70deebfc0 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-node +## 1.17.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 1.17.0-next.1 ### Minor Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index a222e0093d..70ec27bfc1 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-node", - "version": "1.17.0-next.1", + "version": "1.17.0-next.2", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", "backstage": { "role": "node-library", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 7ca221a40d..b598d13f5f 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-react +## 1.18.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/frontend-test-utils@0.3.2-next.3 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 1.18.0-next.2 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index bb9d1bde29..4ab0eb0b37 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-react", - "version": "1.18.0-next.2", + "version": "1.18.0-next.3", "description": "A frontend library that helps other Backstage plugins interact with the catalog", "backstage": { "role": "web-library", diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index e7b747928f..6f974e361b 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.2.17-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + ## 0.2.17-next.2 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index c6663150c0..8b810df81a 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.2.17-next.2", + "version": "0.2.17-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "catalog-unprocessed-entities", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index b410114940..57e4467030 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-catalog +## 1.30.0-next.3 + +### Minor Changes + +- 970cb48: Show the pagination text for the offset-paginated catalog table, and remove the pagination bar from the top of the `CatalogTable` when pagination is enabled. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 1.29.1-next.2 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 8eda14596b..816f3fffd2 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "1.29.1-next.2", + "version": "1.30.0-next.3", "description": "The Backstage plugin for browsing the Backstage catalog", "backstage": { "role": "frontend-plugin", diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index b51d75a457..f4365f0fbc 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-devtools-backend +## 0.5.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-devtools-common@0.1.16-next.0 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 0.5.5-next.2 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index f3831118b7..61e23e8cfe 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.5.5-next.2", + "version": "0.5.5-next.3", "backstage": { "role": "backend-plugin", "pluginId": "devtools", diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md index 267df2e952..987bdf393d 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-devtools +## 0.1.27-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-devtools-common@0.1.16-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 0.1.27-next.2 ### Patch Changes diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 2a1c4890a1..c279bd5d03 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.27-next.2", + "version": "0.1.27-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "devtools", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 7af253f205..090e9be560 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.4.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.4.11-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index c006f80ba5..17d7017de1 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.4.11-next.1", + "version": "0.4.11-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 0beac8787c..a715c9d945 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-azure +## 0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.2.20-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 79af151214..5aaba0499b 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.2.20-next.1", + "version": "0.2.20-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 8681c0540c..ea36c98810 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.2.20-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 62d39f6f0e..5c340dad46 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.2.20-next.1", + "version": "0.2.20-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-bitbucket-server/CHANGELOG.md b/plugins/events-backend-module-bitbucket-server/CHANGELOG.md index dea752d4d7..6bdc04dd96 100644 --- a/plugins/events-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-bitbucket-server +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-server/package.json b/plugins/events-backend-module-bitbucket-server/package.json index bda209ef5a..e2c0c62c58 100644 --- a/plugins/events-backend-module-bitbucket-server/package.json +++ b/plugins/events-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-server", - "version": "0.1.1-next.1", + "version": "0.1.1-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index d19438a8c5..1e04e58cdb 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.2.20-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 102e118552..bed07d1546 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.2.20-next.1", + "version": "0.2.20-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index db61a7eba0..94d7d10009 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-events-backend-module-github +## 0.4.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.4.0-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 8b38788c91..d11562a47d 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.4.0-next.2", + "version": "0.4.0-next.3", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index 2f509717be..6f0b139cb3 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.3.1-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 6af20dccdc..28fd7ace5b 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.3.1-next.1", + "version": "0.3.1-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-google-pubsub/CHANGELOG.md b/plugins/events-backend-module-google-pubsub/CHANGELOG.md index c24077f931..5af310dd6e 100644 --- a/plugins/events-backend-module-google-pubsub/CHANGELOG.md +++ b/plugins/events-backend-module-google-pubsub/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-events-backend-module-google-pubsub +## 0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.1.0-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-google-pubsub/package.json b/plugins/events-backend-module-google-pubsub/package.json index 6d8418eb59..946263032a 100644 --- a/plugins/events-backend-module-google-pubsub/package.json +++ b/plugins/events-backend-module-google-pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-google-pubsub", - "version": "0.1.0-next.1", + "version": "0.1.0-next.2", "description": "The google-pubsub backend module for the events plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index 2827335a14..bce3d51721 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.1.44-next.1 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 8edb3f30f5..9c728b6875 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-test-utils", - "version": "0.1.44-next.1", + "version": "0.1.44-next.2", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", "backstage": { "role": "node-library", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index b41cb3e07f..62a72ec740 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-events-backend +## 0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index f41794fc68..472e0cf49f 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "backstage": { "role": "backend-plugin", "pluginId": "events", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index e7d8de11e2..5864a91deb 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-node +## 0.4.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.4.11-next.1 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 4753149051..1b117621f0 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-node", - "version": "0.4.11-next.1", + "version": "0.4.11-next.2", "description": "The plugin-events-node module for @backstage/plugin-events-backend", "backstage": { "role": "node-library", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index e55e25e9c0..d1f59ca675 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-todo-list-backend +## 1.0.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + ## 1.0.39-next.1 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 1317b7dfd2..d522874de1 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.39-next.1", + "version": "1.0.39-next.2", "backstage": { "role": "backend-plugin", "pluginId": "todo-list", diff --git a/plugins/gateway-backend/CHANGELOG.md b/plugins/gateway-backend/CHANGELOG.md index 5af5109613..47723dfc69 100644 --- a/plugins/gateway-backend/CHANGELOG.md +++ b/plugins/gateway-backend/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-gateway-backend +## 1.0.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 1.0.1-next.1 ### Patch Changes diff --git a/plugins/gateway-backend/package.json b/plugins/gateway-backend/package.json index bb898cedd5..bb49127c62 100644 --- a/plugins/gateway-backend/package.json +++ b/plugins/gateway-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gateway-backend", - "version": "1.0.1-next.1", + "version": "1.0.1-next.2", "backstage": { "role": "backend-plugin", "pluginId": "gateway", diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md index 06a3cdff85..1ebfec3ff3 100644 --- a/plugins/home-react/CHANGELOG.md +++ b/plugins/home-react/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-home-react +## 0.1.26-next.2 + +### Patch Changes + +- 16eb4bf: Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. + Renamed `CatalogReactComponentsNameToClassKey` to `PluginHomeComponentsNameToClassKey` in `overridableComponents.ts` + + Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. + Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + ## 0.1.26-next.1 ### Patch Changes diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 43f4e79aed..4cba4959f9 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-home-react", - "version": "0.1.26-next.1", + "version": "0.1.26-next.2", "description": "A Backstage plugin that contains react components helps you build a home page", "backstage": { "role": "web-library", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 73eb07ffd7..1a1eba2dae 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-home +## 0.8.8-next.3 + +### Patch Changes + +- f7ca0fe: Added the Catalog presentation API to the HomePageRecentlyVisited and HomePageTopVisited components +- eddd96c: Added optional title prop to `customHomePageGrid` +- 16eb4bf: Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. + Renamed `CatalogReactComponentsNameToClassKey` to `PluginHomeComponentsNameToClassKey` in `overridableComponents.ts` + + Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. + Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. + +- 195323f: Export root page route from the home plugin to enable adding links/nav to it from outside the plugin +- d710d74: docs: Update default for `preventCollision` prop +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/plugin-home-react@0.1.26-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + ## 0.8.8-next.2 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index c832e8f888..30cd16529a 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-home", - "version": "0.8.8-next.2", + "version": "0.8.8-next.3", "description": "A Backstage plugin that helps you build a home page", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 4147c855f8..c162bcb8cc 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-kubernetes-backend +## 0.19.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + - @backstage/plugin-kubernetes-node@0.3.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 0.19.6-next.2 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 95854d8e88..9f7dc6fd31 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.19.6-next.2", + "version": "0.19.6-next.3", "description": "A Backstage backend plugin that integrates towards Kubernetes", "backstage": { "role": "backend-plugin", diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index aeaf6868ed..4343e9f5a2 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.25-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-kubernetes-react@0.5.7-next.1 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 0.0.25-next.2 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index c7d0013ad2..02e6253c2e 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-cluster", - "version": "0.0.25-next.2", + "version": "0.0.25-next.3", "description": "A Backstage plugin that shows details of Kubernetes clusters", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes-node/CHANGELOG.md b/plugins/kubernetes-node/CHANGELOG.md index 43e94e275a..6cbd464a9f 100644 --- a/plugins/kubernetes-node/CHANGELOG.md +++ b/plugins/kubernetes-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kubernetes-node +## 0.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + ## 0.3.0-next.1 ### Minor Changes diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index ef81490e0a..d4842f9030 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-node", - "version": "0.3.0-next.1", + "version": "0.3.0-next.2", "description": "Node.js library for the kubernetes plugin", "backstage": { "role": "node-library", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index b2c602a222..685e751982 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes +## 0.12.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-kubernetes-react@0.5.7-next.1 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-kubernetes-common@0.9.5-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + ## 0.12.7-next.2 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 60c232bc51..6dc09d3c6a 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.12.7-next.2", + "version": "0.12.7-next.3", "description": "A Backstage plugin that integrates towards Kubernetes", "backstage": { "role": "frontend-plugin", diff --git a/plugins/notifications-backend-module-email/CHANGELOG.md b/plugins/notifications-backend-module-email/CHANGELOG.md index f0baa3195d..8b39ef8055 100644 --- a/plugins/notifications-backend-module-email/CHANGELOG.md +++ b/plugins/notifications-backend-module-email/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-notifications-backend-module-email +## 0.3.9-next.3 + +### Patch Changes + +- aa3a63a: Enable the ability to configure the endpoint for the SES connection used in the notifications email module. This enables the configuration of alternate endpoints as required, for example for local testing or alternative stacks. +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index 566a446aa3..94e953d480 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-email", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "description": "The email backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/notifications-backend-module-slack/CHANGELOG.md b/plugins/notifications-backend-module-slack/CHANGELOG.md index 2cdd8848a4..6b8aede3b6 100644 --- a/plugins/notifications-backend-module-slack/CHANGELOG.md +++ b/plugins/notifications-backend-module-slack/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-notifications-backend-module-slack +## 0.1.1-next.3 + +### Patch Changes + +- f6480c7: Fix dataloader caching, and use the proper catalog service ref +- e099d0a: Notifications which mention user entity refs are now replaced with Slack compatible mentions. + + Example: `Welcome <@user:default/billy>!` -> `Welcome <@U123456890>!` + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + ## 0.1.1-next.2 ### Patch Changes diff --git a/plugins/notifications-backend-module-slack/package.json b/plugins/notifications-backend-module-slack/package.json index 33770bdeac..33bfcc55bc 100644 --- a/plugins/notifications-backend-module-slack/package.json +++ b/plugins/notifications-backend-module-slack/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-slack", - "version": "0.1.1-next.2", + "version": "0.1.1-next.3", "description": "The slack backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/notifications-backend/CHANGELOG.md b/plugins/notifications-backend/CHANGELOG.md index 34435c659f..03f8828ea3 100644 --- a/plugins/notifications-backend/CHANGELOG.md +++ b/plugins/notifications-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-notifications-backend +## 0.5.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + - @backstage/plugin-signals-node@0.1.20-next.2 + ## 0.5.6-next.1 ### Patch Changes diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index 6929b362b9..1f1c328abe 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend", - "version": "0.5.6-next.1", + "version": "0.5.6-next.2", "backstage": { "role": "backend-plugin", "pluginId": "notifications", diff --git a/plugins/notifications-node/CHANGELOG.md b/plugins/notifications-node/CHANGELOG.md index 3b0c21e7d7..2191de49ad 100644 --- a/plugins/notifications-node/CHANGELOG.md +++ b/plugins/notifications-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-notifications-node +## 0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-signals-node@0.1.20-next.2 + ## 0.2.15-next.1 ### Patch Changes diff --git a/plugins/notifications-node/package.json b/plugins/notifications-node/package.json index ca66d819b9..02775f2030 100644 --- a/plugins/notifications-node/package.json +++ b/plugins/notifications-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-node", - "version": "0.2.15-next.1", + "version": "0.2.15-next.2", "description": "Node.js library for the notifications plugin", "backstage": { "role": "node-library", diff --git a/plugins/notifications/CHANGELOG.md b/plugins/notifications/CHANGELOG.md index f171b8a148..9527fe373f 100644 --- a/plugins/notifications/CHANGELOG.md +++ b/plugins/notifications/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-notifications +## 0.5.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-signals-react@0.0.13-next.0 + ## 0.5.5-next.2 ### Patch Changes diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index 0a9d383056..9b5df4bfe2 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications", - "version": "0.5.5-next.2", + "version": "0.5.5-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "notifications", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 766eb1b7ca..8ad4f304ba 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-org-react +## 0.1.38-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + ## 0.1.38-next.2 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 8659c22098..99d7f2b1b5 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.38-next.2", + "version": "0.1.38-next.3", "backstage": { "role": "web-library", "pluginId": "org", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 5dd3fe3463..e77c76c618 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-org +## 0.6.39-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + ## 0.6.39-next.2 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 5337c5ec0f..78e0dad480 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.6.39-next.2", + "version": "0.6.39-next.3", "description": "A Backstage plugin that helps you create entity pages for your organization", "backstage": { "role": "frontend-plugin", diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index 71dbc1bfe5..fd25849e16 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index fb56a68093..63c1d3e98d 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend-module-allow-all-policy", - "version": "0.2.8-next.1", + "version": "0.2.8-next.2", "description": "Allow all policy backend module for the permission plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 6205e7e819..f6e675c843 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-backend +## 0.7.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + ## 0.7.0-next.1 ### Minor Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 2a2348a263..88ca6ad884 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.7.0-next.1", + "version": "0.7.0-next.2", "backstage": { "role": "backend-plugin", "pluginId": "permission", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 13c3f7907d..0b7c03bac1 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-node +## 0.10.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0-next.0 + ## 0.10.0-next.1 ### Minor Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index f60f50f305..7e388faf29 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-node", - "version": "0.10.0-next.1", + "version": "0.10.0-next.2", "description": "Common permission and authorization utilities for backend plugins", "backstage": { "role": "node-library", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index c7c9c22f77..573f50ff60 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-proxy-backend +## 0.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/types@1.2.1 + - @backstage/plugin-proxy-node@0.1.4-next.2 + ## 0.6.2-next.1 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 60d0464c4a..3ad9442d97 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-backend", - "version": "0.6.2-next.1", + "version": "0.6.2-next.2", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", "backstage": { "role": "backend-plugin", diff --git a/plugins/proxy-node/CHANGELOG.md b/plugins/proxy-node/CHANGELOG.md index 6d1a68beb7..db7df34df3 100644 --- a/plugins/proxy-node/CHANGELOG.md +++ b/plugins/proxy-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-proxy-node +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/proxy-node/package.json b/plugins/proxy-node/package.json index 20db83410b..5318593350 100644 --- a/plugins/proxy-node/package.json +++ b/plugins/proxy-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-node", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "description": "The plugin-proxy-node module for @backstage/plugin-proxy-backend", "backstage": { "role": "node-library", diff --git a/plugins/scaffolder-backend-module-azure/CHANGELOG.md b/plugins/scaffolder-backend-module-azure/CHANGELOG.md index 4575bae2c7..58f802e4fd 100644 --- a/plugins/scaffolder-backend-module-azure/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-azure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-azure +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-azure/package.json b/plugins/scaffolder-backend-module-azure/package.json index 9507c527d7..f16c53d00d 100644 --- a/plugins/scaffolder-backend-module-azure/package.json +++ b/plugins/scaffolder-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-azure", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The azure module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md index cd1207a738..8138ca43aa 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-cloud +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json index 79ea0f1131..d6a5761fa0 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The Bitbucket Cloud module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md index ad54b35865..cc84fff174 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-server +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-server/package.json b/plugins/scaffolder-backend-module-bitbucket-server/package.json index c092f10207..f78ebfec25 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-server", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The Bitbucket Server module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md index c8bfd2fc7b..0e7d33210b 100644 --- a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket +## 0.3.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.3 + ## 0.3.10-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket/package.json b/plugins/scaffolder-backend-module-bitbucket/package.json index 699858702c..27ac5f6bc0 100644 --- a/plugins/scaffolder-backend-module-bitbucket/package.json +++ b/plugins/scaffolder-backend-module-bitbucket/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket", - "version": "0.3.10-next.2", + "version": "0.3.10-next.3", "description": "The bitbucket module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index 06756b19fd..2b161776cb 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.3.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index de6045689f..d28013752e 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index c1a9ce091f..7b6b0c3dc8 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.3.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.3.10-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 404bad2b94..4618c01653 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", - "version": "0.3.10-next.2", + "version": "0.3.10-next.3", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gcp/CHANGELOG.md b/plugins/scaffolder-backend-module-gcp/CHANGELOG.md index 9f7f9b1631..563d5f588c 100644 --- a/plugins/scaffolder-backend-module-gcp/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-gcp +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gcp/package.json b/plugins/scaffolder-backend-module-gcp/package.json index 7c2fc0a624..dde1a8ba87 100644 --- a/plugins/scaffolder-backend-module-gcp/package.json +++ b/plugins/scaffolder-backend-module-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gcp", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The GCP Bucket module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md b/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md index 7c0367d1b0..23ea33f17a 100644 --- a/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-gerrit +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gerrit/package.json b/plugins/scaffolder-backend-module-gerrit/package.json index aa6e7478ef..32678efabf 100644 --- a/plugins/scaffolder-backend-module-gerrit/package.json +++ b/plugins/scaffolder-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gerrit", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The gerrit module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gitea/CHANGELOG.md b/plugins/scaffolder-backend-module-gitea/CHANGELOG.md index c7e65d176e..72d4cbe1d7 100644 --- a/plugins/scaffolder-backend-module-gitea/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitea/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-gitea +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitea/package.json b/plugins/scaffolder-backend-module-gitea/package.json index 1be15b9164..c3b14f0ba1 100644 --- a/plugins/scaffolder-backend-module-gitea/package.json +++ b/plugins/scaffolder-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitea", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "description": "The gitea module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-github/CHANGELOG.md b/plugins/scaffolder-backend-module-github/CHANGELOG.md index 6170587864..67b338beac 100644 --- a/plugins/scaffolder-backend-module-github/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-github/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-backend-module-github +## 0.7.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.7.1-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json index 0217d0b48d..1e6b265412 100644 --- a/plugins/scaffolder-backend-module-github/package.json +++ b/plugins/scaffolder-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-github", - "version": "0.7.1-next.2", + "version": "0.7.1-next.3", "description": "The github module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index aa4a43c22c..dc7c180b59 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.9.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.9.1-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index d2f699b219..54c6d5efec 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.9.1-next.2", + "version": "0.9.1-next.3", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-backend-module-notifications/CHANGELOG.md b/plugins/scaffolder-backend-module-notifications/CHANGELOG.md index 4db8585828..3923382d94 100644 --- a/plugins/scaffolder-backend-module-notifications/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-notifications/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-notifications +## 0.1.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/plugin-notifications-common@0.0.8 + - @backstage/plugin-notifications-node@0.2.15-next.2 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-notifications/package.json b/plugins/scaffolder-backend-module-notifications/package.json index ea6c416a9e..c49531786f 100644 --- a/plugins/scaffolder-backend-module-notifications/package.json +++ b/plugins/scaffolder-backend-module-notifications/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-notifications", - "version": "0.1.10-next.2", + "version": "0.1.10-next.3", "description": "The notifications backend module for the scaffolder plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 9c9117bfb3..d4a8d0f82b 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.5.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + ## 0.5.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index c4f58e24f0..6cd2e344cd 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", - "version": "0.5.9-next.2", + "version": "0.5.9-next.3", "description": "A module for the scaffolder backend that lets you template projects using Rails", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 886803e1f0..829c30ef6a 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index c59a288861..bebe43c2f5 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index a319388ed3..df48b09214 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.4.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-node-test-utils@0.2.2-next.3 + ## 0.4.10-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 577e6735a0..44bdb6d120 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.4.10-next.2", + "version": "0.4.10-next.3", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index bfcea59479..8c42f7a26a 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-scaffolder-backend +## 1.33.0-next.3 + +### Patch Changes + +- ec42f8e: Generating new tokens on each Scaffolder Task Retry +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.1-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.2 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.10-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.9-next.3 + - @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.3 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + ## 1.33.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 8a36adfd7a..30cc5ffbf3 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "1.33.0-next.2", + "version": "1.33.0-next.3", "description": "The Backstage backend plugin that helps you create new things", "backstage": { "role": "backend-plugin", diff --git a/plugins/scaffolder-node-test-utils/CHANGELOG.md b/plugins/scaffolder-node-test-utils/CHANGELOG.md index 02f9c91a97..e867e35a94 100644 --- a/plugins/scaffolder-node-test-utils/CHANGELOG.md +++ b/plugins/scaffolder-node-test-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-node-test-utils +## 0.2.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.2-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/backend-test-utils@1.5.0-next.3 + - @backstage/types@1.2.1 + ## 0.2.2-next.2 ### Patch Changes diff --git a/plugins/scaffolder-node-test-utils/package.json b/plugins/scaffolder-node-test-utils/package.json index 9473450114..87874d23c4 100644 --- a/plugins/scaffolder-node-test-utils/package.json +++ b/plugins/scaffolder-node-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-node-test-utils", - "version": "0.2.2-next.2", + "version": "0.2.2-next.3", "backstage": { "role": "node-library", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 9654b575de..c978c94944 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-node +## 0.8.2-next.3 + +### Patch Changes + +- 16e2e9c: trim leading and trailing slashes from parseRepoUrl query parameters +- ec42f8e: Generating new tokens on each Scaffolder Task Retry +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + ## 0.8.2-next.2 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index ba938c3843..61557aa4a8 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-node", - "version": "0.8.2-next.2", + "version": "0.8.2-next.3", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "node-library", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 97925ee2a1..9cddcfefca 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-scaffolder-react +## 1.16.0-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + ## 1.16.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 514da4fe93..81f9dad6dc 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-react", - "version": "1.16.0-next.2", + "version": "1.16.0-next.3", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", "backstage": { "role": "web-library", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index ba8d5db71b..c315185b92 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-scaffolder +## 1.31.0-next.3 + +### Patch Changes + +- a274e0a: Migrate custom fields to new schema factory function; + standardize field descriptions to prefer ui:description and present consistently, + utilizing ScaffolderField component where possible. +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-scaffolder-react@1.16.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-permission-react@0.4.34-next.1 + - @backstage/plugin-scaffolder-common@1.5.11-next.0 + ## 1.31.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 9c71f584ed..47e092112f 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "1.31.0-next.2", + "version": "1.31.0-next.3", "description": "The Backstage plugin that helps you create new things", "backstage": { "role": "frontend-plugin", diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index 0ba985b2ff..fa2816ea35 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend-module-catalog +## 0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 0.3.4-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index 0ffb660686..d3f2942ee0 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-catalog", - "version": "0.3.4-next.1", + "version": "0.3.4-next.2", "description": "A module for the search backend that exports catalog modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 08897eb4c3..b2d00455d0 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.7.2-next.3 + +### Patch Changes + +- 01f772c: Fixed an issue where the `search.elasticsearch.queryOptions` config were not picked up by the `ElasticSearchSearchEngine`. +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 1.7.2-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index fb9399cf2d..8f4df74367 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", - "version": "1.7.2-next.2", + "version": "1.7.2-next.3", "description": "A module for the search backend that implements search using ElasticSearch", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index b2fa21aa3b..fc0f405a24 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-explore +## 0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index e57ea07e00..92ef1a18e7 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-explore", - "version": "0.3.2-next.1", + "version": "0.3.2-next.2", "description": "A module for the search backend that exports explore modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index def19bf30b..47c2a65de4 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 0.5.44-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 0eb67810d4..0686bac80d 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-pg", - "version": "0.5.44-next.1", + "version": "0.5.44-next.2", "description": "A module for the search backend that implements search using PostgreSQL", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md b/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md index 3aa92b12ec..99ee569733 100644 --- a/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md +++ b/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-stack-overflow-collator +## 0.3.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 0.3.9-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-stack-overflow-collator/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json index 465627c118..b5d0258dcf 100644 --- a/plugins/search-backend-module-stack-overflow-collator/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-stack-overflow-collator", - "version": "0.3.9-next.1", + "version": "0.3.9-next.2", "description": "A module for the search backend that exports stack overflow modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index 4af1906d57..62d6f6a1d8 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.4.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-node@1.13.3-next.3 + ## 0.4.2-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index 8d088fe1b7..22683c1179 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", - "version": "0.4.2-next.2", + "version": "0.4.2-next.3", "description": "A module for the search backend that exports techdocs modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 28e245a5ef..7cd55d993c 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend-node +## 1.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 1.3.11-next.1 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index ab6f99462c..cd16c32b8b 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-node", - "version": "1.3.11-next.1", + "version": "1.3.11-next.2", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", "backstage": { "role": "node-library", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 9f51eb47ea..1a9875b526 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend +## 2.0.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/backend-openapi-utils@0.5.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-permission-node@0.10.0-next.2 + - @backstage/plugin-search-backend-node@1.3.11-next.2 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 2.0.2-next.2 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 57b212d906..a45345bbe5 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend", - "version": "2.0.2-next.2", + "version": "2.0.2-next.3", "description": "The Backstage backend plugin that provides your backstage app with search", "backstage": { "role": "backend-plugin", diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index a6c9421949..1551669adc 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-search-react +## 1.9.0-next.2 + +### Patch Changes + +- 2c76614: Fix memoization of `filterValue` in `SearchFilter.Autocomplete` to prevent unintended resets +- fa48594: search plugin support i18n +- Updated dependencies + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 1.9.0-next.1 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 59bc492e10..3e4e7ba821 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.9.0-next.1", + "version": "1.9.0-next.2", "backstage": { "role": "web-library", "pluginId": "search", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 8a4d42569e..66b7f98985 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-search +## 1.4.26-next.3 + +### Patch Changes + +- fa48594: search plugin support i18n +- Updated dependencies + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18-next.0 + ## 1.4.26-next.2 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 8a872978e2..c9bff12da7 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "1.4.26-next.2", + "version": "1.4.26-next.3", "description": "The Backstage plugin that provides your backstage app with search", "backstage": { "role": "frontend-plugin", diff --git a/plugins/signals-backend/CHANGELOG.md b/plugins/signals-backend/CHANGELOG.md index 93c0bfc099..d53dc508e8 100644 --- a/plugins/signals-backend/CHANGELOG.md +++ b/plugins/signals-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-signals-backend +## 0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + - @backstage/plugin-signals-node@0.1.20-next.2 + ## 0.3.4-next.1 ### Patch Changes diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index 39ca69672f..65d7e3ab4a 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-backend", - "version": "0.3.4-next.1", + "version": "0.3.4-next.2", "backstage": { "role": "backend-plugin", "pluginId": "signals", diff --git a/plugins/signals-node/CHANGELOG.md b/plugins/signals-node/CHANGELOG.md index 23fa9ade45..bebb00934c 100644 --- a/plugins/signals-node/CHANGELOG.md +++ b/plugins/signals-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-signals-node +## 0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.11-next.2 + ## 0.1.20-next.1 ### Patch Changes diff --git a/plugins/signals-node/package.json b/plugins/signals-node/package.json index b3510d3d5a..1b1f235cf7 100644 --- a/plugins/signals-node/package.json +++ b/plugins/signals-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-node", - "version": "0.1.20-next.1", + "version": "0.1.20-next.2", "description": "Node.js library for the signals plugin", "backstage": { "role": "node-library", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index b59f735816..2dc7e1ba49 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.48-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/plugin-catalog@1.30.0-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/test-utils@1.7.8-next.2 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/plugin-techdocs@1.12.6-next.3 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + ## 1.0.48-next.2 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 0b6ee4f297..aaa9864a08 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.48-next.2", + "version": "1.0.48-next.3", "backstage": { "role": "web-library", "pluginId": "techdocs-addons", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 8ba2abcdb2..8d1dd79d28 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-techdocs-backend +## 2.0.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4-next.0 + - @backstage/plugin-catalog-node@1.17.0-next.2 + - @backstage/plugin-permission-common@0.9.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.2-next.3 + - @backstage/plugin-techdocs-common@0.1.0 + - @backstage/plugin-techdocs-node@1.13.3-next.3 + ## 2.0.2-next.2 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 380d37f79a..ab2f3dd17f 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "2.0.2-next.2", + "version": "2.0.2-next.3", "description": "The Backstage backend plugin that renders technical documentation for your components", "backstage": { "role": "backend-plugin", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index df7bb86451..cc6d00815d 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.24-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + ## 1.1.24-next.2 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 8896409a09..14d5280b55 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", - "version": "1.1.24-next.2", + "version": "1.1.24-next.3", "description": "Plugin module for contributed TechDocs Addons", "backstage": { "role": "frontend-plugin-module", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index b7c474a1e9..76b9836cd3 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-techdocs-node +## 1.13.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16-next.0 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-common@0.1.0 + ## 1.13.3-next.2 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 2cabc2b3c2..ff5986a5d4 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-node", - "version": "1.13.3-next.2", + "version": "1.13.3-next.3", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", "backstage": { "role": "node-library", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index bcc2f88efa..747eccd17b 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-techdocs +## 1.12.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.0-next.3 + - @backstage/plugin-search-react@1.9.0-next.2 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-client@1.10.0-next.0 + - @backstage/catalog-model@1.7.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/integration-react@1.2.7-next.3 + - @backstage/theme@0.6.6-next.0 + - @backstage/plugin-auth-react@0.1.15-next.1 + - @backstage/plugin-search-common@1.2.18-next.0 + - @backstage/plugin-techdocs-common@0.1.0 + - @backstage/plugin-techdocs-react@1.2.17-next.1 + ## 1.12.6-next.2 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 8ddeaa597f..a488863a25 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "1.12.6-next.2", + "version": "1.12.6-next.3", "description": "The Backstage plugin that renders technical documentation for your components", "backstage": { "role": "frontend-plugin", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 5c3a22f044..7920484835 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-user-settings-backend +## 0.3.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.0-next.3 + - @backstage/plugin-auth-node@0.6.3-next.2 + - @backstage/backend-plugin-api@1.3.1-next.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-node@0.1.20-next.2 + - @backstage/plugin-user-settings-common@0.0.1 + ## 0.3.2-next.2 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index b216e566a5..70c77f740b 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings-backend", - "version": "0.3.2-next.2", + "version": "0.3.2-next.3", "description": "The Backstage backend plugin to manage user settings", "backstage": { "role": "backend-plugin", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index f5170c340f..1d2d5aa0dc 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-user-settings +## 0.8.22-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.0-next.1 + - @backstage/core-compat-api@0.4.2-next.3 + - @backstage/core-components@0.17.2-next.1 + - @backstage/core-plugin-api@1.10.7-next.0 + - @backstage/plugin-catalog-react@1.18.0-next.3 + - @backstage/catalog-model@1.7.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.2-next.1 + - @backstage/theme@0.6.6-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.13-next.0 + - @backstage/plugin-user-settings-common@0.0.1 + ## 0.8.22-next.2 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 54dfcc0d26..66d768d102 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings", - "version": "0.8.22-next.2", + "version": "0.8.22-next.3", "description": "A Backstage plugin that provides a settings page", "backstage": { "role": "frontend-plugin", From 3cd1409f45485b7da11cb5728e1e625c264ef035 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Tue, 13 May 2025 13:38:23 -0500 Subject: [PATCH 103/143] Removed redirect to fix failing deployment Signed-off-by: Andre Wanlin --- microsite/docusaurus.config.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/microsite/docusaurus.config.ts b/microsite/docusaurus.config.ts index 0213ebc05b..71331710d5 100644 --- a/microsite/docusaurus.config.ts +++ b/microsite/docusaurus.config.ts @@ -269,10 +269,6 @@ const config: Config = { from: '/docs/plugins/url-reader/', to: '/docs/backend-system/core-services/url-reader', }, - { - from: '/docs/features/software-templates/template-extensions/', - to: '/docs/features/software-templates/templating-extensions', - }, ], }), [ From 3f45861646221a9a55d5ead3dfe93b0abbd62138 Mon Sep 17 00:00:00 2001 From: Paul Schultz Date: Tue, 13 May 2025 17:00:20 -0500 Subject: [PATCH 104/143] feat: add a react 17 deprecation warning Signed-off-by: Paul Schultz --- .changeset/fluffy-lands-stand.md | 5 +++++ .../modules/start/commands/package/start/startFrontend.ts | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 .changeset/fluffy-lands-stand.md diff --git a/.changeset/fluffy-lands-stand.md b/.changeset/fluffy-lands-stand.md new file mode 100644 index 0000000000..8f1452d7b3 --- /dev/null +++ b/.changeset/fluffy-lands-stand.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': minor +--- + +Add a warning for React 17 deprecation that triggers when frontend packages and plugins start. diff --git a/packages/cli/src/modules/start/commands/package/start/startFrontend.ts b/packages/cli/src/modules/start/commands/package/start/startFrontend.ts index d4b2f6a1cd..aaadf3ed95 100644 --- a/packages/cli/src/modules/start/commands/package/start/startFrontend.ts +++ b/packages/cli/src/modules/start/commands/package/start/startFrontend.ts @@ -22,6 +22,7 @@ import { } from '../../../../build/lib/bundler'; import { paths } from '../../../../../lib/paths'; import { BackstagePackageJson } from '@backstage/cli-node'; +import { hasReactDomClient } from '../../../../build/lib/bundler/hasReactDomClient'; interface StartAppOptions { verifyVersions?: boolean; @@ -40,6 +41,12 @@ export async function startFrontend(options: StartAppOptions) { resolvePath(options.targetDir ?? paths.targetDir, 'package.json'), )) as BackstagePackageJson; + if (!hasReactDomClient()) { + console.warn( + 'React 17 is now deprecated! Please follow the Backstage migration guide to update to React 18: https://backstage.io/docs/tutorials/react18-migration/', + ); + } + const waitForExit = await serveBundle({ entry: options.entry, targetDir: options.targetDir, From 2882b28b8144ad183243378581038662e4c73a84 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Date: Wed, 14 May 2025 09:55:06 -0400 Subject: [PATCH 105/143] Update .changeset/fifty-trains-bow.md Co-authored-by: Patrik Oldsberg Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> --- .changeset/fifty-trains-bow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/fifty-trains-bow.md b/.changeset/fifty-trains-bow.md index 29c0ee4315..37d05c177e 100644 --- a/.changeset/fifty-trains-bow.md +++ b/.changeset/fifty-trains-bow.md @@ -1,5 +1,5 @@ --- -'@backstage/cli': minor +'@backstage/cli': patch --- Add missing modules to the Backstage CLI alpha entrypoint. From 0092facaaa063e0a6e03e5ac5de864b1bd6fd798 Mon Sep 17 00:00:00 2001 From: "Maceachern, Matthew" Date: Mon, 5 May 2025 14:02:45 -0400 Subject: [PATCH 106/143] Fix typo in CONTRIBUTING.md Signed-off-by: Matthew MacEachern --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a91fc4196..9413206197 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -388,7 +388,7 @@ Once you've submitted a Pull Request (PR) the various bots will come out and do - adding labels to help make reviewing PRs easier - checking for missing changesets or confirming them - checking for commits for their DCO (Developer Certificate of Origin) -- kick of the various CI builds +- kick off the various CI builds Once these steps are completed, it's just a matter of being patient. As the reviewers have time, they will begin reviewing your PR. When the review process begins, there may be a few layers to this, but the general rule is that you need approval from one of the core maintainers and one from the specific area impacted by your PR. You may also have someone from the community review your changes. This can really help speed things up as they may catch some early items making the review for the maintainers simpler. Once you have the two (2) approvals, it's ready to be merged, a task that is also performed by the maintainers. From c2545d5828d535375d7c329fd37f527a15b93176 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Wed, 14 May 2025 13:35:58 -0400 Subject: [PATCH 107/143] remove support for string filtering Signed-off-by: Mark Dunphy --- .../EntityContextMenuItemBlueprint.test.tsx | 218 ++++++++---------- .../EntityContextMenuItemBlueprint.tsx | 30 ++- plugins/catalog/src/alpha/pages.test.tsx | 6 +- plugins/catalog/src/alpha/pages.tsx | 8 +- 4 files changed, 125 insertions(+), 137 deletions(-) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 2491b714b1..6c0efb84dd 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -89,124 +89,117 @@ describe('EntityContextMenuItemBlueprint', () => { "properties": { "filter": { "anyOf": [ - { - "type": "string", - }, { "anyOf": [ { - "anyOf": [ - { - "type": [ - "string", - "number", - "boolean", - ], - }, - { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", - }, - "type": "array", - }, + "type": [ + "string", + "number", + "boolean", ], }, { - "additionalProperties": false, - "properties": { - "$all": { - "items": { - "$ref": "#/properties/filter/anyOf/1", - }, - "type": "array", - }, + "items": { + "$ref": "#/properties/filter/anyOf/0/anyOf/0", }, - "required": [ - "$all", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$any": { - "items": { - "$ref": "#/properties/filter/anyOf/1", - }, - "type": "array", - }, - }, - "required": [ - "$any", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$not": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$not", - ], - "type": "object", - }, - { - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/properties/filter/anyOf/1/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", + "type": "array", }, ], }, + { + "additionalProperties": false, + "properties": { + "$all": { + "items": { + "$ref": "#/properties/filter", + }, + "type": "array", + }, + }, + "required": [ + "$all", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$any": { + "items": { + "$ref": "#/properties/filter", + }, + "type": "array", + }, + }, + "required": [ + "$any", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$not": { + "$ref": "#/properties/filter", + }, + }, + "required": [ + "$not", + ], + "type": "object", + }, + { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/properties/filter/anyOf/0", + }, + { + "additionalProperties": false, + "properties": { + "$exists": { + "type": "boolean", + }, + }, + "required": [ + "$exists", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$in": { + "items": { + "$ref": "#/properties/filter/anyOf/0/anyOf/0", + }, + "type": "array", + }, + }, + "required": [ + "$in", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$contains": { + "$ref": "#/properties/filter", + }, + }, + "required": [ + "$contains", + ], + "type": "object", + }, + ], + }, + "propertyNames": { + "pattern": "^(?!\\$).*$", + }, + "type": "object", + }, ], }, }, @@ -229,15 +222,6 @@ describe('EntityContextMenuItemBlueprint', () => { "optional": [Function], "toString": [Function], }, - { - "$$type": "@backstage/ExtensionDataRef", - "config": { - "optional": true, - }, - "id": "catalog.entity-filter-expression", - "optional": [Function], - "toString": [Function], - }, ], "override": [Function], "toString": [Function], diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx index 59cd0b48e4..470aa13646 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.tsx @@ -24,14 +24,13 @@ import MenuItem from '@material-ui/core/MenuItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import { useEntityContextMenu } from '../../hooks/useEntityContextMenu'; -import { EntityPredicate } from '../predicates'; -import type { Entity } from '@backstage/catalog-model'; import { - entityFilterExpressionDataRef, - entityFilterFunctionDataRef, -} from './extensionData'; + EntityPredicate, + entityPredicateToFilterFunction, +} from '../predicates'; +import type { Entity } from '@backstage/catalog-model'; +import { entityFilterFunctionDataRef } from './extensionData'; import { createEntityPredicateSchema } from '../predicates/createEntityPredicateSchema'; -import { resolveEntityFilterData } from './resolveEntityFilterData'; /** @alpha */ export type UseProps = () => | { @@ -49,7 +48,7 @@ export type UseProps = () => export type EntityContextMenuItemParams = { useProps: UseProps; icon: JSX.Element; - filter?: string | EntityPredicate | ((entity: Entity) => boolean); + filter?: EntityPredicate | ((entity: Entity) => boolean); }; /** @alpha */ @@ -59,16 +58,13 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ output: [ coreExtensionData.reactElement, entityFilterFunctionDataRef.optional(), - entityFilterExpressionDataRef.optional(), ], dataRefs: { filterFunction: entityFilterFunctionDataRef, - filterExpression: entityFilterExpressionDataRef, }, config: { schema: { - filter: z => - z.union([z.string(), createEntityPredicateSchema(z)]).optional(), + filter: z => createEntityPredicateSchema(z).optional(), }, }, *factory(params: EntityContextMenuItemParams, { node, config }) { @@ -102,6 +98,16 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({ yield coreExtensionData.reactElement(ExtensionBoundary.lazy(node, loader)); - yield* resolveEntityFilterData(params.filter, config, node); + if (config.filter) { + yield entityFilterFunctionDataRef( + entityPredicateToFilterFunction(config.filter), + ); + } else if (typeof params.filter === 'function') { + yield entityFilterFunctionDataRef(params.filter); + } else if (params.filter) { + yield entityFilterFunctionDataRef( + entityPredicateToFilterFunction(params.filter), + ); + } }, }); diff --git a/plugins/catalog/src/alpha/pages.test.tsx b/plugins/catalog/src/alpha/pages.test.tsx index 6e5d3fab95..47b3efbd0a 100644 --- a/plugins/catalog/src/alpha/pages.test.tsx +++ b/plugins/catalog/src/alpha/pages.test.tsx @@ -738,11 +738,11 @@ describe('Entity page', () => { it.each([ { positive: { params: {} }, - negative: { params: { filter: 'kind:api' } }, + negative: { params: { filter: { kind: 'api' } } }, }, { - positive: { params: { filter: 'kind:component' } }, - negative: { params: { filter: 'kind:api' } }, + positive: { params: { filter: { kind: 'component' } } }, + negative: { params: { filter: { kind: 'api' } } }, }, { positive: { diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index 3708ae11fa..8eef497845 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -75,7 +75,6 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ contextMenuItems: createExtensionInput([ coreExtensionData.reactElement, EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional(), - EntityContextMenuItemBlueprint.dataRefs.filterExpression.optional(), ]), }, config: { @@ -95,10 +94,9 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ const menuItems = inputs.contextMenuItems.map(item => ({ element: item.get(coreExtensionData.reactElement), - filter: buildFilterFn( - item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction), - item.get(EntityContextMenuItemBlueprint.dataRefs.filterExpression), - ), + filter: + item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction) ?? + (() => true), })); type Groups = Record< From bd182548180db7de83e32fa92c3c9e747e39f837 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Wed, 14 May 2025 13:39:01 -0400 Subject: [PATCH 108/143] revert buildFilterFn relocation af0ab1cb788287cf645a5874796e2b375ace6b9d Signed-off-by: Mark Dunphy --- plugins/catalog-react/src/alpha/index.ts | 1 - plugins/catalog/src/alpha/entityContents.tsx | 2 +- .../src/alpha/filter/FilterWrapper.tsx | 10 +++------- .../src/alpha/filter/matchers/createHasMatcher.test.ts | 0 .../src/alpha/filter/matchers/createHasMatcher.ts | 0 .../src/alpha/filter/matchers/createIsMatcher.test.ts | 0 .../src/alpha/filter/matchers/createIsMatcher.ts | 0 .../alpha/filter/matchers/createKindMatcher.test.ts | 0 .../src/alpha/filter/matchers/createKindMatcher.ts | 0 .../alpha/filter/matchers/createTypeMatcher.test.ts | 0 .../src/alpha/filter/matchers/createTypeMatcher.ts | 0 .../src/alpha/filter/matchers/types.ts | 0 .../src/alpha/filter/parseFilterExpression.test.ts | 0 .../src/alpha/filter/parseFilterExpression.ts | 0 plugins/catalog/src/alpha/pages.tsx | 2 +- 15 files changed, 5 insertions(+), 10 deletions(-) rename plugins/{catalog-react => catalog}/src/alpha/filter/FilterWrapper.tsx (94%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createHasMatcher.test.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createHasMatcher.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createIsMatcher.test.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createIsMatcher.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createKindMatcher.test.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createKindMatcher.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createTypeMatcher.test.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/createTypeMatcher.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/matchers/types.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/parseFilterExpression.test.ts (100%) rename plugins/{catalog-react => catalog}/src/alpha/filter/parseFilterExpression.ts (100%) diff --git a/plugins/catalog-react/src/alpha/index.ts b/plugins/catalog-react/src/alpha/index.ts index f1b8b05c62..4ff4dbf0dd 100644 --- a/plugins/catalog-react/src/alpha/index.ts +++ b/plugins/catalog-react/src/alpha/index.ts @@ -20,4 +20,3 @@ export * from './predicates'; export { catalogReactTranslationRef } from '../translation'; export { isOwnerOf } from '../utils/isOwnerOf'; export { useEntityPermission } from '../hooks/useEntityPermission'; -export { buildFilterFn } from './filter/FilterWrapper'; diff --git a/plugins/catalog/src/alpha/entityContents.tsx b/plugins/catalog/src/alpha/entityContents.tsx index 224557519e..165ed33e04 100644 --- a/plugins/catalog/src/alpha/entityContents.tsx +++ b/plugins/catalog/src/alpha/entityContents.tsx @@ -26,7 +26,7 @@ import { EntityContentLayoutBlueprint, EntityContentLayoutProps, } from '@backstage/plugin-catalog-react/alpha'; -import { buildFilterFn } from '@backstage/plugin-catalog-react/alpha'; +import { buildFilterFn } from './filter/FilterWrapper'; import { useEntity } from '@backstage/plugin-catalog-react'; export const catalogOverviewEntityContent = diff --git a/plugins/catalog-react/src/alpha/filter/FilterWrapper.tsx b/plugins/catalog/src/alpha/filter/FilterWrapper.tsx similarity index 94% rename from plugins/catalog-react/src/alpha/filter/FilterWrapper.tsx rename to plugins/catalog/src/alpha/filter/FilterWrapper.tsx index 76ee69b087..33af9c2c3f 100644 --- a/plugins/catalog-react/src/alpha/filter/FilterWrapper.tsx +++ b/plugins/catalog/src/alpha/filter/FilterWrapper.tsx @@ -24,13 +24,9 @@ import { parseFilterExpression } from './parseFilterExpression'; const seenParseErrorExpressionStrings = new Set(); const seenDuplicateExpressionStrings = new Set(); -/** - * Given an optional filter function and an optional filter expression, make - * sure that at most one of them was given, and return a filter function that - * does the right thing. - * - * @alpha - */ +// Given an optional filter function and an optional filter expression, make +// sure that at most one of them was given, and return a filter function that +// does the right thing. export function buildFilterFn( filterFunction?: (entity: Entity) => boolean, filterExpression?: string, diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.test.ts b/plugins/catalog/src/alpha/filter/matchers/createHasMatcher.test.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.test.ts rename to plugins/catalog/src/alpha/filter/matchers/createHasMatcher.test.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.ts b/plugins/catalog/src/alpha/filter/matchers/createHasMatcher.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createHasMatcher.ts rename to plugins/catalog/src/alpha/filter/matchers/createHasMatcher.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.test.ts b/plugins/catalog/src/alpha/filter/matchers/createIsMatcher.test.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.test.ts rename to plugins/catalog/src/alpha/filter/matchers/createIsMatcher.test.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.ts b/plugins/catalog/src/alpha/filter/matchers/createIsMatcher.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createIsMatcher.ts rename to plugins/catalog/src/alpha/filter/matchers/createIsMatcher.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.test.ts b/plugins/catalog/src/alpha/filter/matchers/createKindMatcher.test.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.test.ts rename to plugins/catalog/src/alpha/filter/matchers/createKindMatcher.test.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.ts b/plugins/catalog/src/alpha/filter/matchers/createKindMatcher.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createKindMatcher.ts rename to plugins/catalog/src/alpha/filter/matchers/createKindMatcher.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.test.ts b/plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.test.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.test.ts rename to plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.test.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.ts b/plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/createTypeMatcher.ts rename to plugins/catalog/src/alpha/filter/matchers/createTypeMatcher.ts diff --git a/plugins/catalog-react/src/alpha/filter/matchers/types.ts b/plugins/catalog/src/alpha/filter/matchers/types.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/matchers/types.ts rename to plugins/catalog/src/alpha/filter/matchers/types.ts diff --git a/plugins/catalog-react/src/alpha/filter/parseFilterExpression.test.ts b/plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/parseFilterExpression.test.ts rename to plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts diff --git a/plugins/catalog-react/src/alpha/filter/parseFilterExpression.ts b/plugins/catalog/src/alpha/filter/parseFilterExpression.ts similarity index 100% rename from plugins/catalog-react/src/alpha/filter/parseFilterExpression.ts rename to plugins/catalog/src/alpha/filter/parseFilterExpression.ts diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index 8eef497845..c1f5b55341 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -31,11 +31,11 @@ import { EntityHeaderBlueprint, EntityContentBlueprint, defaultEntityContentGroups, - buildFilterFn, EntityContextMenuItemBlueprint, } from '@backstage/plugin-catalog-react/alpha'; import { rootRouteRef } from '../routes'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; +import { buildFilterFn } from './filter/FilterWrapper'; export const catalogPage = PageBlueprint.makeWithOverrides({ inputs: { From e875caf0591b4486247f8f31b6d4f4f8ce8ee9a0 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Wed, 14 May 2025 13:41:02 -0400 Subject: [PATCH 109/143] api reports Signed-off-by: Mark Dunphy --- plugins/catalog-react/report-alpha.api.md | 20 +--------------- plugins/catalog/report-alpha.api.md | 28 ----------------------- 2 files changed, 1 insertion(+), 47 deletions(-) diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index bb296e7c28..46d3030140 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -16,12 +16,6 @@ import { ResourcePermission } from '@backstage/plugin-permission-common'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; -// @alpha -export function buildFilterFn( - filterFunction?: (entity: Entity) => boolean, - filterExpression?: string, -): (entity: Entity) => boolean; - // @alpha export const CatalogFilterBlueprint: ExtensionBlueprint<{ kind: 'catalog-filter'; @@ -346,13 +340,6 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ { optional: true; } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } >; inputs: {}; config: { @@ -367,11 +354,6 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ 'catalog.entity-filter-function', {} >; - filterExpression: ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - {} - >; }; }>; @@ -379,7 +361,7 @@ export const EntityContextMenuItemBlueprint: ExtensionBlueprint<{ export type EntityContextMenuItemParams = { useProps: UseProps; icon: JSX_2.Element; - filter?: string | EntityPredicate | ((entity: Entity) => boolean); + filter?: EntityPredicate | ((entity: Entity) => boolean); }; // @alpha (undocumented) diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index 93a4e94225..7ef20d8228 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -877,13 +877,6 @@ const _default: FrontendPlugin< { optional: true; } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } >; inputs: {}; params: EntityContextMenuItemParams; @@ -905,13 +898,6 @@ const _default: FrontendPlugin< { optional: true; } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } >; inputs: {}; params: EntityContextMenuItemParams; @@ -933,13 +919,6 @@ const _default: FrontendPlugin< { optional: true; } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } >; inputs: {}; params: EntityContextMenuItemParams; @@ -1097,13 +1076,6 @@ const _default: FrontendPlugin< { optional: true; } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } >, { singleton: false; From c454bd06ff666381de760d94580129c68b016561 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Wed, 14 May 2025 13:44:03 -0400 Subject: [PATCH 110/143] remove unnecessary test cases Signed-off-by: Mark Dunphy --- .../EntityContextMenuItemBlueprint.test.tsx | 85 ------------------- 1 file changed, 85 deletions(-) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 6c0efb84dd..e15eb8a89c 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -48,25 +48,6 @@ describe('EntityContextMenuItemBlueprint', () => { }, ]; - const filterTestCases = [ - { - params: { filter: 'kind:component' }, - config: undefined, - }, - { - params: { filter: (e: Entity) => e.kind.toLowerCase() === 'component' }, - config: undefined, - }, - { - params: {}, - config: { filter: 'kind:component' }, - }, - { - params: {}, - config: { filter: { kind: 'component' } }, - }, - ]; - it.each(data)('should return an extension with sane defaults', params => { const extension = EntityContextMenuItemBlueprint.make({ name: 'test', @@ -230,72 +211,6 @@ describe('EntityContextMenuItemBlueprint', () => { `); }); - it.each(filterTestCases)( - 'should exclude items based on the filter', - async ({ params, config }) => { - const extension = EntityContextMenuItemBlueprint.make({ - name: 'test', - params: { - icon: Icon, - ...params, - useProps: () => ({ - title: 'Test', - onClick: () => {}, - }), - }, - }); - - renderInTestApp( - -
    {createExtensionTester(extension, { config }).reactElement()}
-
, - ); - - await waitFor(() => { - expect(screen.queryByText('Test')).not.toBeInTheDocument(); - }); - }, - ); - - it.each(filterTestCases)( - 'should include items based on the filter', - async ({ params, config }) => { - const extension = EntityContextMenuItemBlueprint.make({ - name: 'test', - params: { - icon: Icon, - ...params, - useProps: () => ({ - title: 'Test', - onClick: () => {}, - }), - }, - }); - - renderInTestApp( - -
    {createExtensionTester(extension, { config }).reactElement()}
-
, - ); - - await waitFor(() => { - expect(screen.getByText('Test')).toBeInTheDocument(); - }); - }, - ); - it('should render a menu item', async () => { const extension = EntityContextMenuItemBlueprint.make({ name: 'test', From 8be3cd3fd89e57b74a819847b020fd75ba944ec9 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Wed, 14 May 2025 15:07:05 -0400 Subject: [PATCH 111/143] remove unused imports Signed-off-by: Mark Dunphy --- .../src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index e15eb8a89c..e91cb70558 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -20,7 +20,6 @@ import { import { EntityContextMenuItemBlueprint } from './EntityContextMenuItemBlueprint'; import { screen, waitFor } from '@testing-library/react'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { Entity } from '@backstage/catalog-model'; jest.mock('../../hooks/useEntityContextMenu', () => ({ useEntityContextMenu: () => ({ From 8112cb4b7ca3f5e6c3a20a0555c7596188b3fa26 Mon Sep 17 00:00:00 2001 From: Mark Dunphy Date: Wed, 14 May 2025 16:46:07 -0400 Subject: [PATCH 112/143] add test for filter function Signed-off-by: Mark Dunphy --- .../EntityContextMenuItemBlueprint.test.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index e91cb70558..55598f5de1 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -20,6 +20,7 @@ import { import { EntityContextMenuItemBlueprint } from './EntityContextMenuItemBlueprint'; import { screen, waitFor } from '@testing-library/react'; import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { Entity } from '@backstage/catalog-model'; jest.mock('../../hooks/useEntityContextMenu', () => ({ useEntityContextMenu: () => ({ @@ -238,4 +239,28 @@ describe('EntityContextMenuItemBlueprint', () => { expect(screen.getByText('Test')).toBeInTheDocument(); }); }); + + it.each([ + { filter: { kind: 'Api' } }, + { filter: (e: Entity) => e.kind.toLowerCase() === 'api' }, + ])('should return a filter function', async ({ filter }) => { + const extension = EntityContextMenuItemBlueprint.make({ + name: 'test', + params: { + icon: Icon, + useProps: () => ({ title: 'Test', onClick: () => {} }), + filter, + }, + }); + + const tester = createExtensionTester(extension); + + const filterFn = tester.get( + EntityContextMenuItemBlueprint.dataRefs.filterFunction, + ); + + expect(filterFn).toBeDefined(); + expect(filterFn?.({ kind: 'Api' } as Entity)).toBe(true); + expect(filterFn?.({ kind: 'Component' } as Entity)).toBe(false); + }); }); From 373131d9545a745cce0b682e45e9775fe913be4f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 13:54:54 +0000 Subject: [PATCH 113/143] Update dependency @google-cloud/firestore to v7.11.1 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 c31541c537..11ad343d60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10466,15 +10466,15 @@ __metadata: linkType: hard "@google-cloud/firestore@npm:^7.0.0": - version: 7.11.0 - resolution: "@google-cloud/firestore@npm:7.11.0" + version: 7.11.1 + resolution: "@google-cloud/firestore@npm:7.11.1" dependencies: "@opentelemetry/api": "npm:^1.3.0" fast-deep-equal: "npm:^3.1.1" functional-red-black-tree: "npm:^1.0.1" google-gax: "npm:^4.3.3" protobufjs: "npm:^7.2.6" - checksum: 10/ae0e42ffee1e5cf7160149e1a581c0ceee702ea34d87d7212f7ffa326d9101f0aa2e9c5d37527a7f75864ac174cf32b50f1c593a81d02476ca4c8b8e85cba3bc + checksum: 10/c793718c5ecc6c4e2f7affabaeaab42af3d382c40c6b748f17bd3724232583073a4d7236f448b24c6b1a9e8bf5d485fb62d1ffb10588b0fe54a0d105fc2b3f40 languageName: node linkType: hard From 6d2df8d24cfb57a4651610d277a5e2e6d120d7e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 14:06:50 +0000 Subject: [PATCH 114/143] Update dependency @useoptic/optic to v1.0.8 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/yarn.lock b/yarn.lock index 20a3f4ff78..ba8512fd0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22073,24 +22073,24 @@ __metadata: languageName: node linkType: hard -"@useoptic/json-pointer-helpers@npm:1.0.6": - version: 1.0.6 - resolution: "@useoptic/json-pointer-helpers@npm:1.0.6" +"@useoptic/json-pointer-helpers@npm:1.0.8": + version: 1.0.8 + resolution: "@useoptic/json-pointer-helpers@npm:1.0.8" dependencies: jsonpointer: "npm:^5.0.1" minimatch: "npm:9.0.3" - checksum: 10/a4a0b2175a7a95c1c658f384d26aed2bc0e9db53aba9d44e03e4be239d3fce8b5e20b089dbb3a3bdfcd9cdf3951d46eeec662f6c47156c14ac8dc0a81463b30e + checksum: 10/075142e33ab89de448283ef2199438e84942ad285600df33d6a8f3553e4d3ab60d139c080c0dcd667f60ee607cadedeceb904739b6d7b03d99c2558413f1b223 languageName: node linkType: hard -"@useoptic/openapi-io@npm:1.0.6": - version: 1.0.6 - resolution: "@useoptic/openapi-io@npm:1.0.6" +"@useoptic/openapi-io@npm:1.0.8": + version: 1.0.8 + resolution: "@useoptic/openapi-io@npm:1.0.8" dependencies: "@apidevtools/json-schema-ref-parser": "npm:9.0.9" "@jsdevtools/ono": "npm:^7.1.3" - "@useoptic/json-pointer-helpers": "npm:1.0.6" - "@useoptic/openapi-utilities": "npm:1.0.6" + "@useoptic/json-pointer-helpers": "npm:1.0.8" + "@useoptic/openapi-utilities": "npm:1.0.8" ajv: "npm:8.17.1" ajv-errors: "npm:~3.0.0" ajv-formats: "npm:~2.1.0" @@ -22108,15 +22108,15 @@ __metadata: upath: "npm:^2.0.1" yaml: "npm:^2.3.2" yaml-ast-parser: "npm:^0.0.43" - checksum: 10/6c91f614d49840c7913a70d60bbdd9b43271765da3c109ea4efcf8191d01206e0ac3729d111bf76dfa5287a3be0a75b5f63b5c88d3c5aca97e8556ba002b6920 + checksum: 10/1d228bf7191ed8496b1ddcb5478ff051f5d7d2014e8dfa4d0e60e3d2def1284dc607e35f6ccba3b36a2d6263ce5fdea0b573bf9a7164f122036f2d54831db159 languageName: node linkType: hard -"@useoptic/openapi-utilities@npm:1.0.6": - version: 1.0.6 - resolution: "@useoptic/openapi-utilities@npm:1.0.6" +"@useoptic/openapi-utilities@npm:1.0.8": + version: 1.0.8 + resolution: "@useoptic/openapi-utilities@npm:1.0.8" dependencies: - "@useoptic/json-pointer-helpers": "npm:1.0.6" + "@useoptic/json-pointer-helpers": "npm:1.0.8" ajv: "npm:8.17.1" ajv-errors: "npm:^3.0.0" ajv-formats: "npm:^3.0.1" @@ -22133,7 +22133,7 @@ __metadata: ts-invariant: "npm:^0.9.3" url-join: "npm:^4.0.1" yaml-ast-parser: "npm:^0.0.43" - checksum: 10/e7aebd5fb1548da8d10512aaf9c54ca2e398ceaca4d3f754393082aa9f6b301823f0a0e24cf6369a12eb13dd520a9e0ad9ade1839820de06a9319c6611f3aae4 + checksum: 10/0c0b7ec345ca9b13553c096dbf39dc90e719fc4c21855134783b7c98896bd16b2bd7e19c5419a345e4e44705e928e8dafea574d20a075028ae50a5871042a5ea languageName: node linkType: hard @@ -22163,8 +22163,8 @@ __metadata: linkType: hard "@useoptic/optic@npm:^1.0.0": - version: 1.0.6 - resolution: "@useoptic/optic@npm:1.0.6" + version: 1.0.8 + resolution: "@useoptic/optic@npm:1.0.8" dependencies: "@babel/runtime": "npm:^7.20.6" "@httptoolkit/httpolyglot": "npm:^2.0.1" @@ -22174,10 +22174,10 @@ __metadata: "@sentry/node": "npm:^7.74.0" "@sinclair/typebox": "npm:0.31.28" "@stoplight/spectral-core": "npm:^1.8.1" - "@useoptic/openapi-io": "npm:1.0.6" - "@useoptic/openapi-utilities": "npm:1.0.6" - "@useoptic/rulesets-base": "npm:1.0.6" - "@useoptic/standard-rulesets": "npm:1.0.6" + "@useoptic/openapi-io": "npm:1.0.8" + "@useoptic/openapi-utilities": "npm:1.0.8" + "@useoptic/rulesets-base": "npm:1.0.8" + "@useoptic/standard-rulesets": "npm:1.0.8" ajv: "npm:8.17.1" ajv-formats: "npm:~2.1.0" async-exit-hook: "npm:^2.0.1" @@ -22234,34 +22234,34 @@ __metadata: yaml: "npm:^2.3.4" bin: optic: build/index.js - checksum: 10/16dd6b98a84eff68cefde74688c4dfc9a219d8b9d960945b4da3a893cf7113f80a05ee9a12a6dd9f907bd4c653bfc40a57c998062dda482595f23ab443c38548 + checksum: 10/7d9275697e068ffe72656bf38044d5724cc18b707e9507c65babe28f1b84017cc7be33abef4fa696fa9290e843342778d0131004aee76417fc902aa25d68038a languageName: node linkType: hard -"@useoptic/rulesets-base@npm:1.0.6": - version: 1.0.6 - resolution: "@useoptic/rulesets-base@npm:1.0.6" +"@useoptic/rulesets-base@npm:1.0.8": + version: 1.0.8 + resolution: "@useoptic/rulesets-base@npm:1.0.8" dependencies: "@stoplight/spectral-core": "npm:^1.8.1" "@stoplight/spectral-rulesets": "npm:^1.14.1" - "@useoptic/json-pointer-helpers": "npm:1.0.6" - "@useoptic/openapi-utilities": "npm:1.0.6" + "@useoptic/json-pointer-helpers": "npm:1.0.8" + "@useoptic/openapi-utilities": "npm:1.0.8" ajv: "npm:^8.6.0" lodash.pick: "npm:^4.4.0" node-fetch: "npm:^2.6.7" semver: "npm:^7.5.4" bin: rulesets-base: build/index.js - checksum: 10/ecf1844f569aa52ece6ae118f1d2df89f1b2d19f28f620bad2dfaa99d8e477d64b9b884718c5e8f62c41a7768129c54e13aae6117b3dd289d458a6edc213591a + checksum: 10/d92a2f72dca642f61ea0a4f0318b0f9e689c647b30c90896c49cfd294ab635b096906c697e57cb28486cc647154025ede0328c72dfc785dd7e873429e316a5db languageName: node linkType: hard -"@useoptic/standard-rulesets@npm:1.0.6": - version: 1.0.6 - resolution: "@useoptic/standard-rulesets@npm:1.0.6" +"@useoptic/standard-rulesets@npm:1.0.8": + version: 1.0.8 + resolution: "@useoptic/standard-rulesets@npm:1.0.8" dependencies: - "@useoptic/openapi-utilities": "npm:1.0.6" - "@useoptic/rulesets-base": "npm:1.0.6" + "@useoptic/openapi-utilities": "npm:1.0.8" + "@useoptic/rulesets-base": "npm:1.0.8" ajv: "npm:^8.6.0" ajv-draft-04: "npm:^1.0.0" ajv-formats: "npm:~2.1.0" @@ -22272,7 +22272,7 @@ __metadata: whatwg-mimetype: "npm:^3.0.0" bin: standard-rulesets: build/index.js - checksum: 10/e1e7d59f5cdd953486583cc9cb9a4a06e3821bb2ff21506a27a261c1c3173ed91f35409297a4f5fed102bd084486c36b60358dbacf3a3c45f6cb59dbf143070e + checksum: 10/63f60ac25fb8cccd0ea89097336cf5bc7ad59022ad6ef49fd382e7555f5ea9d88ca144991315eb07646aa309f5f38f3d056c4b7c869ab6b5f66fa9e93d96f4ef languageName: node linkType: hard From 2b8d6582867458c6f3f1d273bcb11f5f3400b3a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 14:44:55 +0000 Subject: [PATCH 115/143] Update dependency undici to v7.5.0 [SECURITY] Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1aa2e82b27..2db0bba73c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -47497,18 +47497,18 @@ __metadata: linkType: hard "undici@npm:^5.28.4": - version: 5.28.4 - resolution: "undici@npm:5.28.4" + version: 5.29.0 + resolution: "undici@npm:5.29.0" dependencies: "@fastify/busboy": "npm:^2.0.0" - checksum: 10/a666a9f5ac4270c659fafc33d78b6b5039a0adbae3e28f934774c85dcc66ea91da907896f12b414bd6f578508b44d5dc206fa636afa0e49a4e1c9e99831ff065 + checksum: 10/0ceca8924a32acdcc0cfb8dd2d368c217840970aa3f5e314fc169608474be6341c5b8e50cad7bd257dbe3b4e432bc5d0a0d000f83644b54fa11a48735ec52b93 languageName: node linkType: hard "undici@npm:^7.2.3": - version: 7.2.3 - resolution: "undici@npm:7.2.3" - checksum: 10/92870d186682c19f4b9909e4b6229a88b4e73e6e12d7a3e151033cefb66579bdc1d36e46d97e386161ba0afcd84b718e917fca7b7f08d409d918689343034c09 + version: 7.9.0 + resolution: "undici@npm:7.9.0" + checksum: 10/fa92d3d9106612be566e79942174e00426c2e1f9a688fb86c8d1809c84a032c02fc57bd601d2051a45d94bbd312c50221644b58c8186c4f0d64f8ecc7f18b806 languageName: node linkType: hard From c09599ddacca546f64e51eae522767fc631850a2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 15 May 2025 17:21:05 +0200 Subject: [PATCH 116/143] docs/frontend-system: tiny fix Signed-off-by: Patrik Oldsberg --- docs/frontend-system/architecture/10-app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/frontend-system/architecture/10-app.md b/docs/frontend-system/architecture/10-app.md index d1c3820f09..0fa4ba04cc 100644 --- a/docs/frontend-system/architecture/10-app.md +++ b/docs/frontend-system/architecture/10-app.md @@ -30,7 +30,7 @@ const root = app.createRoot(); // Just like any other React we need a root element. No server side rendering is used. const rootEl = document.getElementById('root')!; -ReactDOM.createRoot(rootEl).render(app); +ReactDOM.createRoot(rootEl).render(root); ``` We call `createApp` to create a new app instance, which is responsible for wiring together all of the features that we provide to the app. It also provides a set of built-in [Extensions](./20-extensions.md) that help build out the foundations of the app, as well as defaults for many other systems such as [Utility API](./33-utility-apis.md) implementations, components, icons, themes, and how to load configuration. No real work is done at the point of creating the app though, it's all deferred to the rendering of the element returned from `app.createRoot()`. From bf990b95964ee967c3ee450b553986cb486ffc8c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 15 May 2025 17:27:34 +0200 Subject: [PATCH 117/143] exit prerelease Signed-off-by: Patrik Oldsberg --- .changeset/pre.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index fe254886cd..c2037b7c8a 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.108", From 953554b228870d9c3a0c834aa50c8c885de69f59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 15:35:40 +0000 Subject: [PATCH 118/143] Update dependency @openapitools/openapi-generator-cli to v2.20.0 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 271 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 173 insertions(+), 98 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4ed8dc5fd0..337604b388 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12781,23 +12781,25 @@ __metadata: languageName: node linkType: hard -"@nestjs/axios@npm:3.1.1": - version: 3.1.1 - resolution: "@nestjs/axios@npm:3.1.1" +"@nestjs/axios@npm:4.0.0": + version: 4.0.0 + resolution: "@nestjs/axios@npm:4.0.0" peerDependencies: - "@nestjs/common": ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + "@nestjs/common": ^10.0.0 || ^11.0.0 axios: ^1.3.1 - rxjs: ^6.0.0 || ^7.0.0 - checksum: 10/2022e63016577f9448837591ec5c700c724bf48763ec3006f41acd3edba4e18d5508bcf5f513dfdb8c0f25eb8c6c84aa6378ed6e3ed6abb4aab3f8b8e851db96 + rxjs: ^7.0.0 + checksum: 10/9a61ac8a2fdbf304961696148945ba9e19c0ed73256767b0a643bbafe77106b2f738cb2f35f2fc63bff09a8abcd18365d2f8c772484e2fdd70b455bceb7b5822 languageName: node linkType: hard -"@nestjs/common@npm:10.4.6": - version: 10.4.6 - resolution: "@nestjs/common@npm:10.4.6" +"@nestjs/common@npm:11.0.20": + version: 11.0.20 + resolution: "@nestjs/common@npm:11.0.20" dependencies: + file-type: "npm:20.4.1" iterare: "npm:1.2.1" - tslib: "npm:2.7.0" + load-esm: "npm:1.0.2" + tslib: "npm:2.8.1" uid: "npm:2.0.2" peerDependencies: class-transformer: "*" @@ -12809,25 +12811,25 @@ __metadata: optional: true class-validator: optional: true - checksum: 10/bf1887715a8612e207c621a00761c0caed5c32f3fce9f6abd7de6a9c6f0217f825696f4dde218952017967493e47bd6fcc5b85d6f5d7fe82e31be9811179d2f5 + checksum: 10/ab06f3d910a86351e895829773b28236dcb4a80a3eba1ed902c51dbc44db9d40f619d5f8713c5ce42518fc95633bbe9c80b1c7188ffc4fd3d5d934b561e2f495 languageName: node linkType: hard -"@nestjs/core@npm:10.4.6": - version: 10.4.6 - resolution: "@nestjs/core@npm:10.4.6" +"@nestjs/core@npm:11.0.20": + version: 11.0.20 + resolution: "@nestjs/core@npm:11.0.20" dependencies: - "@nuxtjs/opencollective": "npm:0.3.2" + "@nuxt/opencollective": "npm:0.4.1" fast-safe-stringify: "npm:2.1.1" iterare: "npm:1.2.1" - path-to-regexp: "npm:3.3.0" - tslib: "npm:2.7.0" + path-to-regexp: "npm:8.2.0" + tslib: "npm:2.8.1" uid: "npm:2.0.2" peerDependencies: - "@nestjs/common": ^10.0.0 - "@nestjs/microservices": ^10.0.0 - "@nestjs/platform-express": ^10.0.0 - "@nestjs/websockets": ^10.0.0 + "@nestjs/common": ^11.0.0 + "@nestjs/microservices": ^11.0.0 + "@nestjs/platform-express": ^11.0.0 + "@nestjs/websockets": ^11.0.0 reflect-metadata: ^0.1.12 || ^0.2.0 rxjs: ^7.1.0 peerDependenciesMeta: @@ -12837,7 +12839,7 @@ __metadata: optional: true "@nestjs/websockets": optional: true - checksum: 10/09dd2b2a44a4c3cb546db78027ec76fbd6b12510b3013217d012b670abcbf6f7f021a91b0a59fe65eb5bc0cd53634edb9daebb61341d1d10e44476087759d21a + checksum: 10/0e18e6744eaa912442d43d6a8d5543bc4b7e09d350943881d76110aa53a0d26876818898d1ddb71f92d24e6f7154ab3264c6c5604c9670221a5f63552e61d431 languageName: node linkType: hard @@ -13124,6 +13126,17 @@ __metadata: languageName: node linkType: hard +"@nuxt/opencollective@npm:0.4.1": + version: 0.4.1 + resolution: "@nuxt/opencollective@npm:0.4.1" + dependencies: + consola: "npm:^3.2.3" + bin: + opencollective: bin/opencollective.js + checksum: 10/37739657e87196c7f1019a76bc33dc6e33b028eeeec43ffbf29c821e89bf5c170514e9e224456e1da85d95859ba63a3a36bd7ce1b82f2d366f7be3d6299e7631 + languageName: node + linkType: hard + "@nuxtjs/opencollective@npm:0.3.2": version: 0.3.2 resolution: "@nuxtjs/opencollective@npm:0.3.2" @@ -13891,30 +13904,30 @@ __metadata: linkType: hard "@openapitools/openapi-generator-cli@npm:^2.4.26, @openapitools/openapi-generator-cli@npm:^2.7.0": - version: 2.15.3 - resolution: "@openapitools/openapi-generator-cli@npm:2.15.3" + version: 2.20.0 + resolution: "@openapitools/openapi-generator-cli@npm:2.20.0" dependencies: - "@nestjs/axios": "npm:3.1.1" - "@nestjs/common": "npm:10.4.6" - "@nestjs/core": "npm:10.4.6" + "@nestjs/axios": "npm:4.0.0" + "@nestjs/common": "npm:11.0.20" + "@nestjs/core": "npm:11.0.20" "@nuxtjs/opencollective": "npm:0.3.2" - axios: "npm:1.7.7" + axios: "npm:1.8.4" chalk: "npm:4.1.2" commander: "npm:8.3.0" compare-versions: "npm:4.1.4" concurrently: "npm:6.5.1" console.table: "npm:0.10.0" - fs-extra: "npm:10.1.0" + fs-extra: "npm:11.3.0" glob: "npm:9.3.5" inquirer: "npm:8.2.6" lodash: "npm:4.17.21" - proxy-agent: "npm:6.4.0" - reflect-metadata: "npm:0.1.13" - rxjs: "npm:7.8.1" + proxy-agent: "npm:6.5.0" + reflect-metadata: "npm:0.2.2" + rxjs: "npm:7.8.2" tslib: "npm:2.8.1" bin: openapi-generator-cli: main.js - checksum: 10/8956772c697b11205c577a3f77161853a00cfdc405189fdc4d71cc20a1bc2d2d07a28ae50b0e2d7c43dee89ad57af1dab2b4675599d9ce2e223811542c8b5cd0 + checksum: 10/b5114d7811505e4fd3e7fa050c1262a76510b1d9e0c1a0e24a417f9570ca986a2edc0c7234eea0e6e30aae2ed698d2e9815ccdd8a5d1663b5794e9e505868edb languageName: node linkType: hard @@ -19784,6 +19797,17 @@ __metadata: languageName: node linkType: hard +"@tokenizer/inflate@npm:^0.2.6": + version: 0.2.7 + resolution: "@tokenizer/inflate@npm:0.2.7" + dependencies: + debug: "npm:^4.4.0" + fflate: "npm:^0.8.2" + token-types: "npm:^6.0.0" + checksum: 10/6cee1857e47ca0fc053d6cd87773b7c21857ab84cb847c7d9437a76d923e265c88f8e99a4ac9643c2f989f4b9791259ca17128f0480191449e2b412821a1b9a7 + languageName: node + linkType: hard + "@tokenizer/token@npm:^0.3.0": version: 0.3.0 resolution: "@tokenizer/token@npm:0.3.0" @@ -23472,7 +23496,7 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": version: 7.1.3 resolution: "agent-base@npm:7.1.3" checksum: 10/3db6d8d4651f2aa1a9e4af35b96ab11a7607af57a24f3bc721a387eaa3b5f674e901f0a648b0caefd48f3fd117c7761b79a3b55854e2aebaa96c3f32cf76af84 @@ -24417,14 +24441,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:1.7.7": - version: 1.7.7 - resolution: "axios@npm:1.7.7" +"axios@npm:1.8.4": + version: 1.8.4 + resolution: "axios@npm:1.8.4" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10/7f875ea13b9298cd7b40fd09985209f7a38d38321f1118c701520939de2f113c4ba137832fe8e3f811f99a38e12c8225481011023209a77b0c0641270e20cde1 + checksum: 10/a10f0dd836613924e48cf03dc2eff3fd21b14f764807aedaee4880a70c0f142aaebdb21da7ce27104d4c16ca00d0e452a20a20851f60e385a8d5bad1ae909d46 languageName: node linkType: hard @@ -26612,6 +26636,13 @@ __metadata: languageName: node linkType: hard +"consola@npm:^3.2.3": + version: 3.4.2 + resolution: "consola@npm:3.4.2" + checksum: 10/32192c9f50d7cac27c5d7c4ecd3ff3679aea863e6bf5bd6a9cc2b05d1cd78addf5dae71df08c54330c142be8e7fbd46f051030129b57c6aacdd771efe409c4b2 + languageName: node + linkType: hard + "console-browserify@npm:^1.1.0": version: 1.2.0 resolution: "console-browserify@npm:1.2.0" @@ -30453,6 +30484,13 @@ __metadata: languageName: node linkType: hard +"fflate@npm:^0.8.2": + version: 0.8.2 + resolution: "fflate@npm:0.8.2" + checksum: 10/2bd26ba6d235d428de793c6a0cd1aaa96a06269ebd4e21b46c8fd1bd136abc631acf27e188d47c3936db090bf3e1ede11d15ce9eae9bffdc4bfe1b9dc66ca9cb + languageName: node + linkType: hard + "figures@npm:^3.0.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -30471,6 +30509,18 @@ __metadata: languageName: node linkType: hard +"file-type@npm:20.4.1": + version: 20.4.1 + resolution: "file-type@npm:20.4.1" + dependencies: + "@tokenizer/inflate": "npm:^0.2.6" + strtok3: "npm:^10.2.0" + token-types: "npm:^6.0.0" + uint8array-extras: "npm:^1.4.0" + checksum: 10/efbb81c69c84ea4d83ea86dc1c95a45bc6830d5455deb7666e0dbefde2dbfe2bcee4e5398bfc5a8fc1ac55a80a27a3ec4f2bff4b53d4af20be799db4fae324b6 + languageName: node + linkType: hard + "file-type@npm:3.9.0": version: 3.9.0 resolution: "file-type@npm:3.9.0" @@ -31002,14 +31052,14 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:10.1.0, fs-extra@npm:^10.0.0": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" +"fs-extra@npm:11.3.0, fs-extra@npm:^11.0.0, fs-extra@npm:^11.1.0, fs-extra@npm:^11.2.0": + version: 11.3.0 + resolution: "fs-extra@npm:11.3.0" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/05ce2c3b59049bcb7b52001acd000e44b3c4af4ec1f8839f383ef41ec0048e3cfa7fd8a637b1bddfefad319145db89be91f4b7c1db2908205d38bf91e7d1d3b7 + checksum: 10/c9fe7b23dded1efe7bbae528d685c3206477e20cc60e9aaceb3f024f9b9ff2ee1f62413c161cb88546cc564009ab516dec99e9781ba782d869bb37e4fe04a97f languageName: node linkType: hard @@ -31025,14 +31075,14 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.0.0, fs-extra@npm:^11.1.0, fs-extra@npm:^11.2.0": - version: 11.2.0 - resolution: "fs-extra@npm:11.2.0" +"fs-extra@npm:^10.0.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/0579bf6726a4cd054d4aa308f10b483f52478bb16284f32cf60b4ce0542063d551fca1a08a2af365e35db21a3fa5a06cf2a6ed614004b4368982bc754cb816b3 + checksum: 10/05ce2c3b59049bcb7b52001acd000e44b3c4af4ec1f8839f383ef41ec0048e3cfa7fd8a637b1bddfefad319145db89be91f4b7c1db2908205d38bf91e7d1d3b7 languageName: node linkType: hard @@ -32615,13 +32665,13 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.0, https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.3, https-proxy-agent@npm:^7.0.5": - version: 7.0.5 - resolution: "https-proxy-agent@npm:7.0.5" +"https-proxy-agent@npm:^7.0.0, https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.5, https-proxy-agent@npm:^7.0.6": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.2" debug: "npm:4" - checksum: 10/6679d46159ab3f9a5509ee80c3a3fc83fba3a920a5e18d32176c3327852c3c00ad640c0c4210a8fd70ea3c4a6d3a1b375bf01942516e7df80e2646bdc77658ab + checksum: 10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13 languageName: node linkType: hard @@ -36039,6 +36089,13 @@ __metadata: languageName: node linkType: hard +"load-esm@npm:1.0.2": + version: 1.0.2 + resolution: "load-esm@npm:1.0.2" + checksum: 10/1b4adb40c28c6fdbd4ca8c97942c04debddb3c93ae91413540ff5a21ca3511a651988c835cb80cad7288d1ecb869c4794b8a787ab02e09cc07ec951ad1eefcf9 + languageName: node + linkType: hard + "load-yaml-file@npm:^0.2.0": version: 0.2.0 resolution: "load-yaml-file@npm:0.2.0" @@ -39916,19 +39973,19 @@ __metadata: languageName: node linkType: hard -"pac-proxy-agent@npm:^7.0.0, pac-proxy-agent@npm:^7.0.1": - version: 7.0.2 - resolution: "pac-proxy-agent@npm:7.0.2" +"pac-proxy-agent@npm:^7.0.0, pac-proxy-agent@npm:^7.1.0": + version: 7.2.0 + resolution: "pac-proxy-agent@npm:7.2.0" dependencies: "@tootallnate/quickjs-emscripten": "npm:^0.23.0" - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.2" debug: "npm:^4.3.4" get-uri: "npm:^6.0.1" http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.5" + https-proxy-agent: "npm:^7.0.6" pac-resolver: "npm:^7.0.1" - socks-proxy-agent: "npm:^8.0.4" - checksum: 10/bb9b53b32ba98f085fd98ad0ea5e4201498585bf8d9390b3365c057b692b8562997be166d44224878ac216a81f1016c1f55f4e1dec52a6d92e5aa659eba9124c + socks-proxy-agent: "npm:^8.0.5" + checksum: 10/187656be62d5a6b983d90a86d64106a38b1a9ee78f591fabb27b3cf0d51e5d528456a9faaaf981c93dd54dc9c9ee8d33e35a51072b73a19ec1a8e0d0c36a2b99 languageName: node linkType: hard @@ -40400,6 +40457,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:8.2.0, path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.1.0": + version: 8.2.0 + resolution: "path-to-regexp@npm:8.2.0" + checksum: 10/23378276a172b8ba5f5fb824475d1818ca5ccee7bbdb4674701616470f23a14e536c1db11da9c9e6d82b82c556a817bbf4eee6e41b9ed20090ef9427cbb38e13 + languageName: node + linkType: hard + "path-to-regexp@npm:^6.3.0": version: 6.3.0 resolution: "path-to-regexp@npm:6.3.0" @@ -40407,13 +40471,6 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.1.0": - version: 8.2.0 - resolution: "path-to-regexp@npm:8.2.0" - checksum: 10/23378276a172b8ba5f5fb824475d1818ca5ccee7bbdb4674701616470f23a14e536c1db11da9c9e6d82b82c556a817bbf4eee6e41b9ed20090ef9427cbb38e13 - languageName: node - linkType: hard - "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -40469,6 +40526,13 @@ __metadata: languageName: node linkType: hard +"peek-readable@npm:^7.0.0": + version: 7.0.0 + resolution: "peek-readable@npm:7.0.0" + checksum: 10/e14d533c6a43f3991bb98b644101a55631e307f7fe70e26bd0fd0341bde1e6cdd60e205a66ec17c226b32cb8a4ad5c4e76c1a6173d37201f0bf466cbb617485c + languageName: node + linkType: hard + "pend@npm:~1.2.0": version: 1.2.0 resolution: "pend@npm:1.2.0" @@ -41765,19 +41829,19 @@ __metadata: languageName: node linkType: hard -"proxy-agent@npm:6.4.0": - version: 6.4.0 - resolution: "proxy-agent@npm:6.4.0" +"proxy-agent@npm:6.5.0": + version: 6.5.0 + resolution: "proxy-agent@npm:6.5.0" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.2" debug: "npm:^4.3.4" http-proxy-agent: "npm:^7.0.1" - https-proxy-agent: "npm:^7.0.3" + https-proxy-agent: "npm:^7.0.6" lru-cache: "npm:^7.14.1" - pac-proxy-agent: "npm:^7.0.1" + pac-proxy-agent: "npm:^7.1.0" proxy-from-env: "npm:^1.1.0" - socks-proxy-agent: "npm:^8.0.2" - checksum: 10/a22f202b74cc52f093efd9bfe52de8db08eda8bbc16b9d3d73acda2acc1b40223966e5521b1706788b06adf9265f093ed554d989b354e81b2d6ad482e5bd4d23 + socks-proxy-agent: "npm:^8.0.5" + checksum: 10/56d5a494d96dafad94868870af776939e7b9aaca172465a5c251d2523496a8353b029c32d2a72a012bd62622cdc9a43ba3df59b5738ab7b740bc6b362e9f9477 languageName: node linkType: hard @@ -43133,10 +43197,10 @@ __metadata: languageName: node linkType: hard -"reflect-metadata@npm:0.1.13": - version: 0.1.13 - resolution: "reflect-metadata@npm:0.1.13" - checksum: 10/732570da35d2d96f8fdd5aac60fb263aa92f6512eaded5962b052bd9e90f22a9dec5aaf0d7ff4bfe97646c9530e8444e8435c2d80b24d0bdf938b5d47f6f5b83 +"reflect-metadata@npm:0.2.2": + version: 0.2.2 + resolution: "reflect-metadata@npm:0.2.2" + checksum: 10/1c93f9ac790fea1c852fde80c91b2760420069f4862f28e6fae0c00c6937a56508716b0ed2419ab02869dd488d123c4ab92d062ae84e8739ea7417fae10c4745 languageName: node linkType: hard @@ -44016,12 +44080,12 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:7.8.1": - version: 7.8.1 - resolution: "rxjs@npm:7.8.1" +"rxjs@npm:7.8.2, rxjs@npm:^7.2.0, rxjs@npm:^7.5.5": + version: 7.8.2 + resolution: "rxjs@npm:7.8.2" dependencies: tslib: "npm:^2.1.0" - checksum: 10/b10cac1a5258f885e9dd1b70d23c34daeb21b61222ee735d2ec40a8685bdca40429000703a44f0e638c27a684ac139e1c37e835d2a0dc16f6fc061a138ae3abb + checksum: 10/03dff09191356b2b87d94fbc1e97c4e9eb3c09d4452399dddd451b09c2f1ba8d56925a40af114282d7bc0c6fe7514a2236ca09f903cf70e4bbf156650dddb49d languageName: node linkType: hard @@ -44034,15 +44098,6 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.2.0, rxjs@npm:^7.5.5": - version: 7.8.2 - resolution: "rxjs@npm:7.8.2" - dependencies: - tslib: "npm:^2.1.0" - checksum: 10/03dff09191356b2b87d94fbc1e97c4e9eb3c09d4452399dddd451b09c2f1ba8d56925a40af114282d7bc0c6fe7514a2236ca09f903cf70e4bbf156650dddb49d - languageName: node - linkType: hard - "sade@npm:^1.7.3": version: 1.8.1 resolution: "sade@npm:1.8.1" @@ -44939,7 +44994,7 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1, socks-proxy-agent@npm:^8.0.2, socks-proxy-agent@npm:^8.0.3, socks-proxy-agent@npm:^8.0.4": +"socks-proxy-agent@npm:^8.0.1, socks-proxy-agent@npm:^8.0.3, socks-proxy-agent@npm:^8.0.4, socks-proxy-agent@npm:^8.0.5": version: 8.0.5 resolution: "socks-proxy-agent@npm:8.0.5" dependencies: @@ -45827,6 +45882,16 @@ __metadata: languageName: node linkType: hard +"strtok3@npm:^10.2.0": + version: 10.2.2 + resolution: "strtok3@npm:10.2.2" + dependencies: + "@tokenizer/token": "npm:^0.3.0" + peek-readable: "npm:^7.0.0" + checksum: 10/964e60d76576232803fc75572adfb8778b55a7ef021ecfa3a507dcdb426f1e2c42580e545ab18f882da8f2e9bfca05fb0659f56f71b18723e95c31c0512301fc + languageName: node + linkType: hard + "strtok3@npm:^6.2.4": version: 6.2.4 resolution: "strtok3@npm:6.2.4" @@ -46703,6 +46768,16 @@ __metadata: languageName: node linkType: hard +"token-types@npm:^6.0.0": + version: 6.0.0 + resolution: "token-types@npm:6.0.0" + dependencies: + "@tokenizer/token": "npm:^0.3.0" + ieee754: "npm:^1.2.1" + checksum: 10/b541b605d602e8e6495745badb35f90ee8f997e43dc29bc51aee7e9a0bc3c6bc7372a305bd45f3e80d75223c2b6a5c7e65cb5159d8c4e49fa25cdbaae531fad4 + languageName: node + linkType: hard + "tosource@npm:^2.0.0-alpha.3": version: 2.0.0-alpha.3 resolution: "tosource@npm:2.0.0-alpha.3" @@ -47009,13 +47084,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.7.0": - version: 2.7.0 - resolution: "tslib@npm:2.7.0" - checksum: 10/9a5b47ddac65874fa011c20ff76db69f97cf90c78cff5934799ab8894a5342db2d17b4e7613a087046bc1d133d21547ddff87ac558abeec31ffa929c88b7fce6 - languageName: node - linkType: hard - "tslib@npm:^1.11.1, tslib@npm:^1.13.0, tslib@npm:^1.14.1, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -47442,6 +47510,13 @@ __metadata: languageName: node linkType: hard +"uint8array-extras@npm:^1.4.0": + version: 1.4.0 + resolution: "uint8array-extras@npm:1.4.0" + checksum: 10/4d2955d67c112e5ebaa4901272a75fc9ad14902c40f05a178b01e32387aa2702b6840472d931a1ca16e068ac59013c7d9ee2b4b2f141c4e73ba4bc7456490599 + languageName: node + linkType: hard + "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" From d2818d437bcd27ea4935c53003ac943f0266a9a8 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 15 May 2025 18:49:16 +0100 Subject: [PATCH 119/143] Improve TextField Signed-off-by: Charles de Dreuille --- packages/canon/src/components/Button/types.ts | 5 ++--- .../TextField/TextField.stories.tsx | 7 ++++--- .../components/TextField/TextField.styles.css | 19 ++++++++++++++----- .../src/components/TextField/TextField.tsx | 12 ++++++++++-- .../canon/src/components/TextField/types.ts | 3 +-- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts index 4ab62d5683..15feca581c 100644 --- a/packages/canon/src/components/Button/types.ts +++ b/packages/canon/src/components/Button/types.ts @@ -15,7 +15,6 @@ */ import type { ButtonOwnProps } from './Button.props'; -import { ReactElement } from 'react'; /** * Properties for {@link Button} @@ -44,10 +43,10 @@ export interface ButtonProps /** * Optional icon to display at the start of the button */ - iconStart?: ReactElement; + iconStart?: React.ReactNode; /** * Optional icon to display at the end of the button */ - iconEnd?: ReactElement; + iconEnd?: React.ReactNode; } diff --git a/packages/canon/src/components/TextField/TextField.stories.tsx b/packages/canon/src/components/TextField/TextField.stories.tsx index 0615a157a1..86f9034e5c 100644 --- a/packages/canon/src/components/TextField/TextField.stories.tsx +++ b/packages/canon/src/components/TextField/TextField.stories.tsx @@ -17,6 +17,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { TextField } from './TextField'; import { Flex } from '../Flex'; +import { Icon } from '../Icon'; const meta = { title: 'Components/TextField', @@ -79,8 +80,8 @@ export const Sizes: Story = { }, render: args => ( - - + } /> + } /> ), }; @@ -114,7 +115,7 @@ export const WithIcon: Story = { args: { ...WithLabel.args, placeholder: 'Search...', - icon: 'search', + icon: , }, }; diff --git a/packages/canon/src/components/TextField/TextField.styles.css b/packages/canon/src/components/TextField/TextField.styles.css index ad3ccc931b..be7ec3379c 100644 --- a/packages/canon/src/components/TextField/TextField.styles.css +++ b/packages/canon/src/components/TextField/TextField.styles.css @@ -59,15 +59,24 @@ background-color: var(--canon-bg-surface-1); } -.canon-TextFieldInputIcon { - display: block; - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; } +.canon-TextFieldIcon[data-size='small'], +.canon-TextFieldIcon[data-size='small'] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size='medium'], +.canon-TextFieldIcon[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; +} + .canon-TextFieldInput { border: none; background: none; diff --git a/packages/canon/src/components/TextField/TextField.tsx b/packages/canon/src/components/TextField/TextField.tsx index bb32033da4..e4cf43a711 100644 --- a/packages/canon/src/components/TextField/TextField.tsx +++ b/packages/canon/src/components/TextField/TextField.tsx @@ -27,7 +27,7 @@ export const TextField = forwardRef( (props: TextFieldProps, ref) => { const { className, - size = 'medium', + size = 'small', label, description, error, @@ -61,7 +61,15 @@ export const TextField = forwardRef( )}
- {icon && } + {icon && ( + + )} Date: Thu, 15 May 2025 18:50:34 +0100 Subject: [PATCH 120/143] Update Button.tsx Signed-off-by: Charles de Dreuille --- packages/canon/src/components/Button/Button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index ab70f168c8..e9774ad083 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -24,7 +24,7 @@ import type { ButtonProps } from './types'; export const Button = forwardRef( (props: ButtonProps, ref) => { const { - size = 'medium', + size = 'small', variant = 'primary', disabled, iconStart, From 04a65c63ebc8078e6fd9ffda9953d8ba46c4e3f5 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 15 May 2025 18:54:38 +0100 Subject: [PATCH 121/143] Add API report + styles + changeset Signed-off-by: Charles de Dreuille --- .changeset/spotty-papers-call.md | 5 +++++ packages/canon/css/components.css | 17 ++++++++++++----- packages/canon/css/styles.css | 17 ++++++++++++----- packages/canon/css/textfield.css | 17 ++++++++++++----- packages/canon/report.api.md | 6 +++--- packages/canon/src/components/Button/Button.tsx | 2 +- 6 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 .changeset/spotty-papers-call.md diff --git a/.changeset/spotty-papers-call.md b/.changeset/spotty-papers-call.md new file mode 100644 index 0000000000..3e39e8e1f8 --- /dev/null +++ b/.changeset/spotty-papers-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': minor +--- + +The icon prop in TextField now accept a ReactNode instead of an icon name. We also updated the icon sizes for each input sizes. diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 6aae715633..d479444df9 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -576,13 +576,20 @@ display: flex; } -.canon-TextFieldInputIcon { - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; - display: block; +} + +.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; } .canon-TextFieldInput { diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 5fb6a934cb..6c53aaa198 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9800,13 +9800,20 @@ display: flex; } -.canon-TextFieldInputIcon { - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; - display: block; +} + +.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; } .canon-TextFieldInput { diff --git a/packages/canon/css/textfield.css b/packages/canon/css/textfield.css index a2980d6beb..c3c1a88ad6 100644 --- a/packages/canon/css/textfield.css +++ b/packages/canon/css/textfield.css @@ -43,13 +43,20 @@ display: flex; } -.canon-TextFieldInputIcon { - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; - display: block; +} + +.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; } .canon-TextFieldInput { diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index da1b5015b4..dec30129e3 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -174,8 +174,8 @@ export const buttonPropDefs: { export interface ButtonProps extends Omit, 'children'> { children: React.ReactNode; - iconEnd?: ReactElement; - iconStart?: ReactElement; + iconEnd?: React.ReactNode; + iconStart?: React.ReactNode; size?: ButtonOwnProps['size']; variant?: ButtonOwnProps['variant']; } @@ -1220,7 +1220,7 @@ export interface TextFieldProps className?: string; description?: string; error?: string | null; - icon?: IconNames; + icon?: React.ReactNode; label?: string; name: string; onClear?: React.MouseEventHandler; diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index e9774ad083..ab70f168c8 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -24,7 +24,7 @@ import type { ButtonProps } from './types'; export const Button = forwardRef( (props: ButtonProps, ref) => { const { - size = 'small', + size = 'medium', variant = 'primary', disabled, iconStart, From 13d15f7bfcf39006dbb475cf2a7aa18d3d02dd7b Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 15 May 2025 20:51:20 +0200 Subject: [PATCH 122/143] permission-common: fix basic permission validation Signed-off-by: Vincenzo Scamporlino --- .../src/PermissionClient.test.ts | 2 +- .../permission-common/src/PermissionClient.ts | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/plugins/permission-common/src/PermissionClient.test.ts b/plugins/permission-common/src/PermissionClient.test.ts index b55e5da94d..4ddfadadda 100644 --- a/plugins/permission-common/src/PermissionClient.test.ts +++ b/plugins/permission-common/src/PermissionClient.test.ts @@ -407,7 +407,7 @@ describe('PermissionClient', () => { }, { id: req.body.items[1].id, - result: [AuthorizeResult.DENY], + result: AuthorizeResult.DENY, }, { id: req.body.items[2].id, diff --git a/plugins/permission-common/src/PermissionClient.ts b/plugins/permission-common/src/PermissionClient.ts index 93c3d5152f..61adc9279a 100644 --- a/plugins/permission-common/src/PermissionClient.ts +++ b/plugins/permission-common/src/PermissionClient.ts @@ -60,14 +60,16 @@ const authorizePermissionResponseSchema: z.ZodSchema = z.union([ @@ -240,9 +242,13 @@ export class PermissionClient implements PermissionEvaluator { const { id } = request[query.permission.name]; const item = responsesById[id]; - return { - result: query.resourceRef ? item.result.shift()! : item.result[0], - }; + + if (Array.isArray(item.result)) { + return { + result: query.resourceRef ? item.result.shift()! : item.result[0], + }; + } + return { result: item.result }; }); } From 37328b1b50a41fed9e705c15ade9e281da844522 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 15 May 2025 20:51:36 +0200 Subject: [PATCH 123/143] permission-common: basic permission changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/shaggy-gifts-beam.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shaggy-gifts-beam.md diff --git a/.changeset/shaggy-gifts-beam.md b/.changeset/shaggy-gifts-beam.md new file mode 100644 index 0000000000..f2957fc2c3 --- /dev/null +++ b/.changeset/shaggy-gifts-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-permission-common': patch +--- + +Fixed an issue causing `PermissionClient` to throw an error when authorizing basic permissions with the `permission.EXPERIMENTAL_enableBatchedRequests` config enabled. From 3fd94f8f5fd3bba158f2a5ac49e597d8b309d244 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 08:20:18 +0100 Subject: [PATCH 124/143] Docs improvements Signed-off-by: Charles de Dreuille --- .../app/(docs)/components/text-field/page.mdx | 17 ++++++++++++----- .../app/(docs)/components/text-field/props.ts | 8 ++++++-- packages/canon/report.api.md | 5 +++-- .../components/TextField/TextField.stories.tsx | 4 ++-- .../canon/src/components/TextField/types.ts | 6 +++--- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/canon-docs/src/app/(docs)/components/text-field/page.mdx b/canon-docs/src/app/(docs)/components/text-field/page.mdx index bd5fa31025..ed857def4e 100644 --- a/canon-docs/src/app/(docs)/components/text-field/page.mdx +++ b/canon-docs/src/app/(docs)/components/text-field/page.mdx @@ -33,9 +33,16 @@ A text field component for your forms. We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> + - `canon-TextField` + - `canon-TextFieldLabel` + - `canon-TextFieldRequired` + - `canon-TextFieldInputWrapper` + - `canon-TextFieldIcon` + - `canon-TextFieldInput` + - `canon-TextFieldClearButton` + - `canon-TextFieldClearButtonIcon` + - `canon-TextFieldDescription` + - `canon-TextFieldError` @@ -55,8 +62,8 @@ We support two different sizes: `small`, `medium`. open preview={} code={` - - + } /> + } /> `} /> diff --git a/canon-docs/src/app/(docs)/components/text-field/props.ts b/canon-docs/src/app/(docs)/components/text-field/props.ts index cafed21189..74dec9d5e6 100644 --- a/canon-docs/src/app/(docs)/components/text-field/props.ts +++ b/canon-docs/src/app/(docs)/components/text-field/props.ts @@ -5,12 +5,16 @@ export const inputPropDefs: Record = { size: { type: 'enum', values: ['small', 'medium'], - default: 'medium', - responsive: false, + default: 'small', + responsive: true, }, label: { type: 'string', }, + icon: { + type: 'enum', + values: ['ReactNode'], + }, description: { type: 'string', }, diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index dec30129e3..ebec81fcae 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -15,6 +15,7 @@ import { ForwardRefExoticComponent } from 'react'; import { HTMLAttributes } from 'react'; import { JSX as JSX_2 } from 'react/jsx-runtime'; import { Menu as Menu_2 } from '@base-ui-components/react/menu'; +import type { MouseEventHandler } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RefAttributes } from 'react'; @@ -1220,10 +1221,10 @@ export interface TextFieldProps className?: string; description?: string; error?: string | null; - icon?: React.ReactNode; + icon?: ReactNode; label?: string; name: string; - onClear?: React.MouseEventHandler; + onClear?: MouseEventHandler; size?: 'small' | 'medium' | Partial>; } diff --git a/packages/canon/src/components/TextField/TextField.stories.tsx b/packages/canon/src/components/TextField/TextField.stories.tsx index 86f9034e5c..7e625dad24 100644 --- a/packages/canon/src/components/TextField/TextField.stories.tsx +++ b/packages/canon/src/components/TextField/TextField.stories.tsx @@ -80,8 +80,8 @@ export const Sizes: Story = { }, render: args => ( - } /> - } /> + } /> + } /> ), }; diff --git a/packages/canon/src/components/TextField/types.ts b/packages/canon/src/components/TextField/types.ts index a01061cbfd..8a37a23efe 100644 --- a/packages/canon/src/components/TextField/types.ts +++ b/packages/canon/src/components/TextField/types.ts @@ -15,7 +15,7 @@ */ import type { Breakpoint } from '../../types'; - +import type { ReactNode, MouseEventHandler } from 'react'; /** @public */ export interface TextFieldProps extends Omit, 'size'> { @@ -53,10 +53,10 @@ export interface TextFieldProps /** * An icon to render before the input */ - icon?: React.ReactNode; + icon?: ReactNode; /** * Handler to call when the clear button is pressed */ - onClear?: React.MouseEventHandler; + onClear?: MouseEventHandler; } From 42c36f2a7f04ee6bd8fce1ef623ef1a7424b3c7a Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 08:24:53 +0100 Subject: [PATCH 125/143] Update types.ts Signed-off-by: Charles de Dreuille --- packages/canon/src/components/Button/types.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts index 15feca581c..4ab62d5683 100644 --- a/packages/canon/src/components/Button/types.ts +++ b/packages/canon/src/components/Button/types.ts @@ -15,6 +15,7 @@ */ import type { ButtonOwnProps } from './Button.props'; +import { ReactElement } from 'react'; /** * Properties for {@link Button} @@ -43,10 +44,10 @@ export interface ButtonProps /** * Optional icon to display at the start of the button */ - iconStart?: React.ReactNode; + iconStart?: ReactElement; /** * Optional icon to display at the end of the button */ - iconEnd?: React.ReactNode; + iconEnd?: ReactElement; } From 6ea31e22a3abddf1c4b00f15fa8a96046087f476 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 09:26:19 +0100 Subject: [PATCH 126/143] Update report.api.md Signed-off-by: Charles de Dreuille --- packages/canon/report.api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index ebec81fcae..cbbdd4db33 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -175,8 +175,8 @@ export const buttonPropDefs: { export interface ButtonProps extends Omit, 'children'> { children: React.ReactNode; - iconEnd?: React.ReactNode; - iconStart?: React.ReactNode; + iconEnd?: ReactElement; + iconStart?: ReactElement; size?: ButtonOwnProps['size']; variant?: ButtonOwnProps['variant']; } From 173db8fcd60caaeb824b93b62bc8fe6af58e7e15 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 16 May 2025 09:49:01 +0200 Subject: [PATCH 127/143] frontend-plugin-api: rename AppNodeSpec.source -> .plugin Signed-off-by: Patrik Oldsberg --- .changeset/angry-candies-draw.md | 5 ++++ .changeset/evil-lies-punch.md | 6 +++++ .../compatWrapper/BackwardsCompatProvider.tsx | 2 +- .../src/routing/RouteTracker.test.tsx | 6 ++--- .../src/routing/RouteTracker.tsx | 2 +- .../routing/extractRouteInfoFromAppNode.ts | 4 +-- .../src/tree/instantiateAppNodeTree.test.ts | 1 + .../src/tree/resolveAppNodeSpecs.test.ts | 6 +++++ .../src/tree/resolveAppNodeSpecs.ts | 26 +++++++++++-------- packages/frontend-plugin-api/report.api.md | 2 ++ .../src/apis/definitions/AppTreeApi.ts | 4 +++ .../src/components/ExtensionBoundary.tsx | 4 +-- 12 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 .changeset/angry-candies-draw.md create mode 100644 .changeset/evil-lies-punch.md diff --git a/.changeset/angry-candies-draw.md b/.changeset/angry-candies-draw.md new file mode 100644 index 0000000000..fdf4d31994 --- /dev/null +++ b/.changeset/angry-candies-draw.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +The `source` property of `AppNodeSpec` has been renamed to `plugin`. The old property has been deprecated and will be removed in a future release. diff --git a/.changeset/evil-lies-punch.md b/.changeset/evil-lies-punch.md new file mode 100644 index 0000000000..e878c65731 --- /dev/null +++ b/.changeset/evil-lies-punch.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-app-api': patch +'@backstage/core-compat-api': patch +--- + +Updates to use the new `plugin` property of `AppNodeSpec`. diff --git a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx index 151fb21067..0a5dd68aa3 100644 --- a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx +++ b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx @@ -119,7 +119,7 @@ function LegacyAppContextProvider(props: { children: ReactNode }) { const pluginSet = new Set(); for (const node of tree.nodes.values()) { - const plugin = node.spec.source; + const plugin = node.spec.plugin; if (plugin) { pluginSet.add(toLegacyPlugin(plugin)); } diff --git a/packages/frontend-app-api/src/routing/RouteTracker.test.tsx b/packages/frontend-app-api/src/routing/RouteTracker.test.tsx index 08a9673afc..5cee727075 100644 --- a/packages/frontend-app-api/src/routing/RouteTracker.test.tsx +++ b/packages/frontend-app-api/src/routing/RouteTracker.test.tsx @@ -49,7 +49,7 @@ describe('RouteTracker', () => { appNode: { spec: { extension: { id: 'home.page.index' }, - source: { id: 'home' }, + plugin: { id: 'home' }, }, } as AppNode, }, @@ -63,7 +63,7 @@ describe('RouteTracker', () => { appNode: { spec: { extension: { id: 'plugin1.page.index' }, - source: { id: 'plugin1' }, + plugin: { id: 'plugin1' }, }, } as AppNode, }, @@ -77,7 +77,7 @@ describe('RouteTracker', () => { appNode: { spec: { extension: { id: 'plugin2.page.index' }, - source: { id: 'plugin2' }, + plugin: { id: 'plugin2' }, }, } as AppNode, }, diff --git a/packages/frontend-app-api/src/routing/RouteTracker.tsx b/packages/frontend-app-api/src/routing/RouteTracker.tsx index 4a218a0900..0068f87d4d 100644 --- a/packages/frontend-app-api/src/routing/RouteTracker.tsx +++ b/packages/frontend-app-api/src/routing/RouteTracker.tsx @@ -63,7 +63,7 @@ const getExtensionContext = ( return acc; }, {}); - const plugin = routeObject.appNode?.spec.source; + const plugin = routeObject.appNode?.spec.plugin; const extension = routeObject.appNode?.spec.extension; return { diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts index 17afbeb4c9..a1abaf1599 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts @@ -124,8 +124,8 @@ export function extractRouteInfoFromAppNode(node: AppNode): { routeParents.set(routeRef, newParentRef); currentObj?.routeRefs.add(routeRef); - if (current.spec.source) { - currentObj?.plugins.add(toLegacyPlugin(current.spec.source)); + if (current.spec.plugin) { + currentObj?.plugins.add(toLegacyPlugin(current.spec.plugin)); } } diff --git a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts index a000e016be..8801e2070e 100644 --- a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts +++ b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts @@ -57,6 +57,7 @@ function makeSpec( disabled: extension.disabled, extension: extension as Extension, source: undefined, + plugin: undefined, ...spec, }; } diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts index c486370563..979c851a47 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts @@ -126,6 +126,7 @@ describe('resolveAppNodeSpecs', () => { extension: makeExt('test/a'), attachTo: { id: 'root', input: 'default' }, source: pluginA, + plugin: pluginA, disabled: false, }, ]); @@ -162,6 +163,7 @@ describe('resolveAppNodeSpecs', () => { id: 'test/a', extension: a, attachTo: { id: 'root', input: 'default' }, + plugin, source: plugin, config: { foo: { bar: 1 } }, disabled: false, @@ -170,6 +172,7 @@ describe('resolveAppNodeSpecs', () => { id: 'test/b', extension: b, attachTo: { id: 'root', input: 'default' }, + plugin, source: plugin, config: { foo: { qux: 3 } }, disabled: false, @@ -305,6 +308,7 @@ describe('resolveAppNodeSpecs', () => { id: 'test/a', extension: expect.objectContaining(aOverride), attachTo: { id: 'other', input: 'default' }, + plugin, source: plugin, disabled: false, }, @@ -312,6 +316,7 @@ describe('resolveAppNodeSpecs', () => { id: 'test/b', extension: expect.objectContaining(bOverride), attachTo: { id: 'other', input: 'default' }, + plugin, source: plugin, disabled: true, }, @@ -319,6 +324,7 @@ describe('resolveAppNodeSpecs', () => { id: 'test/c', extension: expect.objectContaining(cOverride), attachTo: { id: 'root', input: 'default' }, + plugin, source: plugin, disabled: false, }, diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index 3da68dcb50..399e6ccb7b 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -46,23 +46,23 @@ export function resolveAppNodeSpecs(options: { const plugins = features.filter(OpaqueFrontendPlugin.isType); const modules = features.filter(isInternalFrontendModule); - const pluginExtensions = plugins.flatMap(source => { - return OpaqueFrontendPlugin.toInternal(source).extensions.map( + const pluginExtensions = plugins.flatMap(plugin => { + return OpaqueFrontendPlugin.toInternal(plugin).extensions.map( extension => ({ ...extension, - source, + plugin, }), ); }); const moduleExtensions = modules.flatMap(mod => toInternalFrontendModule(mod).extensions.flatMap(extension => { // Modules for plugins that are not installed are ignored - const source = plugins.find(p => p.id === mod.pluginId); - if (!source) { + const plugin = plugins.find(p => p.id === mod.pluginId); + if (!plugin) { return []; } - return [{ ...extension, source }]; + return [{ ...extension, plugin }]; }), ); @@ -70,7 +70,7 @@ export function resolveAppNodeSpecs(options: { if (pluginExtensions.some(({ id }) => forbidden.has(id))) { const pluginsStr = pluginExtensions .filter(({ id }) => forbidden.has(id)) - .map(({ source }) => `'${source.id}'`) + .map(({ plugin }) => `'${plugin.id}'`) .join(', '); const forbiddenStr = [...forbidden].map(id => `'${id}'`).join(', '); throw new Error( @@ -80,7 +80,7 @@ export function resolveAppNodeSpecs(options: { if (moduleExtensions.some(({ id }) => forbidden.has(id))) { const pluginsStr = moduleExtensions .filter(({ id }) => forbidden.has(id)) - .map(({ source }) => `'${source.id}'`) + .map(({ plugin }) => `'${plugin.id}'`) .join(', '); const forbiddenStr = [...forbidden].map(id => `'${id}'`).join(', '); throw new Error( @@ -89,12 +89,13 @@ export function resolveAppNodeSpecs(options: { } const configuredExtensions = [ - ...pluginExtensions.map(({ source, ...extension }) => { + ...pluginExtensions.map(({ plugin, ...extension }) => { const internalExtension = toInternalExtension(extension); return { extension: internalExtension, params: { - source, + plugin, + source: plugin, attachTo: internalExtension.attachTo, disabled: internalExtension.disabled, config: undefined as unknown, @@ -107,6 +108,7 @@ export function resolveAppNodeSpecs(options: { extension: internalExtension, params: { source: undefined, + plugin: undefined, attachTo: internalExtension.attachTo, disabled: internalExtension.disabled, config: undefined as unknown, @@ -133,7 +135,8 @@ export function resolveAppNodeSpecs(options: { configuredExtensions.push({ extension: internalExtension, params: { - source: extension.source, + plugin: extension.plugin, + source: extension.plugin, attachTo: internalExtension.attachTo, disabled: internalExtension.disabled, config: undefined, @@ -219,6 +222,7 @@ export function resolveAppNodeSpecs(options: { attachTo: param.params.attachTo, extension: param.extension, disabled: param.params.disabled, + plugin: param.params.plugin, source: param.params.source, config: param.params.config, })); diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index cd5d89401d..1c01e0ac83 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -235,6 +235,8 @@ export interface AppNodeSpec { // (undocumented) readonly id: string; // (undocumented) + readonly plugin?: FrontendPlugin; + // @deprecated (undocumented) readonly source?: FrontendPlugin; } diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts index c9d9896600..0c6dde3cc8 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts @@ -37,6 +37,10 @@ export interface AppNodeSpec { readonly extension: Extension; readonly disabled: boolean; readonly config?: unknown; + readonly plugin?: FrontendPlugin; + /** + * @deprecated Use {@link AppNodeSpec.plugin} instead. + */ readonly source?: FrontendPlugin; } diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx index 46b3956e0e..a55afeeffd 100644 --- a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx @@ -69,14 +69,14 @@ export function ExtensionBoundary(props: ExtensionBoundaryProps) { node.instance?.getData(coreExtensionData.routePath), ); - const plugin = node.spec.source; + const plugin = node.spec.plugin; const Progress = useComponentRef(coreComponentRefs.progress); const fallback = useComponentRef(coreComponentRefs.errorBoundaryFallback); // Skipping "routeRef" attribute in the new system, the extension "id" should provide more insight const attributes = { extensionId: node.spec.id, - pluginId: node.spec.source?.id ?? 'app', + pluginId: node.spec.plugin?.id ?? 'app', }; return ( From f726297733a26706d6ab23d0511be15e55c1cbfa Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 16:35:06 +0100 Subject: [PATCH 128/143] Improve nested menu + combobox Signed-off-by: Charles de Dreuille --- packages/canon/css/components.css | 136 +++++++++- packages/canon/css/menu.css | 136 +++++++++- packages/canon/css/styles.css | 136 +++++++++- .../canon/src/components/Menu/Combobox.tsx | 246 ++++++++++++++++++ .../src/components/Menu/Menu.stories.tsx | 164 +++++++++++- .../canon/src/components/Menu/Menu.styles.css | 136 +++++++++- packages/canon/src/components/Menu/Menu.tsx | 10 +- packages/canon/src/components/Menu/types.ts | 25 ++ 8 files changed, 937 insertions(+), 52 deletions(-) create mode 100644 packages/canon/src/components/Menu/Combobox.tsx diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index d479444df9..cd0809dadb 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -683,16 +683,19 @@ } .canon-MenuPopup { - padding: var(--canon-space-2); + padding: var(--canon-space-1) 0; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); transform-origin: var(--transform-origin); + max-width: min(var(--available-width), 340px); + max-height: min(var(--available-height), 500px); border-radius: .375rem; outline: none; - max-width: 340px; + flex-direction: column; transition: transform .15s, opacity .15s; - overflow: hidden; + display: flex; + overflow: auto; &[data-starting-style], &[data-ending-style] { opacity: 0; @@ -701,26 +704,51 @@ } .canon-MenuItem { - cursor: default; user-select: none; + align-items: center; gap: var(--canon-space-2); + height: 32px; color: var(--canon-fg-primary); border-radius: var(--canon-radius-2); - padding: var(--canon-space-2) var(--canon-space-2); - padding-right: var(--canon-space-4); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; text-decoration: none; display: flex; - &:last-child { - border-bottom: none; + &[data-highlighted] { + background-color: var(--canon-gray-3); + } +} + +.canon-MenuSubmenuTrigger { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + text-decoration: none; + display: flex; + + & .canon-Icon { + color: var(--canon-fg-secondary); } - &[data-highlighted] { - z-index: 0; - background-color: var(--canon-bg-tint-hover); - position: relative; + &[data-popup-open], &[data-highlighted] { + background-color: var(--canon-gray-3); + + & .canon-Icon { + color: var(--canon-fg-primary); + } } } @@ -730,6 +758,90 @@ margin: .375rem 1rem; } +.canon-SubmenuComboboxSearch { + padding: var(--canon-space-2) var(--canon-space-5); + border: none; + border-bottom: 1px solid var(--canon-border); + background-color: var(--canon-bg-surface-1); + color: var(--canon-fg-primary); + outline: none; + line-height: 140%; + + &::placeholder { + color: var(--canon-fg-secondary); + } + + &:focus { + border-color: var(--canon-border-hover); + } + + &:disabled { + opacity: .6; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItems { + padding-top: var(--canon-space-2); + outline: none; + flex-direction: column; + display: flex; + overflow-y: auto; +} + +.canon-SubmenuComboboxNoResults { + padding: var(--canon-space-3); + padding-left: var(--canon-space-5); + color: var(--canon-fg-secondary); + font-size: var(--canon-font-size-3); +} + +.canon-SubmenuComboboxItem { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + text-decoration: none; + display: flex; + + &[data-highlighted] { + background-color: var(--canon-gray-3); + } + + &[data-disabled] { + opacity: .5; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItemCheckbox { + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + background: var(--canon-bg-surface-1); + flex-shrink: 0; + justify-content: center; + align-items: center; + display: flex; +} + +.canon-SubmenuComboboxItemLabel { + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + overflow: hidden; +} + .canon-Link { font-family: var(--canon-font-regular); color: var(--canon-fg-link); diff --git a/packages/canon/css/menu.css b/packages/canon/css/menu.css index de811cde77..d901273cb3 100644 --- a/packages/canon/css/menu.css +++ b/packages/canon/css/menu.css @@ -3,16 +3,19 @@ } .canon-MenuPopup { - padding: var(--canon-space-2); + padding: var(--canon-space-1) 0; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); transform-origin: var(--transform-origin); + max-width: min(var(--available-width), 340px); + max-height: min(var(--available-height), 500px); border-radius: .375rem; outline: none; - max-width: 340px; + flex-direction: column; transition: transform .15s, opacity .15s; - overflow: hidden; + display: flex; + overflow: auto; &[data-starting-style], &[data-ending-style] { opacity: 0; @@ -21,26 +24,51 @@ } .canon-MenuItem { - cursor: default; user-select: none; + align-items: center; gap: var(--canon-space-2); + height: 32px; color: var(--canon-fg-primary); border-radius: var(--canon-radius-2); - padding: var(--canon-space-2) var(--canon-space-2); - padding-right: var(--canon-space-4); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; text-decoration: none; display: flex; - &:last-child { - border-bottom: none; + &[data-highlighted] { + background-color: var(--canon-gray-3); + } +} + +.canon-MenuSubmenuTrigger { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + text-decoration: none; + display: flex; + + & .canon-Icon { + color: var(--canon-fg-secondary); } - &[data-highlighted] { - z-index: 0; - background-color: var(--canon-bg-tint-hover); - position: relative; + &[data-popup-open], &[data-highlighted] { + background-color: var(--canon-gray-3); + + & .canon-Icon { + color: var(--canon-fg-primary); + } } } @@ -49,3 +77,87 @@ height: 1px; margin: .375rem 1rem; } + +.canon-SubmenuComboboxSearch { + padding: var(--canon-space-2) var(--canon-space-5); + border: none; + border-bottom: 1px solid var(--canon-border); + background-color: var(--canon-bg-surface-1); + color: var(--canon-fg-primary); + outline: none; + line-height: 140%; + + &::placeholder { + color: var(--canon-fg-secondary); + } + + &:focus { + border-color: var(--canon-border-hover); + } + + &:disabled { + opacity: .6; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItems { + padding-top: var(--canon-space-2); + outline: none; + flex-direction: column; + display: flex; + overflow-y: auto; +} + +.canon-SubmenuComboboxNoResults { + padding: var(--canon-space-3); + padding-left: var(--canon-space-5); + color: var(--canon-fg-secondary); + font-size: var(--canon-font-size-3); +} + +.canon-SubmenuComboboxItem { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + text-decoration: none; + display: flex; + + &[data-highlighted] { + background-color: var(--canon-gray-3); + } + + &[data-disabled] { + opacity: .5; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItemCheckbox { + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + background: var(--canon-bg-surface-1); + flex-shrink: 0; + justify-content: center; + align-items: center; + display: flex; +} + +.canon-SubmenuComboboxItemLabel { + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + overflow: hidden; +} diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 6c53aaa198..08aaa80970 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9907,16 +9907,19 @@ } .canon-MenuPopup { - padding: var(--canon-space-2); + padding: var(--canon-space-1) 0; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); transform-origin: var(--transform-origin); + max-width: min(var(--available-width), 340px); + max-height: min(var(--available-height), 500px); border-radius: .375rem; outline: none; - max-width: 340px; + flex-direction: column; transition: transform .15s, opacity .15s; - overflow: hidden; + display: flex; + overflow: auto; &[data-starting-style], &[data-ending-style] { opacity: 0; @@ -9925,26 +9928,51 @@ } .canon-MenuItem { - cursor: default; user-select: none; + align-items: center; gap: var(--canon-space-2); + height: 32px; color: var(--canon-fg-primary); border-radius: var(--canon-radius-2); - padding: var(--canon-space-2) var(--canon-space-2); - padding-right: var(--canon-space-4); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; text-decoration: none; display: flex; - &:last-child { - border-bottom: none; + &[data-highlighted] { + background-color: var(--canon-gray-3); + } +} + +.canon-MenuSubmenuTrigger { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + text-decoration: none; + display: flex; + + & .canon-Icon { + color: var(--canon-fg-secondary); } - &[data-highlighted] { - z-index: 0; - background-color: var(--canon-bg-tint-hover); - position: relative; + &[data-popup-open], &[data-highlighted] { + background-color: var(--canon-gray-3); + + & .canon-Icon { + color: var(--canon-fg-primary); + } } } @@ -9954,6 +9982,90 @@ margin: .375rem 1rem; } +.canon-SubmenuComboboxSearch { + padding: var(--canon-space-2) var(--canon-space-5); + border: none; + border-bottom: 1px solid var(--canon-border); + background-color: var(--canon-bg-surface-1); + color: var(--canon-fg-primary); + outline: none; + line-height: 140%; + + &::placeholder { + color: var(--canon-fg-secondary); + } + + &:focus { + border-color: var(--canon-border-hover); + } + + &:disabled { + opacity: .6; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItems { + padding-top: var(--canon-space-2); + outline: none; + flex-direction: column; + display: flex; + overflow-y: auto; +} + +.canon-SubmenuComboboxNoResults { + padding: var(--canon-space-3); + padding-left: var(--canon-space-5); + color: var(--canon-fg-secondary); + font-size: var(--canon-font-size-3); +} + +.canon-SubmenuComboboxItem { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + text-decoration: none; + display: flex; + + &[data-highlighted] { + background-color: var(--canon-gray-3); + } + + &[data-disabled] { + opacity: .5; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItemCheckbox { + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + background: var(--canon-bg-surface-1); + flex-shrink: 0; + justify-content: center; + align-items: center; + display: flex; +} + +.canon-SubmenuComboboxItemLabel { + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + overflow: hidden; +} + .canon-Link { font-family: var(--canon-font-regular); color: var(--canon-fg-link); diff --git a/packages/canon/src/components/Menu/Combobox.tsx b/packages/canon/src/components/Menu/Combobox.tsx new file mode 100644 index 0000000000..8f2955f5e6 --- /dev/null +++ b/packages/canon/src/components/Menu/Combobox.tsx @@ -0,0 +1,246 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + forwardRef, + useState, + useMemo, + useCallback, + useId, + ChangeEvent, + KeyboardEvent, + useRef, + useEffect, +} from 'react'; +import clsx from 'clsx'; +import { ComboboxOption, ComboboxProps } from './types'; +import { Icon } from '@backstage/canon'; + +const getListboxItemId = (listboxId: string, optionValue: string): string => + `${listboxId}-option-${optionValue}`; + +// Internal component for rendering individual items +function ComboboxItem({ + option, + optionIndex, + value, + activeOptionIndex, + onItemActive, + onItemSelect, + listboxId, +}: { + option: ComboboxOption; + optionIndex: number; + value?: string[]; + activeOptionIndex: number; + onItemActive: (index: number) => void; + onItemSelect: (value: string) => void; + listboxId: string; +}) { + const isSelected = value?.includes(option.value) ?? false; + const isHighlighted = optionIndex === activeOptionIndex; + const itemId = getListboxItemId(listboxId, option.value); + + const itemRef = useRef(null); + + // Scroll the item into view when it becomes highlighted + useEffect(() => { + if (isHighlighted && itemRef.current) { + itemRef.current.scrollIntoView({ block: 'nearest' }); + } + }, [isHighlighted]); + + return ( +
!option.disabled && onItemActive(optionIndex)} + onClick={() => !option.disabled && onItemSelect(option.value)} + > +
+ {isSelected &&
+
{option.label}
+
+ ); +} + +/** @public */ +export const Combobox = forwardRef( + (props, ref) => { + const { + options, + value, + onValueChange, + multiselect = false, + className, + ...rest + } = props; + + const triggerId = useId(); + const listboxId = `${triggerId}-listbox`; + + // State management + const [filterString, setFilterString] = useState(''); + const [activeOptionIndex, setActiveOptionIndex] = useState(0); + + // Filter options based on input + const filteredOptions = useMemo(() => { + if (!filterString) return options; + const lowerFilterString = filterString.toLocaleLowerCase('en-US'); + return options.filter(option => + option.label.toLocaleLowerCase('en-US').includes(lowerFilterString), + ); + }, [filterString, options]); + + // Get the active descendant ID for accessibility + const activeDescendantId = + activeOptionIndex >= 0 && filteredOptions.length > 0 + ? getListboxItemId(listboxId, filteredOptions[activeOptionIndex].value) + : undefined; + + const handleValueChange = useCallback( + (toggledValue: string) => { + let newValue: string[]; + if (multiselect) { + newValue = value?.includes(toggledValue) + ? value.filter(v => v !== toggledValue) + : [...(value ?? []), toggledValue]; + } else { + newValue = value?.includes(toggledValue) ? [] : [toggledValue]; + } + + onValueChange?.(newValue); + }, + [multiselect, onValueChange, value], + ); + + const handleSearchChange = useCallback( + (e: ChangeEvent) => { + setFilterString(e.target.value); + setActiveOptionIndex(0); + e.preventDefault(); + }, + [], + ); + + const handleKeyDown = useCallback( + (e: KeyboardEvent) => { + let wasEscapeKey = false; + switch (e.key) { + case 'ArrowDown': + e.preventDefault(); + setActiveOptionIndex(prev => + Math.min(prev + 1, filteredOptions.length - 1), + ); + break; + case 'ArrowUp': + e.preventDefault(); + setActiveOptionIndex(prev => Math.max(prev - 1, 0)); + break; + case 'Home': + e.preventDefault(); + setActiveOptionIndex(0); + break; + case 'End': + e.preventDefault(); + setActiveOptionIndex(Math.max(filteredOptions.length - 1, 0)); + break; + case 'Enter': + e.preventDefault(); + if ( + activeOptionIndex >= 0 && + !filteredOptions[activeOptionIndex].disabled + ) { + handleValueChange(filteredOptions[activeOptionIndex].value); + } + break; + case 'Escape': + // The Menu component should handle this + wasEscapeKey = true; + break; + default: + break; + } + + if (!wasEscapeKey) { + // Stop propagation so Menu components don't prevent the input from updating + e.stopPropagation(); + } + }, + [filteredOptions, activeOptionIndex, handleValueChange], + ); + + return ( +
+ + +
+ {filteredOptions.length === 0 ? ( +
+ No results found +
+ ) : ( + filteredOptions.map((option, index) => ( + + )) + )} +
+
+ ); + }, +); +Combobox.displayName = 'Combobox'; diff --git a/packages/canon/src/components/Menu/Menu.stories.tsx b/packages/canon/src/components/Menu/Menu.stories.tsx index 5d04a2f19c..a41faffc19 100644 --- a/packages/canon/src/components/Menu/Menu.stories.tsx +++ b/packages/canon/src/components/Menu/Menu.stories.tsx @@ -16,8 +16,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Menu } from './Menu'; -import { Button } from '../Button'; -import { Icon } from '../Icon'; +import { Text, Icon, Button } from '../../index'; +import { useState } from 'react'; const meta = { title: 'Components/Menu', @@ -27,6 +27,18 @@ const meta = { export default meta; type Story = StoryObj; +const options = [ + { label: 'Apple', value: 'apple' }, + { label: 'Banana', value: 'banana' }, + { label: 'Blueberry', value: 'blueberry' }, + { label: 'Cherry', value: 'cherry' }, + { label: 'Durian', value: 'durian' }, + { label: 'Elderberry', value: 'elderberry' }, + { label: 'Fig', value: 'fig' }, + { label: 'Grape', value: 'grape' }, + { label: 'Honeydew', value: 'honeydew' }, +]; + export const Default: Story = { args: { children: ( @@ -35,7 +47,7 @@ export const Default: Story = { render={props => ( + )} + /> + + + + Settings + Invite new members + Download app + Log out + + Submenu + + + + Submenu Item 1 + Submenu Item 2 + Submenu Item 3 + + + + + + + + + ), + }, +}; + +export const SubmenuCombobox = () => { + const [selectedValues, setSelectedValues] = useState([]); + + return ( + <> + + {selectedValues.length === 0 + ? 'Which is your favorite fruit?' + : `Yum, ${selectedValues[0]} is delicious!`} + + + ( + + )} + /> + + + + Regular Item + + Fruits + + + + + + + + + Another Item + + + + + + ); +}; + +export const SubmenuComboboxMultiselect = () => { + const [selectedValues, setSelectedValues] = useState([]); + + return ( + <> + + {selectedValues.length === 0 + ? 'Tell us what fruits you like.' + : `${selectedValues.join( + ', ', + )} would make for a great, healthy smoothy!`} + + + ( + + )} + /> + + + + Regular Item + + Fruits + + + + + + + + + Another Item + + + + + + ); +}; diff --git a/packages/canon/src/components/Menu/Menu.styles.css b/packages/canon/src/components/Menu/Menu.styles.css index 403d34294e..27e60708aa 100644 --- a/packages/canon/src/components/Menu/Menu.styles.css +++ b/packages/canon/src/components/Menu/Menu.styles.css @@ -3,15 +3,18 @@ } .canon-MenuPopup { - padding: var(--canon-space-2); + padding: var(--canon-space-1) 0; + display: flex; + flex-direction: column; border-radius: 0.375rem; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); outline: none; - overflow: hidden; + overflow: auto; transform-origin: var(--transform-origin); - max-width: 340px; + max-width: min(var(--available-width), 340px); + max-height: min(var(--available-height), 500px); transition: transform 150ms, opacity 150ms; &[data-starting-style], @@ -23,25 +26,51 @@ .canon-MenuItem { outline: 0; - cursor: default; user-select: none; display: flex; + height: 32px; + align-items: center; gap: var(--canon-space-2); color: var(--canon-fg-primary); text-decoration: none; border-radius: var(--canon-radius-2); - padding: var(--canon-space-2) var(--canon-space-2); - padding-right: var(--canon-space-4); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); cursor: pointer; - &:last-child { - border-bottom: none; + &[data-highlighted] { + background-color: var(--canon-gray-3); + } +} + +.canon-MenuSubmenuTrigger { + outline: 0; + user-select: none; + display: flex; + height: 32px; + align-items: center; + justify-content: space-between; + gap: var(--canon-space-2); + color: var(--canon-fg-primary); + text-decoration: none; + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + + & .canon-Icon { + color: var(--canon-fg-secondary); } + &[data-popup-open], &[data-highlighted] { - z-index: 0; - position: relative; - background-color: var(--canon-bg-tint-hover); + background-color: var(--canon-gray-3); + + .canon-Icon { + color: var(--canon-fg-primary); + } } } @@ -50,3 +79,88 @@ height: 1px; background-color: var(--color-gray-200); } + +.canon-SubmenuComboboxSearch { + padding: var(--canon-space-2) var(--canon-space-5); + border: none; + border-bottom: 1px solid var(--canon-border); + background-color: var(--canon-bg-surface-1); + color: var(--canon-fg-primary); + line-height: 140%; + outline: none; + + &::placeholder { + color: var(--canon-fg-secondary); + } + + &:focus { + border-color: var(--canon-border-hover); + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItems { + overflow-y: auto; + display: flex; + flex-direction: column; + padding-top: var(--canon-space-2); + outline: none; +} + +.canon-SubmenuComboboxNoResults { + padding: var(--canon-space-3); + padding-left: var(--canon-space-5); + color: var(--canon-fg-secondary); + font-size: var(--canon-font-size-3); +} + +.canon-SubmenuComboboxItem { + outline: 0; + user-select: none; + display: flex; + height: 32px; + align-items: center; + justify-content: space-between; + gap: var(--canon-space-2); + color: var(--canon-fg-primary); + text-decoration: none; + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + user-select: none; + + &[data-highlighted] { + background-color: var(--canon-gray-3); + } + + &[data-disabled] { + opacity: 0.5; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItemCheckbox { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + flex-shrink: 0; + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + background: var(--canon-bg-surface-1); +} + +.canon-SubmenuComboboxItemLabel { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/packages/canon/src/components/Menu/Menu.tsx b/packages/canon/src/components/Menu/Menu.tsx index 6b93d14865..123b01b283 100644 --- a/packages/canon/src/components/Menu/Menu.tsx +++ b/packages/canon/src/components/Menu/Menu.tsx @@ -18,6 +18,8 @@ import { forwardRef } from 'react'; import { Menu as MenuPrimitive } from '@base-ui-components/react/menu'; import clsx from 'clsx'; import { MenuComponent } from './types'; +import { Combobox } from './Combobox'; +import { Icon } from '../Icon'; const MenuTrigger = forwardRef< React.ElementRef, @@ -180,12 +182,15 @@ MenuCheckboxItemIndicator.displayName = const MenuSubmenuTrigger = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +>(({ className, children, ...props }, ref) => ( + > +
{children}
+ +
)); MenuSubmenuTrigger.displayName = MenuPrimitive.SubmenuTrigger.displayName; @@ -220,4 +225,5 @@ export const Menu: MenuComponent = { CheckboxItemIndicator: MenuCheckboxItemIndicator, SubmenuTrigger: MenuSubmenuTrigger, Separator: MenuSeparator, + Combobox, }; diff --git a/packages/canon/src/components/Menu/types.ts b/packages/canon/src/components/Menu/types.ts index 63f8069f61..7bc4fa47aa 100644 --- a/packages/canon/src/components/Menu/types.ts +++ b/packages/canon/src/components/Menu/types.ts @@ -13,7 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Menu as MenuPrimitive } from '@base-ui-components/react/menu'; +import { + ForwardRefExoticComponent, + RefAttributes, + ComponentProps, +} from 'react'; /** @public */ export type MenuComponent = { @@ -34,4 +40,23 @@ export type MenuComponent = { CheckboxItemIndicator: typeof MenuPrimitive.CheckboxItemIndicator; SubmenuTrigger: typeof MenuPrimitive.SubmenuTrigger; Separator: typeof MenuPrimitive.Separator; + Combobox: ForwardRefExoticComponent< + ComboboxProps & RefAttributes + >; }; + +/** @public */ +export type ComboboxOption = { + label: string; + value: string; + disabled?: boolean; +}; + +/** @public */ +export interface ComboboxProps extends ComponentProps<'div'> { + options: ComboboxOption[]; + value?: string[]; + onValueChange?: (value: string[]) => void; + multiselect?: boolean; + closeParentOnEsc?: boolean; +} From 4551fb753076f8a3e39aad51a7856a1322ce9238 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 16:45:30 +0100 Subject: [PATCH 129/143] Improve report + naming Signed-off-by: Charles de Dreuille --- .changeset/upset-papayas-flash.md | 5 +++ packages/canon/report.api.md | 25 ++++++++++++++ .../canon/src/components/Menu/Combobox.tsx | 6 ++-- packages/canon/src/components/Menu/types.ts | 34 +++++++++---------- 4 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 .changeset/upset-papayas-flash.md diff --git a/.changeset/upset-papayas-flash.md b/.changeset/upset-papayas-flash.md new file mode 100644 index 0000000000..fae7347e0d --- /dev/null +++ b/.changeset/upset-papayas-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Update Menu component in Canon to make the UI more condensed. We are also adding a new Combobox option for nested navigation. diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index cbbdd4db33..87d6e11f6e 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -7,6 +7,7 @@ import { Avatar as Avatar_2 } from '@base-ui-components/react/avatar'; import { Breakpoint as Breakpoint_2 } from '@backstage/canon'; import { ChangeEvent } from 'react'; import { Collapsible as Collapsible_2 } from '@base-ui-components/react/collapsible'; +import { ComponentProps } from 'react'; import { Context } from 'react'; import type { CSSProperties } from 'react'; import { FC } from 'react'; @@ -891,6 +892,27 @@ export type MarginProps = GetPropDefTypes; // @public (undocumented) export const Menu: MenuComponent; +// @public (undocumented) +export type MenuComboboxOption = { + label: string; + value: string; + disabled?: boolean; +}; + +// @public (undocumented) +export interface MenuComboboxProps extends ComponentProps<'div'> { + // (undocumented) + closeParentOnEsc?: boolean; + // (undocumented) + multiselect?: boolean; + // (undocumented) + onValueChange?: (value: string[]) => void; + // (undocumented) + options: MenuComboboxOption[]; + // (undocumented) + value?: string[]; +} + // @public (undocumented) export type MenuComponent = { Root: typeof Menu_2.Root; @@ -910,6 +932,9 @@ export type MenuComponent = { CheckboxItemIndicator: typeof Menu_2.CheckboxItemIndicator; SubmenuTrigger: typeof Menu_2.SubmenuTrigger; Separator: typeof Menu_2.Separator; + Combobox: ForwardRefExoticComponent< + MenuComboboxProps & RefAttributes + >; }; // @public (undocumented) diff --git a/packages/canon/src/components/Menu/Combobox.tsx b/packages/canon/src/components/Menu/Combobox.tsx index 8f2955f5e6..7d683c4718 100644 --- a/packages/canon/src/components/Menu/Combobox.tsx +++ b/packages/canon/src/components/Menu/Combobox.tsx @@ -26,7 +26,7 @@ import { useEffect, } from 'react'; import clsx from 'clsx'; -import { ComboboxOption, ComboboxProps } from './types'; +import { MenuComboboxOption, MenuComboboxProps } from './types'; import { Icon } from '@backstage/canon'; const getListboxItemId = (listboxId: string, optionValue: string): string => @@ -42,7 +42,7 @@ function ComboboxItem({ onItemSelect, listboxId, }: { - option: ComboboxOption; + option: MenuComboboxOption; optionIndex: number; value?: string[]; activeOptionIndex: number; @@ -85,7 +85,7 @@ function ComboboxItem({ } /** @public */ -export const Combobox = forwardRef( +export const Combobox = forwardRef( (props, ref) => { const { options, diff --git a/packages/canon/src/components/Menu/types.ts b/packages/canon/src/components/Menu/types.ts index 7bc4fa47aa..9071f9a921 100644 --- a/packages/canon/src/components/Menu/types.ts +++ b/packages/canon/src/components/Menu/types.ts @@ -21,6 +21,22 @@ import { ComponentProps, } from 'react'; +/** @public */ +export type MenuComboboxOption = { + label: string; + value: string; + disabled?: boolean; +}; + +/** @public */ +export interface MenuComboboxProps extends ComponentProps<'div'> { + options: MenuComboboxOption[]; + value?: string[]; + onValueChange?: (value: string[]) => void; + multiselect?: boolean; + closeParentOnEsc?: boolean; +} + /** @public */ export type MenuComponent = { Root: typeof MenuPrimitive.Root; @@ -41,22 +57,6 @@ export type MenuComponent = { SubmenuTrigger: typeof MenuPrimitive.SubmenuTrigger; Separator: typeof MenuPrimitive.Separator; Combobox: ForwardRefExoticComponent< - ComboboxProps & RefAttributes + MenuComboboxProps & RefAttributes >; }; - -/** @public */ -export type ComboboxOption = { - label: string; - value: string; - disabled?: boolean; -}; - -/** @public */ -export interface ComboboxProps extends ComponentProps<'div'> { - options: ComboboxOption[]; - value?: string[]; - onValueChange?: (value: string[]) => void; - multiselect?: boolean; - closeParentOnEsc?: boolean; -} From ea4628d64d9dc9a5e2980c3eaadaa07f5d6c6a8f Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 17:20:49 +0100 Subject: [PATCH 130/143] Fix some styling Signed-off-by: Charles de Dreuille --- .../canon/src/components/Menu/Combobox.tsx | 3 +- .../canon/src/components/Menu/Menu.styles.css | 29 ++++++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/canon/src/components/Menu/Combobox.tsx b/packages/canon/src/components/Menu/Combobox.tsx index 7d683c4718..c9593ed2a4 100644 --- a/packages/canon/src/components/Menu/Combobox.tsx +++ b/packages/canon/src/components/Menu/Combobox.tsx @@ -201,7 +201,7 @@ export const Combobox = forwardRef( className="canon-SubmenuComboboxSearch" type="text" role="combobox" - placeholder="Filter" + placeholder="Filter..." aria-labelledby={triggerId} aria-controls={listboxId} aria-autocomplete="list" @@ -212,7 +212,6 @@ export const Combobox = forwardRef( onKeyDown={handleKeyDown} onChange={handleSearchChange} /> -
Date: Fri, 16 May 2025 17:32:44 +0100 Subject: [PATCH 131/143] Build CSS Signed-off-by: Charles de Dreuille --- packages/canon/css/components.css | 31 ++++++++++++++++++++++--------- packages/canon/css/menu.css | 31 ++++++++++++++++++++++--------- packages/canon/css/styles.css | 31 ++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index cd0809dadb..3ef8175c46 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -683,7 +683,6 @@ } .canon-MenuPopup { - padding: var(--canon-space-1) 0; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); @@ -695,6 +694,7 @@ flex-direction: column; transition: transform .15s, opacity .15s; display: flex; + position: relative; overflow: auto; &[data-starting-style], &[data-ending-style] { @@ -715,9 +715,18 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; + &:first-child { + margin-top: var(--canon-space-1); + } + + &:last-child { + margin-bottom: var(--canon-space-1); + } + &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -736,6 +745,7 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; @@ -759,22 +769,23 @@ } .canon-SubmenuComboboxSearch { - padding: var(--canon-space-2) var(--canon-space-5); + padding-inline: var(--canon-space-3); border: none; border-bottom: 1px solid var(--canon-border); background-color: var(--canon-bg-surface-1); + height: 32px; color: var(--canon-fg-primary); - outline: none; line-height: 140%; + font-size: var(--canon-font-size-3); + z-index: 1; + outline: none; + position: sticky; + top: 0; &::placeholder { color: var(--canon-fg-secondary); } - &:focus { - border-color: var(--canon-border-hover); - } - &:disabled { opacity: .6; cursor: not-allowed; @@ -790,8 +801,9 @@ } .canon-SubmenuComboboxNoResults { - padding: var(--canon-space-3); - padding-left: var(--canon-space-5); + padding-inline: var(--canon-space-3); + padding-top: var(--canon-space-2); + padding-bottom: var(--canon-space-4); color: var(--canon-fg-secondary); font-size: var(--canon-font-size-3); } @@ -809,6 +821,7 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; diff --git a/packages/canon/css/menu.css b/packages/canon/css/menu.css index d901273cb3..7671217198 100644 --- a/packages/canon/css/menu.css +++ b/packages/canon/css/menu.css @@ -3,7 +3,6 @@ } .canon-MenuPopup { - padding: var(--canon-space-1) 0; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); @@ -15,6 +14,7 @@ flex-direction: column; transition: transform .15s, opacity .15s; display: flex; + position: relative; overflow: auto; &[data-starting-style], &[data-ending-style] { @@ -35,9 +35,18 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; + &:first-child { + margin-top: var(--canon-space-1); + } + + &:last-child { + margin-bottom: var(--canon-space-1); + } + &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -56,6 +65,7 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; @@ -79,22 +89,23 @@ } .canon-SubmenuComboboxSearch { - padding: var(--canon-space-2) var(--canon-space-5); + padding-inline: var(--canon-space-3); border: none; border-bottom: 1px solid var(--canon-border); background-color: var(--canon-bg-surface-1); + height: 32px; color: var(--canon-fg-primary); - outline: none; line-height: 140%; + font-size: var(--canon-font-size-3); + z-index: 1; + outline: none; + position: sticky; + top: 0; &::placeholder { color: var(--canon-fg-secondary); } - &:focus { - border-color: var(--canon-border-hover); - } - &:disabled { opacity: .6; cursor: not-allowed; @@ -110,8 +121,9 @@ } .canon-SubmenuComboboxNoResults { - padding: var(--canon-space-3); - padding-left: var(--canon-space-5); + padding-inline: var(--canon-space-3); + padding-top: var(--canon-space-2); + padding-bottom: var(--canon-space-4); color: var(--canon-fg-secondary); font-size: var(--canon-font-size-3); } @@ -129,6 +141,7 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 08aaa80970..07bac6155c 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9907,7 +9907,6 @@ } .canon-MenuPopup { - padding: var(--canon-space-1) 0; background-color: var(--canon-bg-surface-1); border: 1px solid var(--canon-border); color: var(--canon-fg-primary); @@ -9919,6 +9918,7 @@ flex-direction: column; transition: transform .15s, opacity .15s; display: flex; + position: relative; overflow: auto; &[data-starting-style], &[data-ending-style] { @@ -9939,9 +9939,18 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; + &:first-child { + margin-top: var(--canon-space-1); + } + + &:last-child { + margin-bottom: var(--canon-space-1); + } + &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -9960,6 +9969,7 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; @@ -9983,22 +9993,23 @@ } .canon-SubmenuComboboxSearch { - padding: var(--canon-space-2) var(--canon-space-5); + padding-inline: var(--canon-space-3); border: none; border-bottom: 1px solid var(--canon-border); background-color: var(--canon-bg-surface-1); + height: 32px; color: var(--canon-fg-primary); - outline: none; line-height: 140%; + font-size: var(--canon-font-size-3); + z-index: 1; + outline: none; + position: sticky; + top: 0; &::placeholder { color: var(--canon-fg-secondary); } - &:focus { - border-color: var(--canon-border-hover); - } - &:disabled { opacity: .6; cursor: not-allowed; @@ -10014,8 +10025,9 @@ } .canon-SubmenuComboboxNoResults { - padding: var(--canon-space-3); - padding-left: var(--canon-space-5); + padding-inline: var(--canon-space-3); + padding-top: var(--canon-space-2); + padding-bottom: var(--canon-space-4); color: var(--canon-fg-secondary); font-size: var(--canon-font-size-3); } @@ -10033,6 +10045,7 @@ font-size: var(--canon-font-size-3); cursor: pointer; outline: 0; + flex-shrink: 0; text-decoration: none; display: flex; From 1ea1db0bd6dc9826d510f931a3ccbb43cc4ac3bf Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 17:51:10 +0100 Subject: [PATCH 132/143] Add truncate prop to Text and Heading Signed-off-by: Charles de Dreuille --- .changeset/witty-weeks-boil.md | 5 +++++ packages/canon/css/components.css | 12 ++++++++++++ packages/canon/css/heading.css | 6 ++++++ packages/canon/css/styles.css | 12 ++++++++++++ packages/canon/css/text.css | 6 ++++++ packages/canon/report.api.md | 4 ++++ .../canon/src/components/Heading/Heading.stories.tsx | 8 ++++++++ packages/canon/src/components/Heading/Heading.tsx | 2 ++ packages/canon/src/components/Heading/styles.css | 6 ++++++ packages/canon/src/components/Heading/types.ts | 1 + packages/canon/src/components/Text/Text.stories.tsx | 7 +++++++ packages/canon/src/components/Text/Text.tsx | 2 ++ packages/canon/src/components/Text/styles.css | 6 ++++++ packages/canon/src/components/Text/types.ts | 1 + 14 files changed, 78 insertions(+) create mode 100644 .changeset/witty-weeks-boil.md diff --git a/.changeset/witty-weeks-boil.md b/.changeset/witty-weeks-boil.md new file mode 100644 index 0000000000..0e49315962 --- /dev/null +++ b/.changeset/witty-weeks-boil.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Add new truncate prop to Text and Heading components in Canon. diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index d479444df9..23133c9966 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -403,6 +403,12 @@ color: var(--canon-fg-success); } +.canon-Text[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + .canon-Heading { font-family: var(--canon-font-regular); color: var(--canon-fg-primary); @@ -441,6 +447,12 @@ font-weight: var(--canon-font-weight-bold); } +.canon-Heading[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + .canon-IconButton { user-select: none; font-family: var(--canon-font-regular); diff --git a/packages/canon/css/heading.css b/packages/canon/css/heading.css index f1bea873b4..53e8d8f25a 100644 --- a/packages/canon/css/heading.css +++ b/packages/canon/css/heading.css @@ -35,3 +35,9 @@ font-size: var(--canon-font-size-5); font-weight: var(--canon-font-weight-bold); } + +.canon-Heading[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 6c53aaa198..42d47267f8 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9627,6 +9627,12 @@ color: var(--canon-fg-success); } +.canon-Text[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + .canon-Heading { font-family: var(--canon-font-regular); color: var(--canon-fg-primary); @@ -9665,6 +9671,12 @@ font-weight: var(--canon-font-weight-bold); } +.canon-Heading[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + .canon-IconButton { user-select: none; font-family: var(--canon-font-regular); diff --git a/packages/canon/css/text.css b/packages/canon/css/text.css index 523574f779..c4f9671816 100644 --- a/packages/canon/css/text.css +++ b/packages/canon/css/text.css @@ -51,3 +51,9 @@ .canon-Text[data-color="success"] { color: var(--canon-fg-success); } + +.canon-Text[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index cbbdd4db33..ecfdfde188 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -627,6 +627,8 @@ export interface HeadingProps { // (undocumented) style?: React.CSSProperties; // (undocumented) + truncate?: boolean; + // (undocumented) variant?: | 'display' | 'title1' @@ -1250,6 +1252,8 @@ export interface TextProps { // (undocumented) style?: CSSProperties; // (undocumented) + truncate?: boolean; + // (undocumented) variant?: | 'subtitle' | 'body' diff --git a/packages/canon/src/components/Heading/Heading.stories.tsx b/packages/canon/src/components/Heading/Heading.stories.tsx index 1fbc882d5d..59ac1aab91 100644 --- a/packages/canon/src/components/Heading/Heading.stories.tsx +++ b/packages/canon/src/components/Heading/Heading.stories.tsx @@ -50,6 +50,14 @@ export const AllVariants: Story = { ), }; +export const Truncate: Story = { + args: { + ...Title1.args, + truncate: true, + style: { maxWidth: '400px' }, + }, +}; + export const Responsive: Story = { args: { variant: { diff --git a/packages/canon/src/components/Heading/Heading.tsx b/packages/canon/src/components/Heading/Heading.tsx index 994b1de06e..b7f99cd102 100644 --- a/packages/canon/src/components/Heading/Heading.tsx +++ b/packages/canon/src/components/Heading/Heading.tsx @@ -27,6 +27,7 @@ export const Heading = forwardRef( children, variant = 'title1', as = 'h1', + truncate, className, ...restProps } = props; @@ -47,6 +48,7 @@ export const Heading = forwardRef( ref={ref} className={clsx('canon-Heading', className)} data-variant={responsiveVariant} + data-truncate={truncate} {...restProps} > {children} diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css index c85bbca135..f0f4561400 100644 --- a/packages/canon/src/components/Heading/styles.css +++ b/packages/canon/src/components/Heading/styles.css @@ -51,3 +51,9 @@ font-size: var(--canon-font-size-5); font-weight: var(--canon-font-weight-bold); } + +.canon-Heading[data-truncate] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/packages/canon/src/components/Heading/types.ts b/packages/canon/src/components/Heading/types.ts index 6250e8d2eb..b87f16eb34 100644 --- a/packages/canon/src/components/Heading/types.ts +++ b/packages/canon/src/components/Heading/types.ts @@ -33,6 +33,7 @@ export interface HeadingProps { > >; as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + truncate?: boolean; className?: string; style?: React.CSSProperties; } diff --git a/packages/canon/src/components/Text/Text.stories.tsx b/packages/canon/src/components/Text/Text.stories.tsx index 0b0ffd2712..ba1155daed 100644 --- a/packages/canon/src/components/Text/Text.stories.tsx +++ b/packages/canon/src/components/Text/Text.stories.tsx @@ -78,6 +78,13 @@ export const AllColors: Story = { ), }; +export const Truncate: Story = { + args: { + ...Default.args, + truncate: true, + }, +}; + export const Responsive: Story = { args: { ...Default.args, diff --git a/packages/canon/src/components/Text/Text.tsx b/packages/canon/src/components/Text/Text.tsx index 76f5adbb43..90cc9bb2ac 100644 --- a/packages/canon/src/components/Text/Text.tsx +++ b/packages/canon/src/components/Text/Text.tsx @@ -30,6 +30,7 @@ export const Text = forwardRef( color = 'primary', style, className, + truncate, ...restProps } = props; @@ -45,6 +46,7 @@ export const Text = forwardRef( data-variant={responsiveVariant} data-weight={responsiveWeight} data-color={responsiveColor} + data-truncate={truncate} style={style} {...restProps} > diff --git a/packages/canon/src/components/Text/styles.css b/packages/canon/src/components/Text/styles.css index 9f0ed703d9..c0cd781007 100644 --- a/packages/canon/src/components/Text/styles.css +++ b/packages/canon/src/components/Text/styles.css @@ -67,3 +67,9 @@ .canon-Text[data-color='success'] { color: var(--canon-fg-success); } + +.canon-Text[data-truncate] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/packages/canon/src/components/Text/types.ts b/packages/canon/src/components/Text/types.ts index d4f1615694..7adafd73d7 100644 --- a/packages/canon/src/components/Text/types.ts +++ b/packages/canon/src/components/Text/types.ts @@ -39,6 +39,7 @@ export interface TextProps { 'primary' | 'secondary' | 'danger' | 'warning' | 'success' > >; + truncate?: boolean; className?: string; style?: CSSProperties; } From 08d62624df4efacecd1f2e731b53ae2ee76df0e9 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 18:02:15 +0100 Subject: [PATCH 133/143] Improve docs Signed-off-by: Charles de Dreuille --- .../src/app/(docs)/components/heading/page.mdx | 16 ++++++++++++++++ .../src/app/(docs)/components/heading/props.ts | 4 ++++ .../src/app/(docs)/components/text/page.mdx | 15 +++++++++++++++ .../src/app/(docs)/components/text/props.ts | 4 ++++ 4 files changed, 39 insertions(+) diff --git a/canon-docs/src/app/(docs)/components/heading/page.mdx b/canon-docs/src/app/(docs)/components/heading/page.mdx index 10fd60bef1..e09bae9945 100644 --- a/canon-docs/src/app/(docs)/components/heading/page.mdx +++ b/canon-docs/src/app/(docs)/components/heading/page.mdx @@ -62,6 +62,22 @@ appearance of the heading. `} /> +### Truncate + +The `Heading` component has a `truncate` prop that can be used to truncate the +heading. + +} + code={` + A man looks at a painting in a museum and says, “Brothers and sisters I + have none, but that man's father is my father's son.” Who is + in the painting? + `} +/> + ### Responsive You can also use the `variant` prop to change the appearance of the text based diff --git a/canon-docs/src/app/(docs)/components/heading/props.ts b/canon-docs/src/app/(docs)/components/heading/props.ts index a3dd3288ff..6d62d2dee1 100644 --- a/canon-docs/src/app/(docs)/components/heading/props.ts +++ b/canon-docs/src/app/(docs)/components/heading/props.ts @@ -12,6 +12,10 @@ export const headingPropDefs: Record = { values: ['ReactNode'], responsive: false, }, + truncate: { + type: 'boolean', + default: 'false', + }, ...classNamePropDefs, ...stylePropDefs, }; diff --git a/canon-docs/src/app/(docs)/components/text/page.mdx b/canon-docs/src/app/(docs)/components/text/page.mdx index 70d5de5504..85a783f4f3 100644 --- a/canon-docs/src/app/(docs)/components/text/page.mdx +++ b/canon-docs/src/app/(docs)/components/text/page.mdx @@ -102,6 +102,21 @@ appearance of the text. `} /> +### Truncate + +The `Text` component has a `truncate` prop that can be used to truncate the +text. + +} + code={` + A man looks at a painting in a museum and says, “Brothers and sisters I + have none, but that man's father is my father's son.” Who is + in the painting? + `} +/> + ### Responsive You can also use the `variant` prop to change the appearance of the text based diff --git a/canon-docs/src/app/(docs)/components/text/props.ts b/canon-docs/src/app/(docs)/components/text/props.ts index 53413dc9e7..76c229af58 100644 --- a/canon-docs/src/app/(docs)/components/text/props.ts +++ b/canon-docs/src/app/(docs)/components/text/props.ts @@ -16,6 +16,10 @@ export const textPropDefs: Record = { values: ['regular', 'bold'], responsive: true, }, + truncate: { + type: 'boolean', + default: 'false', + }, ...childrenPropDefs, ...classNamePropDefs, ...stylePropDefs, From 384a4892abb560059d7cdc450db1b6343b8f00b9 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 18:27:15 +0100 Subject: [PATCH 134/143] Improve docs Signed-off-by: Charles de Dreuille --- .../src/app/(docs)/components/menu/page.mdx | 45 +++++++++++++++++++ packages/canon/css/components.css | 9 ++-- packages/canon/css/menu.css | 9 ++-- packages/canon/css/styles.css | 9 ++-- .../src/components/Menu/Menu.stories.tsx | 10 ++--- .../canon/src/components/Menu/Menu.styles.css | 9 ++-- 6 files changed, 70 insertions(+), 21 deletions(-) diff --git a/canon-docs/src/app/(docs)/components/menu/page.mdx b/canon-docs/src/app/(docs)/components/menu/page.mdx index 98c4949438..524db26cd1 100644 --- a/canon-docs/src/app/(docs)/components/menu/page.mdx +++ b/canon-docs/src/app/(docs)/components/menu/page.mdx @@ -155,3 +155,48 @@ You can additionally configure how quickly the menu opens on hover using the `de `} /> + +### Nested navigation + +You can nest menus to create a more complex navigation structure. + +} + code={` ( + + )} + /> + + + + Settings + Invite new members + Download app + Log out + + Submenu + + + + Submenu Item 1 + Submenu Item 2 + Submenu Item 3 + + + + + + + `} +/> diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 23f1b69728..124d575a96 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -701,6 +701,7 @@ transform-origin: var(--transform-origin); max-width: min(var(--available-width), 340px); max-height: min(var(--available-height), 500px); + padding-bottom: var(--canon-space-1); border-radius: .375rem; outline: none; flex-direction: column; @@ -735,10 +736,6 @@ margin-top: var(--canon-space-1); } - &:last-child { - margin-bottom: var(--canon-space-1); - } - &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -765,6 +762,10 @@ color: var(--canon-fg-secondary); } + &:first-child { + margin-top: var(--canon-space-1); + } + &[data-popup-open], &[data-highlighted] { background-color: var(--canon-gray-3); diff --git a/packages/canon/css/menu.css b/packages/canon/css/menu.css index 7671217198..4c9433275c 100644 --- a/packages/canon/css/menu.css +++ b/packages/canon/css/menu.css @@ -9,6 +9,7 @@ transform-origin: var(--transform-origin); max-width: min(var(--available-width), 340px); max-height: min(var(--available-height), 500px); + padding-bottom: var(--canon-space-1); border-radius: .375rem; outline: none; flex-direction: column; @@ -43,10 +44,6 @@ margin-top: var(--canon-space-1); } - &:last-child { - margin-bottom: var(--canon-space-1); - } - &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -73,6 +70,10 @@ color: var(--canon-fg-secondary); } + &:first-child { + margin-top: var(--canon-space-1); + } + &[data-popup-open], &[data-highlighted] { background-color: var(--canon-gray-3); diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index c441260aaa..084aef2855 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9925,6 +9925,7 @@ transform-origin: var(--transform-origin); max-width: min(var(--available-width), 340px); max-height: min(var(--available-height), 500px); + padding-bottom: var(--canon-space-1); border-radius: .375rem; outline: none; flex-direction: column; @@ -9959,10 +9960,6 @@ margin-top: var(--canon-space-1); } - &:last-child { - margin-bottom: var(--canon-space-1); - } - &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -9989,6 +9986,10 @@ color: var(--canon-fg-secondary); } + &:first-child { + margin-top: var(--canon-space-1); + } + &[data-popup-open], &[data-highlighted] { background-color: var(--canon-gray-3); diff --git a/packages/canon/src/components/Menu/Menu.stories.tsx b/packages/canon/src/components/Menu/Menu.stories.tsx index a41faffc19..578ce945ae 100644 --- a/packages/canon/src/components/Menu/Menu.stories.tsx +++ b/packages/canon/src/components/Menu/Menu.stories.tsx @@ -16,7 +16,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Menu } from './Menu'; -import { Text, Icon, Button } from '../../index'; +import { Text, Icon, Button, Flex } from '../../index'; import { useState } from 'react'; const meta = { @@ -131,7 +131,7 @@ export const SubmenuCombobox = () => { const [selectedValues, setSelectedValues] = useState([]); return ( - <> + {selectedValues.length === 0 ? 'Which is your favorite fruit?' @@ -173,7 +173,7 @@ export const SubmenuCombobox = () => { - + ); }; @@ -181,7 +181,7 @@ export const SubmenuComboboxMultiselect = () => { const [selectedValues, setSelectedValues] = useState([]); return ( - <> + {selectedValues.length === 0 ? 'Tell us what fruits you like.' @@ -226,6 +226,6 @@ export const SubmenuComboboxMultiselect = () => { - + ); }; diff --git a/packages/canon/src/components/Menu/Menu.styles.css b/packages/canon/src/components/Menu/Menu.styles.css index 4e2b473162..07d257f57f 100644 --- a/packages/canon/src/components/Menu/Menu.styles.css +++ b/packages/canon/src/components/Menu/Menu.styles.css @@ -16,6 +16,7 @@ max-height: min(var(--available-height), 500px); transition: transform 150ms, opacity 150ms; position: relative; + padding-bottom: var(--canon-space-1); &[data-starting-style], &[data-ending-style] { @@ -44,10 +45,6 @@ margin-top: var(--canon-space-1); } - &:last-child { - margin-bottom: var(--canon-space-1); - } - &[data-highlighted] { background-color: var(--canon-gray-3); } @@ -74,6 +71,10 @@ color: var(--canon-fg-secondary); } + &:first-child { + margin-top: var(--canon-space-1); + } + &[data-popup-open], &[data-highlighted] { background-color: var(--canon-gray-3); From ccb1fc68b6a0c248ff0da98db78b1f96e87b55c2 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 18:57:36 +0100 Subject: [PATCH 135/143] Improve the way we treat custom render on Text and Heading Signed-off-by: Charles de Dreuille --- .changeset/puny-garlics-bathe.md | 5 +++ packages/canon/css/components.css | 20 +++++++++ packages/canon/css/heading.css | 20 +++++++++ packages/canon/css/styles.css | 20 +++++++++ packages/canon/report.api.md | 29 ++++++++----- .../components/Heading/Heading.stories.tsx | 29 +++++++++---- .../canon/src/components/Heading/Heading.tsx | 41 ++++++++----------- .../canon/src/components/Heading/styles.css | 20 +++++++++ .../canon/src/components/Heading/types.ts | 18 ++++++-- .../src/components/Text/Text.stories.tsx | 7 ++++ packages/canon/src/components/Text/Text.tsx | 35 ++++++++-------- packages/canon/src/components/Text/types.ts | 7 ++-- 12 files changed, 188 insertions(+), 63 deletions(-) create mode 100644 .changeset/puny-garlics-bathe.md diff --git a/.changeset/puny-garlics-bathe.md b/.changeset/puny-garlics-bathe.md new file mode 100644 index 0000000000..97071ac2b7 --- /dev/null +++ b/.changeset/puny-garlics-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': minor +--- + +We are modifying the way we treat custom render using 'useRender()' under the hood from BaseUI. diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 23133c9966..496dd1303d 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -447,6 +447,26 @@ font-weight: var(--canon-font-weight-bold); } +.canon-Heading[data-color="primary"] { + color: var(--canon-fg-primary); +} + +.canon-Heading[data-color="secondary"] { + color: var(--canon-fg-secondary); +} + +.canon-Heading[data-color="danger"] { + color: var(--canon-fg-danger); +} + +.canon-Heading[data-color="warning"] { + color: var(--canon-fg-warning); +} + +.canon-Heading[data-color="success"] { + color: var(--canon-fg-success); +} + .canon-Heading[data-truncate] { text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/canon/css/heading.css b/packages/canon/css/heading.css index 53e8d8f25a..50e9d3503d 100644 --- a/packages/canon/css/heading.css +++ b/packages/canon/css/heading.css @@ -36,6 +36,26 @@ font-weight: var(--canon-font-weight-bold); } +.canon-Heading[data-color="primary"] { + color: var(--canon-fg-primary); +} + +.canon-Heading[data-color="secondary"] { + color: var(--canon-fg-secondary); +} + +.canon-Heading[data-color="danger"] { + color: var(--canon-fg-danger); +} + +.canon-Heading[data-color="warning"] { + color: var(--canon-fg-warning); +} + +.canon-Heading[data-color="success"] { + color: var(--canon-fg-success); +} + .canon-Heading[data-truncate] { text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 42d47267f8..aceb4e39db 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9671,6 +9671,26 @@ font-weight: var(--canon-font-weight-bold); } +.canon-Heading[data-color="primary"] { + color: var(--canon-fg-primary); +} + +.canon-Heading[data-color="secondary"] { + color: var(--canon-fg-secondary); +} + +.canon-Heading[data-color="danger"] { + color: var(--canon-fg-danger); +} + +.canon-Heading[data-color="warning"] { + color: var(--canon-fg-warning); +} + +.canon-Heading[data-color="success"] { + color: var(--canon-fg-success); +} + .canon-Heading[data-truncate] { text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index ecfdfde188..0ffa6052c2 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -613,18 +613,28 @@ export interface GridProps extends SpaceProps { // @public (undocumented) export const Heading: ForwardRefExoticComponent< - HeadingProps & RefAttributes + Omit & RefAttributes >; // @public (undocumented) -export interface HeadingProps { - // (undocumented) - as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; - // (undocumented) - children: React.ReactNode; +export interface HeadingProps + extends Omit, 'color'> { // (undocumented) className?: string; // (undocumented) + color?: + | 'primary' + | 'secondary' + | 'danger' + | 'warning' + | 'success' + | Partial< + Record< + Breakpoint, + 'primary' | 'secondary' | 'danger' | 'warning' | 'success' + > + >; + // (undocumented) style?: React.CSSProperties; // (undocumented) truncate?: boolean; @@ -1208,7 +1218,7 @@ export interface TableCellTextProps // @public (undocumented) const Text_2: ForwardRefExoticComponent< - TextProps & RefAttributes + Omit & RefAttributes >; export { Text_2 as Text }; @@ -1231,9 +1241,8 @@ export interface TextFieldProps } // @public (undocumented) -export interface TextProps { - // (undocumented) - children: ReactNode; +export interface TextProps + extends Omit, 'color'> { // (undocumented) className?: string; // (undocumented) diff --git a/packages/canon/src/components/Heading/Heading.stories.tsx b/packages/canon/src/components/Heading/Heading.stories.tsx index 59ac1aab91..aa9625ae03 100644 --- a/packages/canon/src/components/Heading/Heading.stories.tsx +++ b/packages/canon/src/components/Heading/Heading.stories.tsx @@ -50,6 +50,21 @@ export const AllVariants: Story = { ), }; +export const AllColors: Story = { + args: { + ...Default.args, + }, + render: args => ( + + + + + + + + ), +}; + export const Truncate: Story = { args: { ...Title1.args, @@ -67,13 +82,6 @@ export const Responsive: Story = { }, }; -export const CustomTag: Story = { - args: { - variant: 'title5', - as: 'h2', - }, -}; - export const WrappedInLink: Story = { args: { ...Default.args, @@ -87,6 +95,13 @@ export const WrappedInLink: Story = { ], }; +export const CustomRender: Story = { + args: { + ...Default.args, + render:

, + }, +}; + export const Playground: Story = { render: () => ( diff --git a/packages/canon/src/components/Heading/Heading.tsx b/packages/canon/src/components/Heading/Heading.tsx index b7f99cd102..6ea2fe006b 100644 --- a/packages/canon/src/components/Heading/Heading.tsx +++ b/packages/canon/src/components/Heading/Heading.tsx @@ -14,46 +14,41 @@ * limitations under the License. */ -import { forwardRef } from 'react'; +import { forwardRef, useRef } from 'react'; import clsx from 'clsx'; import { useResponsiveValue } from '../../hooks/useResponsiveValue'; - +import { useRender } from '@base-ui-components/react/use-render'; import type { HeadingProps } from './types'; /** @public */ export const Heading = forwardRef( (props, ref) => { const { - children, variant = 'title1', - as = 'h1', + color = 'primary', truncate, className, + render =

, ...restProps } = props; - // Get the responsive value for the variant const responsiveVariant = useResponsiveValue(variant); + const responsiveColor = useResponsiveValue(color); + const internalRef = useRef(null); - // Determine the component to render based on the variant - let Component = as; - if (variant === 'title2') Component = 'h2'; - if (variant === 'title3') Component = 'h3'; - if (variant === 'title4') Component = 'h4'; - if (variant === 'title5') Component = 'h5'; - if (as) Component = as; + const { renderElement } = useRender({ + render, + props: { + className: clsx('canon-Heading', className), + ['data-variant']: responsiveVariant, + ['data-color']: responsiveColor, + ['data-truncate']: truncate, + ...restProps, + }, + refs: [ref, internalRef], + }); - return ( - - {children} - - ); + return renderElement(); }, ); diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css index f0f4561400..c629c1ba48 100644 --- a/packages/canon/src/components/Heading/styles.css +++ b/packages/canon/src/components/Heading/styles.css @@ -52,6 +52,26 @@ font-weight: var(--canon-font-weight-bold); } +.canon-Heading[data-color='primary'] { + color: var(--canon-fg-primary); +} + +.canon-Heading[data-color='secondary'] { + color: var(--canon-fg-secondary); +} + +.canon-Heading[data-color='danger'] { + color: var(--canon-fg-danger); +} + +.canon-Heading[data-color='warning'] { + color: var(--canon-fg-warning); +} + +.canon-Heading[data-color='success'] { + color: var(--canon-fg-success); +} + .canon-Heading[data-truncate] { overflow: hidden; text-overflow: ellipsis; diff --git a/packages/canon/src/components/Heading/types.ts b/packages/canon/src/components/Heading/types.ts index b87f16eb34..312682033d 100644 --- a/packages/canon/src/components/Heading/types.ts +++ b/packages/canon/src/components/Heading/types.ts @@ -15,10 +15,11 @@ */ import { Breakpoint } from '../../types'; +import type { useRender } from '@base-ui-components/react/use-render'; /** @public */ -export interface HeadingProps { - children: React.ReactNode; +export interface HeadingProps + extends Omit, 'color'> { variant?: | 'display' | 'title1' @@ -32,7 +33,18 @@ export interface HeadingProps { 'display' | 'title1' | 'title2' | 'title3' | 'title4' | 'title5' > >; - as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + color?: + | 'primary' + | 'secondary' + | 'danger' + | 'warning' + | 'success' + | Partial< + Record< + Breakpoint, + 'primary' | 'secondary' | 'danger' | 'warning' | 'success' + > + >; truncate?: boolean; className?: string; style?: React.CSSProperties; diff --git a/packages/canon/src/components/Text/Text.stories.tsx b/packages/canon/src/components/Text/Text.stories.tsx index ba1155daed..5fe0c12cb5 100644 --- a/packages/canon/src/components/Text/Text.stories.tsx +++ b/packages/canon/src/components/Text/Text.stories.tsx @@ -108,6 +108,13 @@ export const WrappedInLink: Story = { ], }; +export const CustomRender: Story = { + args: { + ...Default.args, + render: , + }, +}; + export const Playground: Story = { render: () => ( diff --git a/packages/canon/src/components/Text/Text.tsx b/packages/canon/src/components/Text/Text.tsx index 90cc9bb2ac..7e4dc74720 100644 --- a/packages/canon/src/components/Text/Text.tsx +++ b/packages/canon/src/components/Text/Text.tsx @@ -14,8 +14,9 @@ * limitations under the License. */ -import { forwardRef } from 'react'; +import { forwardRef, useRef } from 'react'; import { useResponsiveValue } from '../../hooks/useResponsiveValue'; +import { useRender } from '@base-ui-components/react/use-render'; import clsx from 'clsx'; import type { TextProps } from './types'; @@ -24,13 +25,12 @@ import type { TextProps } from './types'; export const Text = forwardRef( (props, ref) => { const { - children, variant = 'body', weight = 'regular', color = 'primary', - style, className, truncate, + render =

, ...restProps } = props; @@ -38,21 +38,22 @@ export const Text = forwardRef( const responsiveVariant = useResponsiveValue(variant); const responsiveWeight = useResponsiveValue(weight); const responsiveColor = useResponsiveValue(color); + const internalRef = useRef(null); - return ( -

- {children} -

- ); + const { renderElement } = useRender({ + render, + props: { + className: clsx('canon-Text', className), + ['data-variant']: responsiveVariant, + ['data-weight']: responsiveWeight, + ['data-color']: responsiveColor, + ['data-truncate']: truncate, + ...restProps, + }, + refs: [ref, internalRef], + }); + + return renderElement(); }, ); diff --git a/packages/canon/src/components/Text/types.ts b/packages/canon/src/components/Text/types.ts index 7adafd73d7..f9c3c0aaca 100644 --- a/packages/canon/src/components/Text/types.ts +++ b/packages/canon/src/components/Text/types.ts @@ -14,12 +14,13 @@ * limitations under the License. */ -import type { CSSProperties, ReactNode } from 'react'; +import type { CSSProperties } from 'react'; import type { Breakpoint } from '../../types'; +import type { useRender } from '@base-ui-components/react/use-render'; /** @public */ -export interface TextProps { - children: ReactNode; +export interface TextProps + extends Omit, 'color'> { variant?: | 'subtitle' | 'body' From 4934e7abc9468b47c4bf4a8667e95c907e916474 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 19:00:50 +0100 Subject: [PATCH 136/143] Improve colors for Heading Signed-off-by: Charles de Dreuille --- packages/canon/css/components.css | 12 ------------ packages/canon/css/heading.css | 12 ------------ packages/canon/css/styles.css | 12 ------------ packages/canon/report.api.md | 10 +--------- .../canon/src/components/Heading/Heading.stories.tsx | 3 --- packages/canon/src/components/Heading/styles.css | 12 ------------ packages/canon/src/components/Heading/types.ts | 10 +--------- 7 files changed, 2 insertions(+), 69 deletions(-) diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 496dd1303d..6ed608a808 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -455,18 +455,6 @@ color: var(--canon-fg-secondary); } -.canon-Heading[data-color="danger"] { - color: var(--canon-fg-danger); -} - -.canon-Heading[data-color="warning"] { - color: var(--canon-fg-warning); -} - -.canon-Heading[data-color="success"] { - color: var(--canon-fg-success); -} - .canon-Heading[data-truncate] { text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/canon/css/heading.css b/packages/canon/css/heading.css index 50e9d3503d..96d6f13fac 100644 --- a/packages/canon/css/heading.css +++ b/packages/canon/css/heading.css @@ -44,18 +44,6 @@ color: var(--canon-fg-secondary); } -.canon-Heading[data-color="danger"] { - color: var(--canon-fg-danger); -} - -.canon-Heading[data-color="warning"] { - color: var(--canon-fg-warning); -} - -.canon-Heading[data-color="success"] { - color: var(--canon-fg-success); -} - .canon-Heading[data-truncate] { text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index aceb4e39db..3038e919ba 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9679,18 +9679,6 @@ color: var(--canon-fg-secondary); } -.canon-Heading[data-color="danger"] { - color: var(--canon-fg-danger); -} - -.canon-Heading[data-color="warning"] { - color: var(--canon-fg-warning); -} - -.canon-Heading[data-color="success"] { - color: var(--canon-fg-success); -} - .canon-Heading[data-truncate] { text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index 0ffa6052c2..43ab122f5a 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -625,15 +625,7 @@ export interface HeadingProps color?: | 'primary' | 'secondary' - | 'danger' - | 'warning' - | 'success' - | Partial< - Record< - Breakpoint, - 'primary' | 'secondary' | 'danger' | 'warning' | 'success' - > - >; + | Partial>; // (undocumented) style?: React.CSSProperties; // (undocumented) diff --git a/packages/canon/src/components/Heading/Heading.stories.tsx b/packages/canon/src/components/Heading/Heading.stories.tsx index aa9625ae03..bb241b5aae 100644 --- a/packages/canon/src/components/Heading/Heading.stories.tsx +++ b/packages/canon/src/components/Heading/Heading.stories.tsx @@ -58,9 +58,6 @@ export const AllColors: Story = { - - - ), }; diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css index c629c1ba48..1644da09df 100644 --- a/packages/canon/src/components/Heading/styles.css +++ b/packages/canon/src/components/Heading/styles.css @@ -60,18 +60,6 @@ color: var(--canon-fg-secondary); } -.canon-Heading[data-color='danger'] { - color: var(--canon-fg-danger); -} - -.canon-Heading[data-color='warning'] { - color: var(--canon-fg-warning); -} - -.canon-Heading[data-color='success'] { - color: var(--canon-fg-success); -} - .canon-Heading[data-truncate] { overflow: hidden; text-overflow: ellipsis; diff --git a/packages/canon/src/components/Heading/types.ts b/packages/canon/src/components/Heading/types.ts index 312682033d..7a94bdf2a4 100644 --- a/packages/canon/src/components/Heading/types.ts +++ b/packages/canon/src/components/Heading/types.ts @@ -36,15 +36,7 @@ export interface HeadingProps color?: | 'primary' | 'secondary' - | 'danger' - | 'warning' - | 'success' - | Partial< - Record< - Breakpoint, - 'primary' | 'secondary' | 'danger' | 'warning' | 'success' - > - >; + | Partial>; truncate?: boolean; className?: string; style?: React.CSSProperties; From eac8c6ca66cb1e3163f4f213e6e45f8dc1bf0096 Mon Sep 17 00:00:00 2001 From: "Kevin L." <61201328+KL2808@users.noreply.github.com> Date: Fri, 16 May 2025 22:07:22 +0200 Subject: [PATCH 137/143] Rename scalr to scalr.yaml Signed-off-by: Kevin L. <61201328+KL2808@users.noreply.github.com> --- microsite/data/plugins/{scalr => scalr.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename microsite/data/plugins/{scalr => scalr.yaml} (100%) diff --git a/microsite/data/plugins/scalr b/microsite/data/plugins/scalr.yaml similarity index 100% rename from microsite/data/plugins/scalr rename to microsite/data/plugins/scalr.yaml From 91cb30c621bdb82cbd714d1e0d5ea1624fac07a9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 17 May 2025 11:47:31 +0200 Subject: [PATCH 138/143] docs/backend-system: update index page be an introduction Signed-off-by: Patrik Oldsberg --- docs/backend-system/index.md | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/backend-system/index.md b/docs/backend-system/index.md index b8cf5048be..9fcd7f0c9a 100644 --- a/docs/backend-system/index.md +++ b/docs/backend-system/index.md @@ -3,11 +3,29 @@ id: index title: The Backend System sidebar_label: Introduction # prettier-ignore -description: The Backend System +description: Introduction to Backstage's backend system and its documentation --- -## Status +## Overview -The new backend system is released and ready for production use, and many plugins and modules have already been migrated. We recommend all plugins and deployments to migrate to the new system. +The Backstage backend system provides a flexible foundation for building and extending Backstage backends. It uses a modular architecture where you can create and customize plugins, modules, and service implementations. It's focused both around building your own features as well as installing third-party plugins and modules available in the Backstage ecosystem. The system is designed to be scalable and maintainable, making it work well for organizations of all sizes. -You can find an example backend setup in [the `backend` package](https://github.com/backstage/backstage/tree/master/packages/backend). +## Documentation Sections + +This documentation is organized into several key areas, each focusing on different aspects of the backend system: + +### [Architecture](./architecture/01-index.md) + +The Architecture section explains the core building blocks and concepts of the Backstage backend system. It starts with backend instances, which serve as the main entry point for creating and wiring together backend features. You'll learn about plugins that provide the base features and operate independently as microservices, modules that extend plugins with additional capabilities through extension points, and services that provide shared functionality across plugins and modules. The section also covers feature loaders that enable programmatic selection and installation of features, as well as important naming patterns and conventions used throughout the backend system. + +### [Building Backends](./building-backends/01-index.md) + +This section covers how to set up and customize your own Backstage backend. You'll learn about the basic structure of a backend package, how to install plugins and modules, and ways to customize your installation through configuration and custom service implementations. The section also explains how to split your backend into multiple deployments for better scalability and security isolation. + +### [Building Plugins and Modules](./building-plugins-and-modules/01-index.md) + +The Building Plugins and Modules section shows you how to create and test backend plugins and modules. It covers creating new plugins using `yarn new`, implementing plugin functionality with services and extension points, and building modules that extend existing plugins. You'll learn how to test your plugins and modules using the test utilities in `@backstage/backend-test-utils`, including mocking services, testing HTTP endpoints, and working with databases. The section also explains how to enable users of your plugin to customize it through static configuration and extension points. + +### [Core Services](./core-services/01-index.md) + +The Core Services section documents the essential services that are available to all backend plugins. These include fundamental services like logging, configuration, and HTTP routing that plugins can depend on. Each service is documented with its interface, implementation details, and usage examples. From 9510105a4935c9600159886efe3ca3ba70f30e64 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Sun, 18 May 2025 20:53:59 +0100 Subject: [PATCH 139/143] Add new Tabs component Signed-off-by: Charles de Dreuille --- .changeset/long-ends-shop.md | 5 ++ packages/canon/css/components.css | 77 ++++++++++++++++++ packages/canon/css/styles.css | 77 ++++++++++++++++++ packages/canon/css/tabs.css | 76 ++++++++++++++++++ packages/canon/report.api.md | 21 +++++ .../src/components/Tabs/Tabs.stories.tsx | 50 ++++++++++++ .../canon/src/components/Tabs/Tabs.styles.css | 76 ++++++++++++++++++ packages/canon/src/components/Tabs/Tabs.tsx | 78 +++++++++++++++++++ packages/canon/src/components/Tabs/index.ts | 16 ++++ packages/canon/src/css/components.css | 1 + packages/canon/src/index.ts | 1 + 11 files changed, 478 insertions(+) create mode 100644 .changeset/long-ends-shop.md create mode 100644 packages/canon/css/tabs.css create mode 100644 packages/canon/src/components/Tabs/Tabs.stories.tsx create mode 100644 packages/canon/src/components/Tabs/Tabs.styles.css create mode 100644 packages/canon/src/components/Tabs/Tabs.tsx create mode 100644 packages/canon/src/components/Tabs/index.ts diff --git a/.changeset/long-ends-shop.md b/.changeset/long-ends-shop.md new file mode 100644 index 0000000000..f57c3ccdbd --- /dev/null +++ b/.changeset/long-ends-shop.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Add new Tabs component to Canon diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 124d575a96..6e9ffa6cff 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -349,6 +349,83 @@ display: flex; } +.canon-TabsRoot { + border: 1px solid var(--color-gray-200); + border-radius: .375rem; +} + +.canon-TabsList { + z-index: 0; + display: flex; + position: relative; +} + +.canon-TabsTab { + appearance: none; + color: var(--canon-fg-secondary); + user-select: none; + padding-inline: var(--canon-space-3); + height: 2rem; + font-family: inherit; + font-size: .875rem; + font-weight: 500; + line-height: 1.25rem; + font-size: var(--canon-font-size-2); + cursor: pointer; + background: none; + border: 0; + outline: 0; + justify-content: center; + align-items: center; + margin: 0; + padding-block: 0; + transition: color .2s ease-in-out; + display: flex; + + &[data-selected] { + color: var(--canon-fg-primary); + } + + @media (hover: hover) { + &:hover { + color: var(--canon-fg-primary); + } + } + + &:focus-visible { + position: relative; + + &:before { + content: ""; + outline: 1px solid var(--canon-ring); + outline-offset: -1px; + border-radius: .25rem; + position: absolute; + inset: .25rem 0; + } + } +} + +.canon-TabsIndicator { + z-index: -1; + translate: var(--active-tab-left) -50%; + width: var(--active-tab-width); + background-color: var(--canon-bg-solid); + height: 1px; + transition-property: translate, width; + transition-duration: .2s; + transition-timing-function: ease-in-out; + position: absolute; + bottom: 0; + left: 0; +} + +.canon-TabsPanel { + &[hidden] { + display: none; + } +} + .canon-Text { font-family: var(--canon-font-regular); margin: 0; diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 084aef2855..436c9a8db7 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9573,6 +9573,83 @@ display: flex; } +.canon-TabsRoot { + border: 1px solid var(--color-gray-200); + border-radius: .375rem; +} + +.canon-TabsList { + z-index: 0; + display: flex; + position: relative; +} + +.canon-TabsTab { + appearance: none; + color: var(--canon-fg-secondary); + user-select: none; + padding-inline: var(--canon-space-3); + height: 2rem; + font-family: inherit; + font-size: .875rem; + font-weight: 500; + line-height: 1.25rem; + font-size: var(--canon-font-size-2); + cursor: pointer; + background: none; + border: 0; + outline: 0; + justify-content: center; + align-items: center; + margin: 0; + padding-block: 0; + transition: color .2s ease-in-out; + display: flex; + + &[data-selected] { + color: var(--canon-fg-primary); + } + + @media (hover: hover) { + &:hover { + color: var(--canon-fg-primary); + } + } + + &:focus-visible { + position: relative; + + &:before { + content: ""; + outline: 1px solid var(--canon-ring); + outline-offset: -1px; + border-radius: .25rem; + position: absolute; + inset: .25rem 0; + } + } +} + +.canon-TabsIndicator { + z-index: -1; + translate: var(--active-tab-left) -50%; + width: var(--active-tab-width); + background-color: var(--canon-bg-solid); + height: 1px; + transition-property: translate, width; + transition-duration: .2s; + transition-timing-function: ease-in-out; + position: absolute; + bottom: 0; + left: 0; +} + +.canon-TabsPanel { + &[hidden] { + display: none; + } +} + .canon-Text { font-family: var(--canon-font-regular); margin: 0; diff --git a/packages/canon/css/tabs.css b/packages/canon/css/tabs.css new file mode 100644 index 0000000000..a9bf036c3e --- /dev/null +++ b/packages/canon/css/tabs.css @@ -0,0 +1,76 @@ +.canon-TabsRoot { + border: 1px solid var(--color-gray-200); + border-radius: .375rem; +} + +.canon-TabsList { + z-index: 0; + display: flex; + position: relative; +} + +.canon-TabsTab { + appearance: none; + color: var(--canon-fg-secondary); + user-select: none; + padding-inline: var(--canon-space-3); + height: 2rem; + font-family: inherit; + font-size: .875rem; + font-weight: 500; + line-height: 1.25rem; + font-size: var(--canon-font-size-2); + cursor: pointer; + background: none; + border: 0; + outline: 0; + justify-content: center; + align-items: center; + margin: 0; + padding-block: 0; + transition: color .2s ease-in-out; + display: flex; + + &[data-selected] { + color: var(--canon-fg-primary); + } + + @media (hover: hover) { + &:hover { + color: var(--canon-fg-primary); + } + } + + &:focus-visible { + position: relative; + + &:before { + content: ""; + outline: 1px solid var(--canon-ring); + outline-offset: -1px; + border-radius: .25rem; + position: absolute; + inset: .25rem 0; + } + } +} + +.canon-TabsIndicator { + z-index: -1; + translate: var(--active-tab-left) -50%; + width: var(--active-tab-width); + background-color: var(--canon-bg-solid); + height: 1px; + transition-property: translate, width; + transition-duration: .2s; + transition-timing-function: ease-in-out; + position: absolute; + bottom: 0; + left: 0; +} + +.canon-TabsPanel { + &[hidden] { + display: none; + } +} diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index ff8c36e5ec..59a2e2bffd 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -23,6 +23,7 @@ import { RefAttributes } from 'react'; import type { RemixiconComponentType } from '@remixicon/react'; import { ScrollArea as ScrollArea_2 } from '@base-ui-components/react/scroll-area'; import { Table as Table_2 } from '@tanstack/react-table'; +import { Tabs as Tabs_2 } from '@base-ui-components/react/tabs'; import { TdHTMLAttributes } from 'react'; import { ThHTMLAttributes } from 'react'; import { Tooltip as Tooltip_2 } from '@base-ui-components/react/tooltip'; @@ -1231,6 +1232,26 @@ export interface TableCellTextProps title: string; } +// @public (undocumented) +export const Tabs: { + Root: ForwardRefExoticComponent< + Omit, 'ref'> & + RefAttributes + >; + List: ForwardRefExoticComponent< + Omit, 'ref'> & + RefAttributes + >; + Tab: ForwardRefExoticComponent< + Omit, 'ref'> & + RefAttributes + >; + Panel: ForwardRefExoticComponent< + Omit, 'ref'> & + RefAttributes + >; +}; + // @public (undocumented) const Text_2: ForwardRefExoticComponent< TextProps & RefAttributes diff --git a/packages/canon/src/components/Tabs/Tabs.stories.tsx b/packages/canon/src/components/Tabs/Tabs.stories.tsx new file mode 100644 index 0000000000..ec8526e9b1 --- /dev/null +++ b/packages/canon/src/components/Tabs/Tabs.stories.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Meta, StoryObj } from '@storybook/react'; +import { Tabs } from './Tabs'; +import { Text } from '../../index'; + +const meta = { + title: 'Components/Tabs', + component: Tabs.Root, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + + + Tab 1 + Tab 2 + Tab 3 With long title + + + Content for Tab 1 + + + Content for Tab 2 + + + Content for Tab 3 + + + ), + }, +}; diff --git a/packages/canon/src/components/Tabs/Tabs.styles.css b/packages/canon/src/components/Tabs/Tabs.styles.css new file mode 100644 index 0000000000..84a4d378c1 --- /dev/null +++ b/packages/canon/src/components/Tabs/Tabs.styles.css @@ -0,0 +1,76 @@ +.canon-TabsRoot { + border: 1px solid var(--color-gray-200); + border-radius: 0.375rem; +} + +.canon-TabsList { + display: flex; + position: relative; + z-index: 0; +} + +.canon-TabsTab { + display: flex; + align-items: center; + justify-content: center; + border: 0; + margin: 0; + outline: 0; + background: none; + appearance: none; + color: var(--canon-fg-secondary); + font-family: inherit; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; + user-select: none; + padding-inline: var(--canon-space-3); + padding-block: 0; + height: 2rem; + font-size: var(--canon-font-size-2); + transition: color 200ms ease-in-out; + cursor: pointer; + + &[data-selected] { + color: var(--canon-fg-primary); + } + + @media (hover: hover) { + &:hover { + color: var(--canon-fg-primary); + } + } + + &:focus-visible { + position: relative; + + &::before { + content: ''; + position: absolute; + inset: 0.25rem 0; + border-radius: 0.25rem; + outline: 1px solid var(--canon-ring); + outline-offset: -1px; + } + } +} + +.canon-TabsIndicator { + position: absolute; + z-index: -1; + left: 0; + bottom: 0; + translate: var(--active-tab-left) -50%; + width: var(--active-tab-width); + height: 1px; + background-color: var(--canon-bg-solid); + transition-property: translate, width; + transition-duration: 200ms; + transition-timing-function: ease-in-out; +} + +.canon-TabsPanel { + &[hidden] { + display: none; + } +} diff --git a/packages/canon/src/components/Tabs/Tabs.tsx b/packages/canon/src/components/Tabs/Tabs.tsx new file mode 100644 index 0000000000..116ef94fb9 --- /dev/null +++ b/packages/canon/src/components/Tabs/Tabs.tsx @@ -0,0 +1,78 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { forwardRef } from 'react'; +import { Tabs as TabsPrimitive } from '@base-ui-components/react/tabs'; +import clsx from 'clsx'; + +const TabsRoot = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsRoot.displayName = TabsPrimitive.Root.displayName; + +const TabsList = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + +)); +TabsList.displayName = TabsPrimitive.List.displayName; + +const TabsTab = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsTab.displayName = TabsPrimitive.Tab.displayName; + +const TabsPanel = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsPanel.displayName = TabsPrimitive.Panel.displayName; + +/** @public */ +export const Tabs = { + Root: TabsRoot, + List: TabsList, + Tab: TabsTab, + Panel: TabsPanel, +}; diff --git a/packages/canon/src/components/Tabs/index.ts b/packages/canon/src/components/Tabs/index.ts new file mode 100644 index 0000000000..e9bc130d25 --- /dev/null +++ b/packages/canon/src/components/Tabs/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { Tabs } from './Tabs'; diff --git a/packages/canon/src/css/components.css b/packages/canon/src/css/components.css index 53c2882302..7cee946e3b 100644 --- a/packages/canon/src/css/components.css +++ b/packages/canon/src/css/components.css @@ -30,6 +30,7 @@ @import '../components/Table/TableCellText/TableCellText.styles.css'; @import '../components/Table/TableCellLink/TableCellLink.styles.css'; @import '../components/Table/TableCellProfile/TableCellProfile.styles.css'; +@import '../components/Tabs/Tabs.styles.css'; @import '../components/Text/styles.css'; @import '../components/Heading/styles.css'; @import '../components/IconButton/styles.css'; diff --git a/packages/canon/src/index.ts b/packages/canon/src/index.ts index 7677a539c7..cab4cc4acb 100644 --- a/packages/canon/src/index.ts +++ b/packages/canon/src/index.ts @@ -40,6 +40,7 @@ export * from './components/Icon'; export * from './components/IconButton'; export * from './components/Checkbox'; export * from './components/Table'; +export * from './components/Tabs'; export * from './components/TextField'; export * from './components/Tooltip'; export * from './components/Menu'; From eb54d726d73a79323a3017d6edd1c67b8a08cc35 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Sun, 18 May 2025 22:34:19 +0100 Subject: [PATCH 140/143] Add docs for tabs Signed-off-by: Charles de Dreuille --- .../src/app/(docs)/components/tabs/page.mdx | 92 +++++++++++++++++++ .../src/app/(docs)/components/tabs/props.ts | 61 ++++++++++++ canon-docs/src/snippets/stories-snippets.tsx | 8 ++ canon-docs/src/utils/data.ts | 5 + packages/canon/report.api.md | 10 +- .../src/components/Tabs/Tabs.stories.tsx | 18 ++-- packages/canon/src/components/Tabs/Tabs.tsx | 3 +- packages/canon/src/components/Tabs/index.ts | 2 + packages/canon/src/components/Tabs/types.ts | 25 +++++ 9 files changed, 211 insertions(+), 13 deletions(-) create mode 100644 canon-docs/src/app/(docs)/components/tabs/page.mdx create mode 100644 canon-docs/src/app/(docs)/components/tabs/props.ts create mode 100644 packages/canon/src/components/Tabs/types.ts diff --git a/canon-docs/src/app/(docs)/components/tabs/page.mdx b/canon-docs/src/app/(docs)/components/tabs/page.mdx new file mode 100644 index 0000000000..478608d718 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/tabs/page.mdx @@ -0,0 +1,92 @@ +import { PropsTable } from '@/components/PropsTable'; +import { TabsSnippet } from '@/snippets/stories-snippets'; +import { Snippet } from '@/components/Snippet'; +import { Tabs } from '@/components/Tabs'; +import { CodeBlock } from '@/components/CodeBlock'; +import { + tabsRootPropDefs, + tabsListPropDefs, + tabsTabPropDefs, + tabsPanelPropDefs, +} from './props'; +import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; + +# Tabs + +A component for toggling between related panels on the same page. + +} + code={` + + Tab 1 + Tab 2 + Tab 3 With long title + + Content for Tab 1 + Content for Tab 2 + Content for Tab 3 + `} +/> + + + + Usage + Theming + + + + + Tab 1 + Tab 2 + Tab 3 + + Content for Tab 1 + Content for Tab 2 + Content for Tab 3 + +`} + /> + + + We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with + your brand. For additional flexibility, you can use the provided class names for each element listed below. + - `canon-TabsRoot` + - `canon-TabsList` + - `canon-TabsTab` + - `canon-TabsPanel` + - `canon-TabsIndicator` + + + +## API reference + + + +### Tabs.Root + +Groups the tabs and the corresponding panels. Renders a `
` element. + + + +### Tabs.List + +Groups the individual tab buttons. Renders a `
` element. + + + +### Tabs.Tab + +An individual interactive tab button that toggles the corresponding panel. Renders a `