Merge branch 'master' into scaffolder/autocomplete-github-branches
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-react': patch
|
||||
---
|
||||
|
||||
Hide text output button if only one is present
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-github': patch
|
||||
---
|
||||
|
||||
**DEPRECATION**: The `getOctokitOptions` function signature with `repoUrl` option has been deprecated in favour of a function signature with individual `host`, `owner`, and `repo` parameters:
|
||||
|
||||
```diff
|
||||
const octokitOptions = await getOctokitOptions({
|
||||
integrations,
|
||||
credentialsProvider,
|
||||
token,
|
||||
- repoUrl,
|
||||
+ host,
|
||||
+ owner,
|
||||
+ repo,
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-plugin-api': minor
|
||||
---
|
||||
|
||||
**BREAKING ALPHA**: Removed the deprecated `featureDiscoveryServiceRef` and `FeatureDiscoveryService`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-home': patch
|
||||
---
|
||||
|
||||
feat: add cancel button for WidgetSettingsOverlay
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
|
||||
---
|
||||
|
||||
`createGitlabProjectMigrateAction` can now output the `migrationId`
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/cli-node': patch
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Fixed an issue where default feature type information wasn't being added to package.json/exports before publishing if exports didn't exist beforehand
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-defaults': patch
|
||||
---
|
||||
|
||||
Internal refactor to stop importing the removed `FeatureDiscoveryService` from `@backstage/backend-plugin-api`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Upgrade `dagre` to `@dagrejs/dagre`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-app-api': minor
|
||||
---
|
||||
|
||||
**BREAKING ALPHA**: Removed the deprecated `featureDiscoveryServiceFactory`. Existing usage can be replaced with `discoveryFeatureLoader` from `@backstage/backend-defaults`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-defaults': patch
|
||||
---
|
||||
|
||||
Allow passing IP type to use with cloud-sql-connector
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-backend': patch
|
||||
'@backstage/plugin-kubernetes-cluster': patch
|
||||
'@backstage/plugin-kubernetes-common': patch
|
||||
'@backstage/plugin-kubernetes': patch
|
||||
---
|
||||
|
||||
The `/clusters` endpoint is now protected by the `kubernetes.clusters.read` permission.
|
||||
The `/services/:serviceId` endpoint is now protected by the `kubernetes.resources.read` permission.
|
||||
The `/resources` endpoints are now protected by the `kubernetes.resources.read` permission.
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend-module-cloudflare-access-provider': minor
|
||||
'@backstage/plugin-auth-backend-module-bitbucket-server-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-pinniped-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-auth0-provider': minor
|
||||
'@backstage/plugin-auth-backend-module-oidc-provider': minor
|
||||
'@backstage/plugin-auth-backend-module-okta-provider': minor
|
||||
'@backstage/plugin-auth-node': minor
|
||||
---
|
||||
|
||||
Added `auth.providers.<providerId>.sessionDuration` config for auth providers to allow the lifespan of user sessions to be configured.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Fixed bug of passing wrong value to `onChange` handler when using `GitLab` autocomplete
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': minor
|
||||
---
|
||||
|
||||
Added experimental flag for scaffolder to wait for running tasks to complete on shutdown
|
||||
|
||||
Enabling the `EXPERIMENTAL_gracefulShutdown` flag in the scaffolder config will make the
|
||||
scaffolder block the shutdown process until all running tasks have completed. This is useful
|
||||
when there is a need to ensure that all tasks have completed before the scaffolder is shut down.
|
||||
|
||||
Please note, that the `TaskWorker` `stop` method is now asynchronous and awaited for the
|
||||
tasks to complete when the experimental flag is enabled.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-dynamic-feature-service': minor
|
||||
---
|
||||
|
||||
**BREAKING**: removed the deprecated `dynamicPluginsFeatureDiscoveryServiceFactory`.
|
||||
@@ -3,6 +3,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/sync_version-packages.yml'
|
||||
|
||||
concurrency:
|
||||
group: sync-version-packages
|
||||
@@ -23,6 +25,10 @@ jobs:
|
||||
fetch-depth: 20000
|
||||
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
|
||||
|
||||
@@ -51,6 +51,8 @@ auth:
|
||||
additionalScopes:
|
||||
- 'read:jira-user'
|
||||
- 'read:jira-work'
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/atlassian/provider#resolvers for more resolvers
|
||||
@@ -67,6 +69,10 @@ The Atlassian provider is a structure with the following configuration keys:
|
||||
|
||||
**NOTE:** The scopes `offline_access`, `read:jira-work`, and `read:jira-user` are provided by default.
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -44,6 +44,8 @@ auth:
|
||||
audience: ${AUTH_AUTH0_AUDIENCE}
|
||||
connection: ${AUTH_AUTH0_CONNECTION}
|
||||
connectionScope: ${AUTH_AUTH0_CONNECTION_SCOPE}
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
session:
|
||||
secret: ${AUTH_SESSION_SECRET}
|
||||
```
|
||||
@@ -66,6 +68,7 @@ Auth0 requires a session, so you need to give the session a secret key.
|
||||
- `audience`: The intended recipients of the token.
|
||||
- `connection`: Social identity provider name. To check the available social connections, please visit [Auth0 Social Connections](https://marketplace.auth0.com/features/social-connections).
|
||||
- `connectionScope`: Additional scopes in the interactive token request. It should always be used in combination with the `connection` parameter.
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ auth:
|
||||
signer: 'arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/app/my-load-balancer/1234567890123456'
|
||||
# this is the region where your ALB instance resides
|
||||
region: 'us-west-2'
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/aws-alb/provider#resolvers for more resolvers
|
||||
@@ -31,6 +33,10 @@ auth:
|
||||
|
||||
Ensure that you have set the signer correctly. It is also recommended that you restrict your target groups' security policy to only accept connections from that ALB.
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -37,6 +37,8 @@ auth:
|
||||
development:
|
||||
clientId: ${AUTH_BITBUCKET_CLIENT_ID}
|
||||
clientSecret: ${AUTH_BITBUCKET_CLIENT_SECRET}
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/bitbucket/provider#resolvers for more resolvers
|
||||
@@ -49,6 +51,10 @@ The Bitbucket provider is a structure with two configuration keys:
|
||||
`b59241722e3c3b4816e2`
|
||||
- `clientSecret`: The Secret tied to the generated Key.
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -34,6 +34,8 @@ auth:
|
||||
host: bitbucket.example.org
|
||||
clientId: ${AUTH_BITBUCKET_SERVER_CLIENT_ID}
|
||||
clientSecret: ${AUTH_BITBUCKET_SERVER_CLIENT_SECRET}
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
```
|
||||
|
||||
The Bitbucket Server provider is a structure with two configuration keys:
|
||||
@@ -41,6 +43,10 @@ The Bitbucket Server provider is a structure with two configuration keys:
|
||||
- `clientId`: The client ID that was generated by Bitbucket, e.g. `b0f868455c15dcdff5c5fb5d173ae684`.
|
||||
- `clientSecret`: The client secret tied to the generated client ID.
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -38,6 +38,8 @@ auth:
|
||||
# You can customize the authorization cookie name, by default
|
||||
# CF_Authorization is used
|
||||
authorizationCookieName: <MY_CAUTHORIZATION_COOKIE_NAME>
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
# This picks what sign in resolver(s) you want to use.
|
||||
signIn:
|
||||
resolvers:
|
||||
@@ -47,6 +49,10 @@ auth:
|
||||
|
||||
This config section must be in place for the provider to load at all.
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -49,6 +49,8 @@ auth:
|
||||
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
|
||||
## uncomment if using GitHub Enterprise
|
||||
# enterpriseInstanceUrl: ${AUTH_GITHUB_ENTERPRISE_INSTANCE_URL}
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/github/provider#resolvers for more resolvers
|
||||
@@ -66,6 +68,7 @@ The GitHub provider is a structure with these configuration keys:
|
||||
initiating an OAuth flow, e.g.,
|
||||
`https://your-intermediate-service.com/handler`. Only needed if Backstage is
|
||||
not the immediate receiver (e.g., one OAuth app for many backstage instances).
|
||||
- `sessionDuration` (optional): Lifespan of the user session.
|
||||
- `signIn`: The configuration for the sign-in process, including the **resolvers**
|
||||
that should be used to match the user from the auth provider with the user
|
||||
entity in the Backstage catalog (typically a single resolver is sufficient).
|
||||
|
||||
@@ -45,6 +45,8 @@ auth:
|
||||
# audience: https://gitlab.company.com
|
||||
## uncomment if using a custom redirect URI
|
||||
# callbackUrl: https://${BASE_URL}/api/auth/gitlab/handler/frame
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/gitlab/provider#resolvers for more resolvers
|
||||
@@ -61,6 +63,7 @@ The GitLab provider is a structure with three configuration keys:
|
||||
- `callbackUrl` (optional): The URL matching the Redirect URI registered when creating your GitLab OAuth App, e.g.
|
||||
`https://$backstage.acme.corp/api/auth/gitlab/handler/frame`
|
||||
Note: Due to a peculiarity with GitLab OAuth, ensure there is no trailing `/` after 'frame' in the URL.
|
||||
- `sessionDuration` (optional): Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ auth:
|
||||
development:
|
||||
clientId: ${AUTH_GOOGLE_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GOOGLE_CLIENT_SECRET}
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/google/provider#resolvers for more resolvers
|
||||
@@ -54,6 +56,10 @@ The Google provider is a structure with two configuration keys:
|
||||
`10023341500512-beui241gjwwkrdkr2eh7dprewj2pp1q.apps.googleusercontent.com`
|
||||
- `clientSecret`: The client secret tied to the generated client ID.
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -84,6 +84,7 @@ The Microsoft provider is a structure with three mandatory configuration keys:
|
||||
For more details, see [Home Realm Discovery](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/home-realm-discovery-policy)
|
||||
- `additionalScopes` (optional): List of scopes for the App Registration, to be requested in addition to the required ones.
|
||||
- `skipUserProfile` (optional): If true, skips loading the user profile even if the `User.Read` scope is present. This is a performance optimization during login and can be used with resolvers that only needs the email address in `spec.profile.email` obtained when the `email` OAuth2 scope is present.
|
||||
- `sessionDuration` (optional): Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
|
||||
@@ -263,6 +263,7 @@ check the App Registration you created:
|
||||
basically the same thing.
|
||||
- `prompt`: Recommended to use `auto` so the browser will request login to the IDP if the
|
||||
user has no active session.
|
||||
- `sessionDuration` (optional): Lifespan of the user session.
|
||||
|
||||
Note that for the time being, any change in this yaml file requires a restart of the app,
|
||||
also you need to have the `session.secret` part to use OIDC (some other providers might
|
||||
|
||||
@@ -45,6 +45,8 @@ auth:
|
||||
audience: ${AUTH_OKTA_DOMAIN}
|
||||
authServerId: ${AUTH_OKTA_AUTH_SERVER_ID} # Optional
|
||||
idp: ${AUTH_OKTA_IDP} # Optional
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # Optional: supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
# https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned
|
||||
additionalScopes: ${AUTH_OKTA_ADDITIONAL_SCOPES} # Optional
|
||||
signIn:
|
||||
@@ -62,6 +64,7 @@ The values referenced are found on the Application page on your Okta site.
|
||||
`https://company.okta.com`
|
||||
- `authServerId`: The authorization server ID for the Application
|
||||
- `idp`: The identity provider for the application, e.g. `0oaulob4BFVa4zQvt0g3`
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
`additionalScopes` is an optional value, a string of space separated scopes, that will be combined with the default `scope` value of `openid profile email offline_access` to adjust the `scope` sent to Okta during OAuth. This will have an impact on [the dependent claims returned](https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned). For example, setting the `additionalScopes` value to `groups` will result in the claim returning a list of the groups that the user is a member of that also match the ID token group filter of the client app.
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ auth:
|
||||
clientId: ${AUTH_ONELOGIN_CLIENT_ID}
|
||||
clientSecret: ${AUTH_ONELOGIN_CLIENT_SECRET}
|
||||
issuer: https://<company>.onelogin.com/oidc/2
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/onelogin/provider#resolvers for more resolvers
|
||||
@@ -51,6 +53,10 @@ found on the SSO tab** for the OneLogin Application:
|
||||
- `clientSecret`: The client secret
|
||||
- `issuer`: The issuer URL
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
@@ -47,6 +47,8 @@ auth:
|
||||
development:
|
||||
clientId: ${APP_ID}
|
||||
organizationId: ${ORG_ID}
|
||||
## uncomment to set lifespan of user session
|
||||
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
|
||||
signIn:
|
||||
resolvers:
|
||||
# See https://backstage.io/docs/auth/vmware-cloud/provider#resolvers for more resolvers
|
||||
@@ -68,6 +70,10 @@ key for signing session cookies set by Backstage.
|
||||
|
||||
:::
|
||||
|
||||
### Optional
|
||||
|
||||
- `sessionDuration`: Lifespan of the user session.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: product
|
||||
title: Product FAQ
|
||||
title: Non-technical FAQ
|
||||
description: Questions related to product and design.
|
||||
---
|
||||
|
||||
|
||||
@@ -80,11 +80,13 @@ The default value is `false`.
|
||||
|
||||
#### Internationalization
|
||||
|
||||
To customize or translate the **Delete Pod** text, use the following approach:
|
||||
To customize or translate text in some of the components, use the following approach:
|
||||
|
||||
```js
|
||||
import { createTranslationMessages } from '@backstage/core-plugin-api/alpha';
|
||||
import { kubernetesReactTranslationRef } from '@backstage/plugin-kubernetes-react/alpha';
|
||||
import { kubernetesTranslationRef } from '@backstage/plugin-kubernetes/alpha';
|
||||
import { kubernetesClusterTranslationRef } from '@backstage/plugin-kubernetes-cluster/alpha';
|
||||
|
||||
const app = createApp({
|
||||
__experimentalTranslations: {
|
||||
@@ -94,7 +96,21 @@ const app = createApp({
|
||||
messages: {
|
||||
"podDrawer.buttons.delete": 'Restart Pod'
|
||||
}
|
||||
})
|
||||
}),
|
||||
createTranslationMessages({
|
||||
ref: kubernetesTranslationRef,
|
||||
messages: {
|
||||
'kubernetesContentPage.permissionAlert.title': 'Insufficient permissions',
|
||||
'kubernetesContentPage.permissionAlert.message': 'You do not have permissions to view Kubernetes objects.',
|
||||
},
|
||||
}),
|
||||
createTranslationMessages({
|
||||
ref: kubernetesClusterTranslationRef,
|
||||
messages: {
|
||||
'kubernetesClusterContentPage.permissionAlert.title': 'Insufficient permissions',
|
||||
'kubernetesClusterContentPage.permissionAlert.message': 'You do not have permissions to view Kubernetes objects.',
|
||||
},
|
||||
}),
|
||||
]
|
||||
},
|
||||
...
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
id: permissions
|
||||
title: Permissions
|
||||
description: Configuring permissions for Kubernetes plugin
|
||||
---
|
||||
|
||||
The Kubernetes plugin integrates with the permission framework. Administrators can define PermissionPolicies
|
||||
to restrict access to the `/clusters`, `/services/:serviceId`, `/resources` and `/proxy` endpoints.
|
||||
|
||||
This feature assumes your Backstage instance has enabled the [permissions framework](https://backstage.io/docs/permissions/getting-started).
|
||||
|
||||
### Available permissions
|
||||
|
||||
| Name | Policy | Description |
|
||||
| ------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| kubernetes.clusters.read | read | Allows the user to read Kubernetes clusters information under `/clusters` |
|
||||
| kubernetes.resources.read | read | Allows the user to read Kubernetes resources information under `/services/:serviceId` and `/resources` |
|
||||
| kubernetes.proxy | | Allows the user to make arbitrary requests to the [REST API](https://kubernetes.io/docs/reference/using-api/api-concepts/) under `/proxy` |
|
||||
+1
-32
@@ -7,36 +7,5 @@ description: Guidelines for how to use the Backstage logos and icons
|
||||
|
||||
Guidelines for how to use the Backstage logo and icon can be found
|
||||
[here](https://backstage.io/logo_assets/Backstage_Identity_Assets_Overview.pdf).
|
||||
The assets below are all in `.svg` format. Other formats are available in the
|
||||
[repository](https://github.com/backstage/backstage/tree/master/microsite/static/logo_assets).
|
||||
|
||||
## Backstage logo
|
||||
|
||||
<a href="https://backstage.io/logo_assets/svg/Logo_White.svg" aria-label='Link to Backstage White logo svg'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Logo_White.svg" alt='Backstage White logo' width="600" />
|
||||
</a>
|
||||
|
||||
<a href="https://backstage.io/logo_assets/svg/Logo_Teal.svg" aria-label='Link to Backstage Teal logo svg'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Logo_Teal.svg" alt='Backstage Teal logo' width="600" />
|
||||
</a>
|
||||
|
||||
<a href="https://backstage.io/logo_assets/svg/Logo_Black.svg" aria-label='Link to Backstage Black logo svg'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Logo_Black.svg" alt='Backstage Black logo' width="600" className="logoWhite" class="logoWhite" />
|
||||
</a>
|
||||
|
||||
## Backstage icon
|
||||
|
||||
<div>
|
||||
<a href="https://backstage.io/logo_assets/svg/Icon_White.svg" aria-label='Link to Backstage White icon'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Icon_White.svg" alt='Backstage White Icon' width="180" height="180" />
|
||||
</a>
|
||||
<a href="https://backstage.io/logo_assets/svg/Icon_Teal.svg" aria-label='Link to Backstage Teal icon'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Icon_Teal.svg" alt='Backstage Teal Icon' width="180" height="180" />
|
||||
</a>
|
||||
<a href="https://backstage.io/logo_assets/svg/Icon_Gradient.svg" aria-label='Link to Backstage Gradient icon'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Icon_Gradient.svg" alt='Backstage Gradient Icon' width="180" height="180" />
|
||||
</a>
|
||||
<a href="https://backstage.io/logo_assets/svg/Icon_Black.svg" aria-label='Link to Backstage Black icon'>
|
||||
<img src="https://backstage.io/logo_assets/svg/Icon_Black.svg" alt='Backstage Black Icon' width="180" height="180" className="logoWhite" class="logoWhite" />
|
||||
</a>
|
||||
</div>
|
||||
You can find the assets at https://github.com/cncf/artwork/tree/main/projects/backstage.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: threat-model
|
||||
title: Backstage Threat Model
|
||||
sidebar_label: Security & Thread Model
|
||||
description: A document describing the threat model for Backstage.
|
||||
---
|
||||
|
||||
|
||||
@@ -405,6 +405,10 @@ const config: Config = {
|
||||
label: 'GitHub',
|
||||
to: 'https://github.com/backstage/',
|
||||
},
|
||||
{
|
||||
label: 'Assets',
|
||||
to: 'https://github.com/cncf/artwork/tree/main/projects/backstage',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
+35
-27
@@ -5,14 +5,11 @@ module.exports = {
|
||||
Overview: [
|
||||
'overview/what-is-backstage',
|
||||
'overview/architecture-overview',
|
||||
'overview/roadmap',
|
||||
'overview/vision',
|
||||
'overview/background',
|
||||
'overview/adopting',
|
||||
'overview/versioning-policy',
|
||||
'overview/vision',
|
||||
'overview/roadmap',
|
||||
'overview/threat-model',
|
||||
'overview/support',
|
||||
'overview/logos',
|
||||
'overview/versioning-policy',
|
||||
],
|
||||
'Getting Started': [
|
||||
'getting-started/index',
|
||||
@@ -46,6 +43,7 @@ module.exports = {
|
||||
'getting-started/create-a-component',
|
||||
],
|
||||
},
|
||||
'overview/support',
|
||||
'getting-started/keeping-backstage-updated',
|
||||
],
|
||||
'Core Features': [
|
||||
@@ -494,36 +492,46 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
],
|
||||
'Designing for Backstage': [
|
||||
'dls/design',
|
||||
'dls/component-design-guidelines',
|
||||
'dls/contributing-to-storybook',
|
||||
'dls/figma',
|
||||
],
|
||||
Tutorials: [
|
||||
'tutorials/quickstart-app-plugin',
|
||||
'tutorials/react-router-stable-migration',
|
||||
'tutorials/react18-migration',
|
||||
'tutorials/package-role-migration',
|
||||
'tutorials/migrating-away-from-core',
|
||||
'tutorials/configuring-plugin-databases',
|
||||
'tutorials/switching-sqlite-postgres',
|
||||
'tutorials/using-backstage-proxy-within-plugin',
|
||||
'tutorials/yarn-migration',
|
||||
'tutorials/migrate-to-mui5',
|
||||
'tutorials/auth-service-migration',
|
||||
'tutorials/enable-public-entry',
|
||||
'tutorials/setup-opentelemetry',
|
||||
{ 'Non-technical': ['overview/adopting'] },
|
||||
{
|
||||
Techical: [
|
||||
'tutorials/quickstart-app-plugin',
|
||||
'tutorials/configuring-plugin-databases',
|
||||
'tutorials/switching-sqlite-postgres',
|
||||
'tutorials/using-backstage-proxy-within-plugin',
|
||||
'tutorials/enable-public-entry',
|
||||
'tutorials/setup-opentelemetry',
|
||||
'accessibility/index',
|
||||
],
|
||||
},
|
||||
{
|
||||
Migrations: [
|
||||
'tutorials/react-router-stable-migration',
|
||||
'tutorials/react18-migration',
|
||||
'tutorials/package-role-migration',
|
||||
'tutorials/migrating-away-from-core',
|
||||
'tutorials/yarn-migration',
|
||||
'tutorials/migrate-to-mui5',
|
||||
'tutorials/auth-service-migration',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
FAQ: ['faq/index', 'faq/product', 'faq/technical'],
|
||||
Accessibility: ['accessibility/index'],
|
||||
Contribute: [
|
||||
'contribute/index',
|
||||
'contribute/getting-involved',
|
||||
'contribute/project-structure',
|
||||
],
|
||||
References: [
|
||||
{
|
||||
'Designing for Backstage': [
|
||||
'dls/design',
|
||||
'dls/component-design-guidelines',
|
||||
'dls/contributing-to-storybook',
|
||||
'dls/figma',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Architecture Decision Records (ADRs)',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: justify;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@ const Community = () => {
|
||||
},
|
||||
{
|
||||
content: 'Subscribe to the',
|
||||
label: 'Community newsletter',
|
||||
label: 'Community Newsletter',
|
||||
link: 'https://info.backstage.spotify.com/newsletter_subscribe',
|
||||
},
|
||||
];
|
||||
|
||||
const officialInitiatives: ICollectionItem[] = [
|
||||
{
|
||||
title: 'Community sessions',
|
||||
title: 'Community Sessions',
|
||||
content:
|
||||
'Maintainers and adopters meet monthly to share updates, demos, and ideas. You can find recorded session on our YouTube channel!',
|
||||
link: 'https://github.com/backstage/community/tree/main/backstage-community-sessions#backstage-community-sessions',
|
||||
@@ -63,6 +63,13 @@ const Community = () => {
|
||||
link: 'https://training.linuxfoundation.org/training/introduction-to-backstage-developer-portals-made-easy-lfs142x/',
|
||||
label: 'Learn more',
|
||||
},
|
||||
{
|
||||
title: 'Certified Backstage Associate (CBA)',
|
||||
content:
|
||||
'Designed for IT engineers, developers, platform engineers, and other IT professionals, the CBA proves you have the skills and the mindset to work with Backstage.',
|
||||
link: 'https://www.cncf.io/training/certification/cba/',
|
||||
label: 'Learn more',
|
||||
},
|
||||
];
|
||||
|
||||
const partners: { name: string; url: string; logo: string }[] = [
|
||||
@@ -125,11 +132,10 @@ const Community = () => {
|
||||
>
|
||||
Join the vibrant community around Backstage through social media
|
||||
and different meetups. To ensure that you have a welcoming
|
||||
environment, we follow the
|
||||
environment, we follow the{' '}
|
||||
<Link to="https://github.com/cncf/foundation/blob/master/code-of-conduct.md">
|
||||
{' '}
|
||||
CNCF Code of Conduct{' '}
|
||||
</Link>
|
||||
CNCF Code of Conduct
|
||||
</Link>{' '}
|
||||
in everything we do.
|
||||
</ContentBlock>
|
||||
|
||||
@@ -159,7 +165,7 @@ const Community = () => {
|
||||
<BannerSectionGrid
|
||||
header={
|
||||
<>
|
||||
<h2 className="text--primary">Offical Backstage initiatives</h2>
|
||||
<h2 className="text--primary">Offical Backstage Initiatives</h2>
|
||||
|
||||
<h1>Stay tuned to the latest developments</h1>
|
||||
</>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
.banner {
|
||||
p {
|
||||
flex: 1;
|
||||
text-align: justify;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
iframe {
|
||||
|
||||
@@ -20,16 +20,12 @@
|
||||
"license": "Apache-2.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./alpha": "./src/alpha.ts",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"alpha": [
|
||||
"src/alpha.ts"
|
||||
],
|
||||
"package.json": [
|
||||
"package.json"
|
||||
]
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
## API Report File for "@backstage/backend-app-api"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { FeatureDiscoveryService } from '@backstage/backend-plugin-api/alpha';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @alpha @deprecated (undocumented)
|
||||
export const featureDiscoveryServiceFactory: ServiceFactory<
|
||||
FeatureDiscoveryService,
|
||||
'root',
|
||||
'singleton'
|
||||
>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -1,328 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 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 {
|
||||
startTestBackend,
|
||||
mockServices,
|
||||
createMockDirectory,
|
||||
} from '@backstage/backend-test-utils';
|
||||
import { featureDiscoveryServiceFactory } from './featureDiscoveryServiceFactory';
|
||||
|
||||
const mockDir = createMockDirectory();
|
||||
process.argv[1] = mockDir.path;
|
||||
|
||||
const pluginApiPath = require.resolve('@backstage/backend-plugin-api');
|
||||
|
||||
describe('featureDiscoveryServiceFactory', () => {
|
||||
beforeEach(() => {
|
||||
mockDir.setContent({
|
||||
'package.json': JSON.stringify({
|
||||
name: 'example-app',
|
||||
dependencies: {
|
||||
'detected-plugin': '0.0.0',
|
||||
'detected-module': '0.0.0',
|
||||
'detected-plugin-with-alpha': '0.0.0',
|
||||
'detected-library': '0.0.0',
|
||||
},
|
||||
}),
|
||||
'node_modules/detected-plugin': {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'detected-plugin',
|
||||
main: 'index.js',
|
||||
backstage: {
|
||||
role: 'backend-plugin',
|
||||
},
|
||||
}),
|
||||
'index.js': `
|
||||
const { createBackendPlugin, coreServices } = require('${pluginApiPath}');
|
||||
exports.default = createBackendPlugin({
|
||||
pluginId: 'detected',
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: { logger: coreServices.rootLogger },
|
||||
async init({ logger }) {
|
||||
logger.warn('detected-plugin');
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
},
|
||||
'node_modules/detected-module': {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'detected-module',
|
||||
main: 'index.js',
|
||||
backstage: {
|
||||
role: 'backend-plugin-module',
|
||||
},
|
||||
}),
|
||||
'index.js': `
|
||||
const { createBackendModule, coreServices } = require('${pluginApiPath}');
|
||||
exports.default = createBackendModule({
|
||||
pluginId: 'detected',
|
||||
moduleId: 'derp',
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: { logger: coreServices.rootLogger },
|
||||
async init({ logger }) {
|
||||
logger.warn('detected-module');
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
},
|
||||
'node_modules/detected-plugin-with-alpha': {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'detected-plugin-with-alpha',
|
||||
main: 'index.js',
|
||||
exports: {
|
||||
'.': {
|
||||
default: 'index.js',
|
||||
},
|
||||
'./alpha': {
|
||||
default: 'alpha.js',
|
||||
},
|
||||
'./package.json': './package.json',
|
||||
},
|
||||
backstage: {
|
||||
role: 'backend-plugin',
|
||||
},
|
||||
}),
|
||||
'index.js': `exports.default = undefined;`,
|
||||
'alpha.js': `
|
||||
const { createBackendPlugin, coreServices } = require('${pluginApiPath}');
|
||||
exports.default = createBackendPlugin({
|
||||
pluginId: 'detected-alpha',
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: { logger: coreServices.rootLogger },
|
||||
async init({ logger }) {
|
||||
logger.warn('detected-plugin-with-alpha');
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
},
|
||||
'node_modules/detected-library': {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'detected-library',
|
||||
main: 'index.js',
|
||||
backstage: {
|
||||
role: 'node-library',
|
||||
},
|
||||
}),
|
||||
'index.js': `
|
||||
const { createServiceFactory, createServiceRef, coreServices } = require('${pluginApiPath}');
|
||||
exports.default = createServiceFactory({
|
||||
service: createServiceRef({ id: 'test', scope: 'root' }),
|
||||
deps: { logger: coreServices.rootLogger },
|
||||
factory({ logger }) {
|
||||
logger.warn('detected-library');
|
||||
return {};
|
||||
},
|
||||
});
|
||||
`,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should detect plugin and module packages when "all" is specified', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: { backend: { packages: 'all' } },
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-module');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin-with-alpha');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-library');
|
||||
});
|
||||
|
||||
it('detects only the packages that are listed as included', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
packages: {
|
||||
include: [
|
||||
'detected-plugin',
|
||||
'detected-plugin-with-alpha',
|
||||
'detected-library',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin-with-alpha');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-library');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-module');
|
||||
});
|
||||
|
||||
it('does not detect packages when included is an empty list', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
packages: {
|
||||
include: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-plugin');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-plugin-with-alpha');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-module');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-library');
|
||||
});
|
||||
|
||||
it('does not detect an excluded packages', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
packages: {
|
||||
exclude: ['detected-plugin', 'detected-module'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-plugin');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-module');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin-with-alpha');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-library');
|
||||
});
|
||||
|
||||
it('does not excluded packages when it is an empty list', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
packages: {
|
||||
exclude: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-module');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin-with-alpha');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-library');
|
||||
});
|
||||
|
||||
it('does not detect packages that are included and excluded', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
packages: {
|
||||
include: [
|
||||
'detected-plugin',
|
||||
'detected-module',
|
||||
'detected-plugin-with-alpha',
|
||||
],
|
||||
exclude: ['detected-module'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-library');
|
||||
expect(mock.warn).not.toHaveBeenCalledWith('detected-module');
|
||||
expect(mock.warn).toHaveBeenCalledWith('detected-plugin-with-alpha');
|
||||
});
|
||||
|
||||
it('does not detect any packages when "packages" is empty', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: { backend: { packages: {} } },
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not detect any packages when "packages" is not present', async () => {
|
||||
const mock = mockServices.rootLogger.mock({ child: () => mock });
|
||||
|
||||
await startTestBackend({
|
||||
features: [
|
||||
mock.factory,
|
||||
featureDiscoveryServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: { backend: {} },
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(mock.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 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,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { featureDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { PackageDiscoveryService } from '../../../backend-defaults/src/PackageDiscoveryService';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated The `featureDiscoveryServiceFactory` is deprecated in favor of using {@link @backstage/backend-defaults#discoveryFeatureLoader} instead.
|
||||
*/
|
||||
export const featureDiscoveryServiceFactory = createServiceFactory({
|
||||
service: featureDiscoveryServiceRef,
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
logger: coreServices.rootLogger,
|
||||
},
|
||||
factory({ config, logger }) {
|
||||
return new PackageDiscoveryService(config, logger);
|
||||
},
|
||||
});
|
||||
@@ -37,7 +37,6 @@ import type { InternalServiceFactory } from '../../../backend-plugin-api/src/ser
|
||||
import { ForwardedError, ConflictError, assertError } from '@backstage/errors';
|
||||
import {
|
||||
instanceMetadataServiceRef,
|
||||
featureDiscoveryServiceRef,
|
||||
BackendFeatureMeta,
|
||||
} from '@backstage/backend-plugin-api/alpha';
|
||||
import { DependencyGraph } from '../lib/DependencyGraph';
|
||||
@@ -252,20 +251,6 @@ export class BackendInitializer {
|
||||
this.#addFeature(await feature);
|
||||
}
|
||||
|
||||
const featureDiscovery = await this.#serviceRegistry.get(
|
||||
// TODO: Let's leave this in place and remove it once the deprecated service is removed. We can do that post-1.0 since it's alpha
|
||||
featureDiscoveryServiceRef,
|
||||
'root',
|
||||
);
|
||||
|
||||
if (featureDiscovery) {
|
||||
const { features } = await featureDiscovery.getBackendFeatures();
|
||||
for (const feature of features) {
|
||||
this.#addFeature(unwrapFeature(feature));
|
||||
}
|
||||
this.#serviceRegistry.checkForCircularDeps();
|
||||
}
|
||||
|
||||
await this.#applyBackendFeatureLoaders(this.#registeredFeatureLoaders);
|
||||
|
||||
this.#serviceRegistry.add(
|
||||
|
||||
+4
@@ -429,6 +429,10 @@ export interface Config {
|
||||
* The instance connection name for the cloudsql instance, e.g. `project:region:instance`
|
||||
*/
|
||||
instance: string;
|
||||
/**
|
||||
* The ip address type to use for the connection. Defaults to 'PUBLIC'
|
||||
*/
|
||||
ipAddressType?: 'PUBLIC' | 'PRIVATE' | 'PSC';
|
||||
}
|
||||
| {
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
RootConfigService,
|
||||
RootLoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { FeatureDiscoveryService } from '@backstage/backend-plugin-api/alpha';
|
||||
import { BackstagePackageJson } from '@backstage/cli-node';
|
||||
|
||||
const DETECTED_PACKAGE_ROLES = [
|
||||
@@ -79,7 +78,7 @@ async function findClosestPackageDir(
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class PackageDiscoveryService implements FeatureDiscoveryService {
|
||||
export class PackageDiscoveryService {
|
||||
constructor(
|
||||
private readonly config: RootConfigService,
|
||||
private readonly logger: RootLoggerService,
|
||||
|
||||
@@ -221,6 +221,63 @@ describe('postgres', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('passes default settings to cloud-sql-connector', async () => {
|
||||
const { Connector } = jest.requireMock(
|
||||
'@google-cloud/cloud-sql-connector',
|
||||
) as jest.Mocked<typeof import('@google-cloud/cloud-sql-connector')>;
|
||||
|
||||
const mockStream = (): any => {};
|
||||
Connector.prototype.getOptions.mockResolvedValue({ stream: mockStream });
|
||||
|
||||
await buildPgDatabaseConfig(
|
||||
new ConfigReader({
|
||||
client: 'pg',
|
||||
connection: {
|
||||
type: 'cloudsql',
|
||||
user: 'ben@gke.com',
|
||||
instance: 'project:region:instance',
|
||||
port: 5423,
|
||||
},
|
||||
}),
|
||||
{ connection: { database: 'other_db' } },
|
||||
);
|
||||
|
||||
expect(Connector.prototype.getOptions).toHaveBeenCalledWith({
|
||||
authType: 'IAM',
|
||||
instanceConnectionName: 'project:region:instance',
|
||||
ipType: 'PUBLIC',
|
||||
});
|
||||
});
|
||||
|
||||
it('passes ip settings to cloud-sql-connector', async () => {
|
||||
const { Connector } = jest.requireMock(
|
||||
'@google-cloud/cloud-sql-connector',
|
||||
) as jest.Mocked<typeof import('@google-cloud/cloud-sql-connector')>;
|
||||
|
||||
const mockStream = (): any => {};
|
||||
Connector.prototype.getOptions.mockResolvedValue({ stream: mockStream });
|
||||
|
||||
await buildPgDatabaseConfig(
|
||||
new ConfigReader({
|
||||
client: 'pg',
|
||||
connection: {
|
||||
type: 'cloudsql',
|
||||
user: 'ben@gke.com',
|
||||
instance: 'project:region:instance',
|
||||
ipAddressType: 'PRIVATE',
|
||||
port: 5423,
|
||||
},
|
||||
}),
|
||||
{ connection: { database: 'other_db' } },
|
||||
);
|
||||
|
||||
expect(Connector.prototype.getOptions).toHaveBeenCalledWith({
|
||||
authType: 'IAM',
|
||||
instanceConnectionName: 'project:region:instance',
|
||||
ipType: 'PRIVATE',
|
||||
});
|
||||
});
|
||||
|
||||
it('throws an error when the connection type is not supported', async () => {
|
||||
await expect(
|
||||
buildPgDatabaseConfig(
|
||||
|
||||
@@ -107,7 +107,7 @@ export async function buildPgDatabaseConfig(
|
||||
const connector = new CloudSqlConnector();
|
||||
const clientOpts = await connector.getOptions({
|
||||
instanceConnectionName: config.connection.instance,
|
||||
ipType: IpAddressTypes.PUBLIC,
|
||||
ipType: config.connection.ipAddressType ?? IpAddressTypes.PUBLIC,
|
||||
authType: AuthTypes.IAM,
|
||||
});
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
"test": "backstage-cli package test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-app-api": "workspace:^",
|
||||
"@backstage/backend-common": "^0.25.0",
|
||||
"@backstage/backend-defaults": "workspace:^",
|
||||
"@backstage/backend-plugin-api": "workspace:^",
|
||||
@@ -74,6 +73,7 @@
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-app-api": "workspace:^",
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-app-backend": "workspace:^",
|
||||
|
||||
@@ -13,7 +13,6 @@ import { DiscoveryService } from '@backstage/backend-plugin-api';
|
||||
import { EventBroker } from '@backstage/plugin-events-node';
|
||||
import { EventsBackend } from '@backstage/plugin-events-backend';
|
||||
import { EventsService } from '@backstage/plugin-events-node';
|
||||
import { FeatureDiscoveryService } from '@backstage/backend-plugin-api/alpha';
|
||||
import { HttpPostIngressOptions } from '@backstage/plugin-events-node';
|
||||
import { IdentityApi } from '@backstage/plugin-auth-node';
|
||||
import { IndexBuilder } from '@backstage/plugin-search-backend-node';
|
||||
@@ -150,13 +149,6 @@ export interface DynamicPluginsFactoryOptions {
|
||||
// @public @deprecated (undocumented)
|
||||
export const dynamicPluginsFeatureDiscoveryLoader: BackendFeature;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const dynamicPluginsFeatureDiscoveryServiceFactory: ServiceFactory<
|
||||
FeatureDiscoveryService,
|
||||
'root',
|
||||
'singleton'
|
||||
>;
|
||||
|
||||
// @public
|
||||
export const dynamicPluginsFeatureLoader: ((
|
||||
options?: DynamicPluginsFeatureLoaderOptions,
|
||||
|
||||
@@ -32,7 +32,6 @@ export type {
|
||||
|
||||
export {
|
||||
DynamicPluginManager,
|
||||
dynamicPluginsFeatureDiscoveryServiceFactory,
|
||||
dynamicPluginsServiceFactory,
|
||||
dynamicPluginsServiceFactoryWithOptions,
|
||||
dynamicPluginsServiceRef,
|
||||
|
||||
@@ -37,10 +37,6 @@ import {
|
||||
import { PackageRole, PackageRoles } from '@backstage/cli-node';
|
||||
import { findPaths } from '@backstage/cli-common';
|
||||
import * as fs from 'fs';
|
||||
import {
|
||||
FeatureDiscoveryService,
|
||||
featureDiscoveryServiceRef,
|
||||
} from '@backstage/backend-plugin-api/alpha';
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -307,55 +303,27 @@ export const dynamicPluginsServiceFactory = Object.assign(
|
||||
dynamicPluginsServiceFactoryWithOptions(),
|
||||
);
|
||||
|
||||
class DynamicPluginsEnabledFeatureDiscoveryService
|
||||
implements FeatureDiscoveryService
|
||||
{
|
||||
constructor(
|
||||
private readonly dynamicPlugins: DynamicPluginProvider,
|
||||
private readonly featureDiscoveryService?: FeatureDiscoveryService,
|
||||
) {}
|
||||
class DynamicPluginsEnabledFeatureDiscoveryService {
|
||||
constructor(private readonly dynamicPlugins: DynamicPluginProvider) {}
|
||||
|
||||
async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {
|
||||
const staticFeatures =
|
||||
(await this.featureDiscoveryService?.getBackendFeatures())?.features ??
|
||||
[];
|
||||
|
||||
return {
|
||||
features: [
|
||||
...this.dynamicPlugins
|
||||
.backendPlugins()
|
||||
.flatMap((plugin): BackendFeature[] => {
|
||||
if (plugin.installer?.kind === 'new') {
|
||||
const installed = plugin.installer.install();
|
||||
if (Array.isArray(installed)) {
|
||||
return installed;
|
||||
}
|
||||
return [installed];
|
||||
features: this.dynamicPlugins
|
||||
.backendPlugins()
|
||||
.flatMap((plugin): BackendFeature[] => {
|
||||
if (plugin.installer?.kind === 'new') {
|
||||
const installed = plugin.installer.install();
|
||||
if (Array.isArray(installed)) {
|
||||
return installed;
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
...staticFeatures,
|
||||
],
|
||||
return [installed];
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.
|
||||
*/
|
||||
export const dynamicPluginsFeatureDiscoveryServiceFactory =
|
||||
createServiceFactory({
|
||||
service: featureDiscoveryServiceRef,
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
dynamicPlugins: dynamicPluginsServiceRef,
|
||||
},
|
||||
factory({ dynamicPlugins }) {
|
||||
return new DynamicPluginsEnabledFeatureDiscoveryService(dynamicPlugins);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
> 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 { ServiceRef } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @alpha (undocumented)
|
||||
@@ -18,21 +17,6 @@ export type BackendFeatureMeta =
|
||||
moduleId: string;
|
||||
};
|
||||
|
||||
// @alpha (undocumented)
|
||||
export interface FeatureDiscoveryService {
|
||||
// (undocumented)
|
||||
getBackendFeatures(): Promise<{
|
||||
features: Array<BackendFeature>;
|
||||
}>;
|
||||
}
|
||||
|
||||
// @alpha @deprecated
|
||||
export const featureDiscoveryServiceRef: ServiceRef<
|
||||
FeatureDiscoveryService,
|
||||
'root',
|
||||
'singleton'
|
||||
>;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export interface InstanceMetadataService {
|
||||
// (undocumented)
|
||||
|
||||
@@ -14,26 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
BackendFeature,
|
||||
createServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @alpha */
|
||||
export interface FeatureDiscoveryService {
|
||||
getBackendFeatures(): Promise<{ features: Array<BackendFeature> }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional service that can be used to dynamically load in additional BackendFeatures at runtime.
|
||||
* @alpha
|
||||
* @deprecated The `featureDiscoveryServiceRef` is deprecated in favor of using {@link @backstage/backend-defaults#discoveryFeatureLoader} instead.
|
||||
*/
|
||||
export const featureDiscoveryServiceRef =
|
||||
createServiceRef<FeatureDiscoveryService>({
|
||||
id: 'core.featureDiscovery',
|
||||
scope: 'root',
|
||||
});
|
||||
import { createServiceRef } from '@backstage/backend-plugin-api';
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL: Instance metadata service.
|
||||
|
||||
@@ -12,6 +12,9 @@ export type BackstagePackage = {
|
||||
packageJson: BackstagePackageJson;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type BackstagePackageFeatureType = (typeof packageFeatureType)[number];
|
||||
|
||||
// @public
|
||||
export interface BackstagePackageJson {
|
||||
// (undocumented)
|
||||
@@ -22,6 +25,7 @@ export interface BackstagePackageJson {
|
||||
pluginId?: string | null;
|
||||
pluginPackage?: string;
|
||||
pluginPackages?: string[];
|
||||
features?: Record<string, BackstagePackageFeatureType>;
|
||||
};
|
||||
// (undocumented)
|
||||
bundled?: boolean;
|
||||
@@ -112,6 +116,14 @@ export type LockfileDiffEntry = {
|
||||
range: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const packageFeatureType: readonly [
|
||||
'@backstage/BackendFeature',
|
||||
'@backstage/BackstagePlugin',
|
||||
'@backstage/FrontendPlugin',
|
||||
'@backstage/FrontendModule',
|
||||
];
|
||||
|
||||
// @public
|
||||
export class PackageGraph extends Map<string, PackageGraphNode> {
|
||||
collectPackageNames(
|
||||
|
||||
@@ -22,6 +22,24 @@ import { GitUtils } from '../git';
|
||||
import { Lockfile } from './Lockfile';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
|
||||
/**
|
||||
* A list of the feature types we want to extract from the project
|
||||
* and include in the metadata
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const packageFeatureType = [
|
||||
'@backstage/BackendFeature',
|
||||
'@backstage/BackstagePlugin',
|
||||
'@backstage/FrontendPlugin',
|
||||
'@backstage/FrontendModule',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type BackstagePackageFeatureType = (typeof packageFeatureType)[number];
|
||||
|
||||
/**
|
||||
* Known fields in Backstage package.json files.
|
||||
*
|
||||
@@ -72,6 +90,11 @@ export interface BackstagePackageJson {
|
||||
* All packages that are part of the plugin. Must always and only be set for plugin packages and plugin library packages.
|
||||
*/
|
||||
pluginPackages?: string[];
|
||||
|
||||
/**
|
||||
* The feature types exported from the package, indexed by path.
|
||||
*/
|
||||
features?: Record<string, BackstagePackageFeatureType>;
|
||||
};
|
||||
|
||||
exports?: JsonValue;
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
export { isMonoRepo } from './isMonoRepo';
|
||||
export {
|
||||
packageFeatureType,
|
||||
PackageGraph,
|
||||
type PackageGraphNode,
|
||||
type BackstagePackage,
|
||||
type BackstagePackageJson,
|
||||
type BackstagePackageFeatureType,
|
||||
} from './PackageGraph';
|
||||
export {
|
||||
Lockfile,
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { PackageRole } from '@backstage/cli-node';
|
||||
import { PackageRole, BackstagePackageFeatureType } from '@backstage/cli-node';
|
||||
import { Project } from 'ts-morph';
|
||||
import { BackstagePackageFeatureType } from '../typeDistProject';
|
||||
|
||||
const mockEntryPoint = 'dist/index.d.ts';
|
||||
|
||||
|
||||
@@ -188,7 +188,16 @@ async function rewriteEntryPoints(
|
||||
// This ensures that the `backstage` field is at the top of the
|
||||
// `exports` field in the package.json because order is important.
|
||||
// https://nodejs.org/docs/latest-v20.x/api/packages.html#conditional-exports
|
||||
//
|
||||
// Adding this to the `exports` field in the package.json is to temporarily
|
||||
// support any existing behavior that relies on this, however not all packages
|
||||
// have exports field in their package.json.
|
||||
exp = { backstage: defaultFeatureType, ...exp };
|
||||
|
||||
// Add the default feature type to the backstage metadata in the package.json
|
||||
pkg.backstage = pkg.backstage ?? {};
|
||||
pkg.backstage.features = pkg.backstage.features ?? {};
|
||||
pkg.backstage.features[entryPoint.mount] = defaultFeatureType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { PackageRole } from '@backstage/cli-node';
|
||||
import { PackageRole, BackstagePackageFeatureType } from '@backstage/cli-node';
|
||||
import createFeatureEnvironment from './__testUtils__/createFeatureEnvironment';
|
||||
import {
|
||||
getEntryPointDefaultFeatureType,
|
||||
BackstagePackageFeatureType,
|
||||
} from './typeDistProject';
|
||||
import { getEntryPointDefaultFeatureType } from './typeDistProject';
|
||||
|
||||
describe('typeDistProject', () => {
|
||||
describe('for package role', () => {
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { PackageRole } from '@backstage/cli-node';
|
||||
import {
|
||||
BackstagePackageFeatureType,
|
||||
packageFeatureType,
|
||||
PackageRole,
|
||||
} from '@backstage/cli-node';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import { Project, SourceFile, SyntaxKind, ts, Type } from 'ts-morph';
|
||||
import { paths } from './paths';
|
||||
@@ -35,17 +39,6 @@ const targetPackageRoles: PackageRole[] = [
|
||||
'node-library',
|
||||
];
|
||||
|
||||
// A list of the feature types we want to extract from the project
|
||||
// and include in the metadata
|
||||
const targetFeatureTypes = [
|
||||
'@backstage/BackendFeature',
|
||||
'@backstage/BackstagePlugin',
|
||||
'@backstage/FrontendPlugin',
|
||||
'@backstage/FrontendModule',
|
||||
] as const;
|
||||
|
||||
export type BackstagePackageFeatureType = (typeof targetFeatureTypes)[number];
|
||||
|
||||
export const getEntryPointDefaultFeatureType = (
|
||||
role: PackageRole,
|
||||
packageDir: string,
|
||||
@@ -146,6 +139,6 @@ function isTargetFeatureType(
|
||||
type: string | BackstagePackageFeatureType,
|
||||
): type is BackstagePackageFeatureType {
|
||||
return (
|
||||
!!type && targetFeatureTypes.includes(type as BackstagePackageFeatureType)
|
||||
!!type && packageFeatureType.includes(type as BackstagePackageFeatureType)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@backstage/theme": "workspace:^",
|
||||
"@backstage/version-bridge": "workspace:^",
|
||||
"@dagrejs/dagre": "^1.1.4",
|
||||
"@date-io/core": "^1.3.13",
|
||||
"@material-table/core": "^3.1.0",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
@@ -72,7 +73,6 @@
|
||||
"d3-selection": "^3.0.0",
|
||||
"d3-shape": "^3.0.0",
|
||||
"d3-zoom": "^3.0.0",
|
||||
"dagre": "^0.8.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
"linkify-react": "4.1.3",
|
||||
"linkifyjs": "4.1.3",
|
||||
@@ -106,7 +106,6 @@
|
||||
"@types/d3-selection": "^3.0.1",
|
||||
"@types/d3-shape": "^3.0.1",
|
||||
"@types/d3-zoom": "^3.0.1",
|
||||
"@types/dagre": "^0.7.44",
|
||||
"@types/google-protobuf": "^3.7.2",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-helmet": "^6.1.0",
|
||||
|
||||
@@ -18,7 +18,7 @@ import React from 'react';
|
||||
import * as d3Zoom from 'd3-zoom';
|
||||
import * as d3Selection from 'd3-selection';
|
||||
import useTheme from '@material-ui/core/styles/useTheme';
|
||||
import dagre from 'dagre';
|
||||
import dagre from '@dagrejs/dagre';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { DependencyGraphTypes as Types } from './types';
|
||||
import { Node } from './Node';
|
||||
|
||||
@@ -21,7 +21,7 @@ import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
import { DependencyGraphTypes as Types } from './types';
|
||||
import { ARROW_MARKER_ID, EDGE_TEST_ID, LABEL_TEST_ID } from './constants';
|
||||
import { DefaultLabel } from './DefaultLabel';
|
||||
import dagre from 'dagre';
|
||||
import dagre from '@dagrejs/dagre';
|
||||
|
||||
/* Based on: https://github.com/dagrejs/dagre/wiki#configuring-the-layout */
|
||||
export type EdgeProperties = {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import dagre from 'dagre';
|
||||
import dagre from '@dagrejs/dagre';
|
||||
import { render } from '@testing-library/react';
|
||||
import { Node } from './Node';
|
||||
import { DependencyGraphTypes as Types } from './types';
|
||||
|
||||
@@ -19,7 +19,7 @@ import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
import { DefaultNode } from './DefaultNode';
|
||||
import { DependencyGraphTypes as Types } from './types';
|
||||
import { NODE_TEST_ID } from './constants';
|
||||
import dagre from 'dagre';
|
||||
import dagre from '@dagrejs/dagre';
|
||||
|
||||
/** @public */
|
||||
export type DependencyGraphNodeClassKey = 'node';
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -38,6 +40,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -30,6 +32,7 @@ export interface Config {
|
||||
audience?: string;
|
||||
connection?: string;
|
||||
connectionScope?: string;
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@types/passport-auth0": "^1.0.5",
|
||||
"@types/passport-oauth2": "^1.4.15",
|
||||
"supertest": "^7.0.0"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -48,6 +50,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"express": "^4.18.2",
|
||||
"msw": "^2.0.8"
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -36,6 +38,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -27,6 +29,7 @@ export interface Config {
|
||||
clientSecret: string;
|
||||
host: string;
|
||||
callbackUrl?: string;
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@types/passport-oauth2": "^1.4.15",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface Config {
|
||||
* The backstage token expiration.
|
||||
*/
|
||||
backstageTokenExpiration?: HumanDuration | string;
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -43,6 +45,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -38,6 +40,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -38,6 +40,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
/** Configuration options for the auth plugin */
|
||||
auth?: {
|
||||
@@ -38,6 +40,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@types/passport-google-oauth20": "^2.0.3",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -40,6 +42,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@types/passport-microsoft": "^1.0.0",
|
||||
"msw": "^1.0.0",
|
||||
"supertest": "^7.0.0"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -42,6 +44,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -40,6 +42,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"express-promise-router": "^4.1.1",
|
||||
"express-session": "^1.17.3",
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -40,6 +42,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -37,6 +39,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"supertest": "^7.0.0"
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"@backstage/backend-plugin-api": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/plugin-auth-node": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"luxon": "^3.4.3",
|
||||
"openid-client": "^5.4.3"
|
||||
},
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
/** Configuration options for the auth plugin */
|
||||
auth?: {
|
||||
@@ -27,6 +29,7 @@ export interface Config {
|
||||
*/
|
||||
clientSecret: string;
|
||||
scope?: string;
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
|
||||
export interface Config {
|
||||
auth?: {
|
||||
providers?: {
|
||||
@@ -34,6 +36,7 @@ export interface Config {
|
||||
| { resolver: 'emailMatchingUserEntityProfileEmail' }
|
||||
>;
|
||||
};
|
||||
sessionDuration?: HumanDuration | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@backstage/plugin-auth-backend": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"msw": "^2.0.8",
|
||||
"supertest": "^7.0.0"
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import { CookieOptions, Request, Response } from 'express';
|
||||
import { CookieConfigurer } from '../types';
|
||||
import { HumanDuration, durationToMilliseconds } from '@backstage/types';
|
||||
|
||||
const THOUSAND_DAYS_MS = 1000 * 24 * 60 * 60 * 1000;
|
||||
const TEN_MINUTES_MS = 600 * 1000;
|
||||
@@ -55,6 +56,7 @@ export class OAuthCookieManager {
|
||||
private readonly nonceCookie: string;
|
||||
private readonly refreshTokenCookie: string;
|
||||
private readonly grantedScopeCookie: string;
|
||||
private readonly maxAge: number;
|
||||
|
||||
constructor(
|
||||
private readonly options: {
|
||||
@@ -63,6 +65,7 @@ export class OAuthCookieManager {
|
||||
baseUrl: string;
|
||||
callbackUrl: string;
|
||||
cookieConfigurer?: CookieConfigurer;
|
||||
sessionDuration?: HumanDuration;
|
||||
},
|
||||
) {
|
||||
this.cookieConfigurer = options.cookieConfigurer ?? defaultCookieConfigurer;
|
||||
@@ -70,6 +73,9 @@ export class OAuthCookieManager {
|
||||
this.nonceCookie = `${options.providerId}-nonce`;
|
||||
this.refreshTokenCookie = `${options.providerId}-refresh-token`;
|
||||
this.grantedScopeCookie = `${options.providerId}-granted-scope`;
|
||||
this.maxAge = options.sessionDuration
|
||||
? durationToMilliseconds(options.sessionDuration)
|
||||
: THOUSAND_DAYS_MS;
|
||||
}
|
||||
|
||||
private getConfig(origin?: string, pathSuffix: string = '') {
|
||||
@@ -103,7 +109,7 @@ export class OAuthCookieManager {
|
||||
res,
|
||||
this.refreshTokenCookie,
|
||||
refreshToken,
|
||||
THOUSAND_DAYS_MS,
|
||||
this.maxAge,
|
||||
origin,
|
||||
);
|
||||
}
|
||||
@@ -117,13 +123,7 @@ export class OAuthCookieManager {
|
||||
}
|
||||
|
||||
setGrantedScopes(res: Response, scope: string, origin?: string): void {
|
||||
this.setCookie(
|
||||
res,
|
||||
this.grantedScopeCookie,
|
||||
scope,
|
||||
THOUSAND_DAYS_MS,
|
||||
origin,
|
||||
);
|
||||
this.setCookie(res, this.grantedScopeCookie, scope, this.maxAge, origin);
|
||||
}
|
||||
|
||||
getNonce(req: Request): string | undefined {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user