Merge branch 'master' of https://github.com/backstage/backstage into marley/7678-pull-request-dashboard
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Switched to relying on the built-in support for async loading in `react-syntax-highlighter`. This should provide further improvements to async rendering and lazy loading, and avoid test flakiness that was happening because of the significant number or resources being loaded in lazily all at once.
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Removed the included `jest` configuration from the root `package.json` as the `transformModules` option no longer exists.
|
||||
|
||||
To apply this change to an existing app, make the follow change to the root `package.json`:
|
||||
|
||||
```diff
|
||||
- "jest": {
|
||||
- "transformModules": [
|
||||
- "@asyncapi/react-component"
|
||||
- ]
|
||||
- }
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
Fix a bug preventing an access token to be refreshed a second time with the GitHub provider.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
---
|
||||
|
||||
Configuration schema errors are now filtered using the provided visibility option. This means that schema errors due to missing backend configuration will no longer break frontend builds.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-fossa': patch
|
||||
---
|
||||
|
||||
Add `entitiesFilter` option to `FossaPage` to filter entities displayed in the table.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
---
|
||||
|
||||
Capture analytics events for clicks in the graph.
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
'@backstage/create-app': minor
|
||||
---
|
||||
|
||||
Removed `@backstage/plugin-welcome`, no new updates to the packages will be
|
||||
published in the future.
|
||||
|
||||
The welcome plugin was used by early alpha versions of Backstage, but today only
|
||||
contained a simple page with welcome instructions. It was superseded by
|
||||
`@backstage/plugin-home` which can be used to build a homepage customized to the
|
||||
needs of your organization.
|
||||
|
||||
If it's still used in your app, remove the dependency from your `package.json`
|
||||
as well as left over code.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-jenkins': patch
|
||||
---
|
||||
|
||||
Sort Jenkins build by timestamp in `CITable`
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-git-release-manager': patch
|
||||
---
|
||||
|
||||
Minor internal type improvement
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Only replace the shadow dom if the content is changed to avoid a flickering UI.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/errors': patch
|
||||
---
|
||||
|
||||
Add `stringifyError` that is useful for logging e.g. `Something went wrong, ${stringifyError(e)}`
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': minor
|
||||
---
|
||||
|
||||
The Jest configuration that's included with the Backstage CLI has received several changes.
|
||||
|
||||
As a part of migrating to more widespread usage of ESM modules, the default configuration now transforms all source files everywhere, including those within `node_modules`. Due to this change the existing `transformModules` option has been removed and will be ignored. There is also a list of known packages that do not require transforms in the CLI, which will evolve over time. If needed there will also be an option to add packages to this list in the future, but it is not included yet to avoid clutter.
|
||||
|
||||
To counteract the slowdown of the additional transforms that have been introduced, the default configuration has also been reworked to enable caching across different packages. Previously each package in a Backstage monorepo would have its own isolated Jest cache, but it is now shared between packages that have a similar enough Jest configuration.
|
||||
|
||||
Another change that will speed up test execution is that the transformer for `.esm.js` files has been switched. It used to be an ESM transformer based on Babel, but it is also done by sucrase now since it is significantly faster.
|
||||
|
||||
The changes above are not strictly breaking as all tests should still work. It may however cause excessive slowdowns in projects that have configured custom transforms in the `jest` field within `package.json` files. In this case it is either best to consider removing the custom transforms, or overriding the `transformIgnorePatterns` to instead use Jest's default `'/node_modules/'` pattern.
|
||||
|
||||
This change also removes the `@backstage/cli/config/jestEsmTransform.js` transform, which can be replaced by using the `@backstage/cli/config/sucraseEsmTransform.js` transform instead.
|
||||
@@ -8,6 +8,7 @@ apis
|
||||
args
|
||||
asciidoc
|
||||
async
|
||||
Atlassian
|
||||
automations
|
||||
autoscaling
|
||||
Autoscaling
|
||||
@@ -310,3 +311,4 @@ Zalando
|
||||
Zhou
|
||||
zoomable
|
||||
zsh
|
||||
Firestore
|
||||
|
||||
@@ -58,3 +58,4 @@
|
||||
| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. |
|
||||
| [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. |
|
||||
| [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. |
|
||||
| [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. |
|
||||
|
||||
@@ -292,6 +292,15 @@ scaffolder:
|
||||
visibility: public # or or 'private'
|
||||
|
||||
auth:
|
||||
### Add auth.keyStore.provider to more granularly control how to store JWK data when running
|
||||
# the auth-backend.
|
||||
#
|
||||
# keyStore:
|
||||
# provider: firestore
|
||||
# firestore:
|
||||
# projectId: my-project
|
||||
# path: my-sessions
|
||||
|
||||
environment: development
|
||||
### Providing an auth.session.secret will enable session support in the auth-backend
|
||||
# session:
|
||||
@@ -364,6 +373,11 @@ auth:
|
||||
development:
|
||||
clientId: ${AUTH_BITBUCKET_CLIENT_ID}
|
||||
clientSecret: ${AUTH_BITBUCKET_CLIENT_SECRET}
|
||||
atlassian:
|
||||
development:
|
||||
clientId: ${AUTH_ATLASSIAN_CLIENT_ID}
|
||||
clientSecret: ${AUTH_ATLASSIAN_CLIENT_SECRET}
|
||||
scopes: ${AUTH_ATLASSIAN_SCOPES}
|
||||
costInsights:
|
||||
engineerCost: 200000
|
||||
products:
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: provider
|
||||
title: Atlassian Authentication Provider
|
||||
sidebar_label: Atlassian
|
||||
description: Adding Atlassian as an authentication provider in Backstage
|
||||
---
|
||||
|
||||
The Backstage `core-plugin-api` package comes with an Atlassian authentication
|
||||
provider that can authenticate users using Atlassian products. This auth
|
||||
**only** provides scopes for the following APIs:
|
||||
|
||||
- Confluence API
|
||||
- User REST API
|
||||
- Jira platform REST API
|
||||
- Jira Service Desk API
|
||||
- Personal data reporting API
|
||||
- User identity API
|
||||
|
||||
## Create an OAuth 2.0 (3LO) app in the Atlassian developer console
|
||||
|
||||
To add Atlassian authentication, you must create an OAuth 2.0 (3LO) app.
|
||||
|
||||
Go to `https://developer.atlassian.com/console/myapps/`.
|
||||
|
||||
Click on the drop down `Create`, and choose `OAuth 2.0 integration`.
|
||||
|
||||
Name your integration and click on the `Create` button.
|
||||
|
||||
Settings for local development:
|
||||
|
||||
- Callback URL: `http://localhost:7000/api/auth/atlassian`
|
||||
- Use rotating refresh tokens
|
||||
- For permissions, you **must** enable `View user profile` for the currently
|
||||
logged-in user, under `User identity API`
|
||||
|
||||
## Configuration
|
||||
|
||||
The provider configuration can then be added to your `app-config.yaml` under the
|
||||
root `auth` configuration:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
environment: development
|
||||
providers:
|
||||
atlassian:
|
||||
development:
|
||||
clientId: ${AUTH_ATLASSIAN_CLIENT_ID}
|
||||
clientSecret: ${AUTH_ATLASSIAN_CLIENT_SECRET}
|
||||
scopes: ${AUTH_ATLASSIAN_SCOPES}
|
||||
```
|
||||
|
||||
The Atlassian provider is a structure with three configuration keys:
|
||||
|
||||
- `clientId`: The Key you generated in the developer console.
|
||||
- `clientSecret`: The Secret tied to the generated Key.
|
||||
- `scopes`: List of scopes the app has permissions for, separated by spaces.
|
||||
|
||||
**NOTE:** the scopes `offline_access` and `read:me` are provided by default.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `atlassianAuthApi` reference and
|
||||
`SignInPage` component as shown in
|
||||
[Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page).
|
||||
@@ -29,6 +29,7 @@ kubernetes:
|
||||
serviceAccountToken: ${K8S_MINIKUBE_TOKEN}
|
||||
dashboardUrl: http://127.0.0.1:64713 # url copied from running the command: minikube service kubernetes-dashboard -n kubernetes-dashboard
|
||||
dashboardApp: standard
|
||||
caData: ${K8S_CONFIG_CA_DATA}
|
||||
- url: http://127.0.0.2:9999
|
||||
name: aws-cluster-1
|
||||
authProvider: 'aws'
|
||||
@@ -135,6 +136,24 @@ See also
|
||||
https://github.com/backstage/backstage/tree/master/plugins/kubernetes/src/utils/clusterLinks/formatters
|
||||
for real examples.
|
||||
|
||||
##### `clusters.\*.caData` (optional)
|
||||
|
||||
PEM-encoded certificate authority certificates.
|
||||
|
||||
This values could be obtained via inspecting the Kubernetes config file (usually
|
||||
at `~/.kube/config`) under `clusters.cluster.certificate-authority-data`. For
|
||||
GKE, execute the following command to obtain the value
|
||||
|
||||
```
|
||||
gcloud container clusters describe <YOUR_CLUSTER_NAME> \
|
||||
--zone=<YOUR_COMPUTE_ZONE> \
|
||||
--format="value(masterAuth.clusterCaCertificate)"
|
||||
```
|
||||
|
||||
See also
|
||||
https://cloud.google.com/kubernetes-engine/docs/how-to/api-server-authentication#environments-without-gcloud
|
||||
for complete docs about GKE without `gcloud`.
|
||||
|
||||
#### `gke`
|
||||
|
||||
This cluster locator is designed to work with Kubernetes clusters running in
|
||||
|
||||
@@ -38,7 +38,7 @@ up and running and to start writing your documentation.
|
||||
|
||||
If you have created software templates that do not include documentation by
|
||||
default, we highly recommend you to set that up. Follow our how-to guide
|
||||
[How to add documentation setup to your software templates](./how-to-guides.md#how-to-add-documentation-setup-to-your-software-templates)
|
||||
[How to add documentation setup to your software templates](./how-to-guides.md#how-to-add-the-documentation-setup-to-your-software-templates)
|
||||
to get started.
|
||||
|
||||
### Use the documentation template
|
||||
|
||||
@@ -215,10 +215,10 @@ techdocs:
|
||||
publisher:
|
||||
type: 'local'
|
||||
generator:
|
||||
techdocs: local
|
||||
runIn: local
|
||||
```
|
||||
|
||||
Setting `generators.techdocs` to `local` means you will have to make sure your
|
||||
Setting `generator.runIn` to `local` means you will have to make sure your
|
||||
environment is compatible with techdocs.
|
||||
|
||||
You will have to install the `mkdocs` and `mkdocs-techdocs-core` package from
|
||||
|
||||
@@ -110,7 +110,8 @@ TechDocs uses a composability pattern similar to the Search and Catalog plugins
|
||||
in Backstage. While a default table experience, similar to the one provided by
|
||||
the Catalog plugin, is made available for ease-of-use, it's possible for you to
|
||||
provide a completely custom experience, tailored to the needs of your
|
||||
organization.
|
||||
organization. For example, TechDocs comes with an alternative grid based layout
|
||||
(`<EntityListDocsGrid>`).
|
||||
|
||||
This is done in your `app` package. By default, you might see something like
|
||||
this in your `App.tsx`:
|
||||
|
||||
@@ -7,7 +7,7 @@ description: Importing users and groups from a Microsoft Azure Active Directory
|
||||
---
|
||||
|
||||
The Backstage catalog can be set up to ingest organizational data - users and
|
||||
teams - directly from an tenant in Microsoft Azure Active Directory via the
|
||||
teams - directly from a tenant in Microsoft Azure Active Directory via the
|
||||
Microsoft Graph API.
|
||||
|
||||
More details on this are available in the
|
||||
|
||||
@@ -213,6 +213,7 @@
|
||||
"label": "Included providers",
|
||||
"ids": [
|
||||
"auth/auth0/provider",
|
||||
"auth/atlassian/provider",
|
||||
"auth/bitbucket/provider",
|
||||
"auth/microsoft/provider",
|
||||
"auth/github/provider",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.7.1
|
||||
- @backstage/plugin-techdocs@0.12.3
|
||||
- @backstage/plugin-sentry@0.3.26
|
||||
- @backstage/plugin-user-settings@0.3.10
|
||||
- @backstage/plugin-catalog-graph@0.2.1
|
||||
- @backstage/plugin-jenkins@0.5.11
|
||||
- @backstage/core-app-api@0.1.18
|
||||
- @backstage/core-plugin-api@0.1.11
|
||||
- @backstage/cli@0.8.0
|
||||
- @backstage/plugin-catalog@0.7.2
|
||||
- @backstage/plugin-catalog-import@0.7.3
|
||||
- @backstage/plugin-catalog-react@0.6.1
|
||||
- @backstage/catalog-model@0.9.5
|
||||
|
||||
## 0.2.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+14
-14
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.50",
|
||||
"version": "0.2.51",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.9.4",
|
||||
"@backstage/cli": "^0.7.16",
|
||||
"@backstage/core-app-api": "^0.1.17",
|
||||
"@backstage/core-components": "^0.7.0",
|
||||
"@backstage/core-plugin-api": "^0.1.10",
|
||||
"@backstage/catalog-model": "^0.9.5",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/core-app-api": "^0.1.18",
|
||||
"@backstage/core-components": "^0.7.1",
|
||||
"@backstage/core-plugin-api": "^0.1.11",
|
||||
"@backstage/integration-react": "^0.1.12",
|
||||
"@backstage/plugin-api-docs": "^0.6.12",
|
||||
"@backstage/plugin-azure-devops": "^0.1.1",
|
||||
"@backstage/plugin-badges": "^0.2.13",
|
||||
"@backstage/plugin-catalog": "^0.7.1",
|
||||
"@backstage/plugin-catalog-graph": "^0.2.0",
|
||||
"@backstage/plugin-catalog-import": "^0.7.2",
|
||||
"@backstage/plugin-catalog-react": "^0.6.0",
|
||||
"@backstage/plugin-catalog": "^0.7.2",
|
||||
"@backstage/plugin-catalog-graph": "^0.2.1",
|
||||
"@backstage/plugin-catalog-import": "^0.7.3",
|
||||
"@backstage/plugin-catalog-react": "^0.6.1",
|
||||
"@backstage/plugin-circleci": "^0.2.27",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.27",
|
||||
"@backstage/plugin-code-coverage": "^0.1.15",
|
||||
@@ -26,7 +26,7 @@
|
||||
"@backstage/plugin-github-actions": "^0.4.22",
|
||||
"@backstage/plugin-graphiql": "^0.2.20",
|
||||
"@backstage/plugin-home": "^0.4.4",
|
||||
"@backstage/plugin-jenkins": "^0.5.10",
|
||||
"@backstage/plugin-jenkins": "^0.5.11",
|
||||
"@backstage/plugin-kafka": "^0.2.19",
|
||||
"@backstage/plugin-kubernetes": "^0.4.17",
|
||||
"@backstage/plugin-lighthouse": "^0.2.29",
|
||||
@@ -36,12 +36,12 @@
|
||||
"@backstage/plugin-rollbar": "^0.3.18",
|
||||
"@backstage/plugin-scaffolder": "^0.11.8",
|
||||
"@backstage/plugin-search": "^0.4.15",
|
||||
"@backstage/plugin-sentry": "^0.3.25",
|
||||
"@backstage/plugin-sentry": "^0.3.26",
|
||||
"@backstage/plugin-shortcuts": "^0.1.12",
|
||||
"@backstage/plugin-tech-radar": "^0.4.11",
|
||||
"@backstage/plugin-techdocs": "^0.12.2",
|
||||
"@backstage/plugin-techdocs": "^0.12.3",
|
||||
"@backstage/plugin-todo": "^0.1.14",
|
||||
"@backstage/plugin-user-settings": "^0.3.9",
|
||||
"@backstage/plugin-user-settings": "^0.3.10",
|
||||
"@backstage/search-common": "^0.2.0",
|
||||
"@backstage/theme": "^0.2.11",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.9.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- be59619212: Add "rate limit exceeded" to error from GithubUrlReader if that is the cause of a read failure
|
||||
- 36e67d2f24: Internal updates to apply more strict checks to throw errors.
|
||||
- Updated dependencies
|
||||
- @backstage/config-loader@0.7.0
|
||||
- @backstage/errors@0.1.3
|
||||
|
||||
## 0.9.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.9.6",
|
||||
"version": "0.9.7",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -31,8 +31,8 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.4",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/config-loader": "^0.6.10",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/config-loader": "^0.7.0",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"@backstage/integration": "^0.6.7",
|
||||
"@google-cloud/storage": "^5.8.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.15",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/test-utils": "^0.1.18",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import knexFactory, { Knex } from 'knex';
|
||||
|
||||
import { Config } from '@backstage/config';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import { mergeDatabaseConfig } from '../config';
|
||||
import { DatabaseConnector } from '../types';
|
||||
import defaultNameOverride from './defaultNameOverride';
|
||||
@@ -94,8 +95,7 @@ function requirePgConnectionString() {
|
||||
try {
|
||||
return require('pg-connection-string').parse;
|
||||
} catch (e) {
|
||||
const message = `Postgres: Install 'pg-connection-string'`;
|
||||
throw new Error(`${message}\n${e.message}`);
|
||||
throw new ForwardedError("Postgres: Install 'pg-connection-string'", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ describe('AwsS3UrlReader', () => {
|
||||
),
|
||||
).rejects.toThrow(
|
||||
Error(
|
||||
`Could not retrieve file from S3: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
`Could not retrieve file from S3; caused by Error: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -216,7 +216,7 @@ describe('AwsS3UrlReader', () => {
|
||||
),
|
||||
).rejects.toThrow(
|
||||
Error(
|
||||
`Could not retrieve file from S3: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
`Could not retrieve file from S3; caused by Error: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
} from './types';
|
||||
import getRawBody from 'raw-body';
|
||||
import { AwsS3Integration, ScmIntegrations } from '@backstage/integration';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import { ListObjectsV2Output, ObjectList } from 'aws-sdk/clients/s3';
|
||||
|
||||
const parseURL = (
|
||||
@@ -162,7 +163,7 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
etag: etag,
|
||||
};
|
||||
} catch (e) {
|
||||
throw new Error(`Could not retrieve file from S3: ${e.message}`);
|
||||
throw new ForwardedError('Could not retrieve file from S3', e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
|
||||
return await this.deps.treeResponseFactory.fromReadableArray(responses);
|
||||
} catch (e) {
|
||||
throw new Error(`Could not retrieve file tree from S3: ${e.message}`);
|
||||
throw new ForwardedError('Could not retrieve file tree from S3', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -221,6 +221,32 @@ describe('GithubUrlReader', () => {
|
||||
).rejects.toThrow(NotModifiedError);
|
||||
});
|
||||
|
||||
it('should throw Error with ratelimit exceeded if GitHub responds with 403 and rate limit is exceeded', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
worker.use(
|
||||
rest.get(
|
||||
'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/',
|
||||
(_req, res, ctx) => {
|
||||
return res(
|
||||
ctx.status(403),
|
||||
ctx.set('X-RateLimit-Remaining', '0'),
|
||||
ctx.body(
|
||||
'{"message": "API rate limit exceeded for xxx.xxx.xxx.xxx..."}',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
await expect(
|
||||
gheProcessor.readUrl(
|
||||
'https://github.com/backstage/mock/tree/blob/main',
|
||||
{ etag: 'foo' },
|
||||
),
|
||||
).rejects.toThrow(/rate limit exceeded/);
|
||||
});
|
||||
|
||||
it('should return etag from the response', async () => {
|
||||
(mockCredentialsProvider.getCredentials as jest.Mock).mockResolvedValue({
|
||||
headers: {
|
||||
|
||||
@@ -126,10 +126,21 @@ export class GithubUrlReader implements UrlReader {
|
||||
};
|
||||
}
|
||||
|
||||
const message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`;
|
||||
let message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`;
|
||||
if (response.status === 404) {
|
||||
throw new NotFoundError(message);
|
||||
}
|
||||
|
||||
// GitHub returns a 403 response with a couple of headers indicating rate
|
||||
// limit status. See more in the GitHub docs:
|
||||
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
|
||||
if (
|
||||
response.status === 403 &&
|
||||
response.headers.get('X-RateLimit-Remaining') === '0'
|
||||
) {
|
||||
message += ' (rate limit exceeded)';
|
||||
}
|
||||
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { isError } from '@backstage/errors';
|
||||
import { getVoidLogger } from '../logging';
|
||||
import { UrlReaders } from './UrlReaders';
|
||||
|
||||
@@ -71,7 +72,10 @@ function withRetries(count: number, fn: () => Promise<void>) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
if (!error.message.match(/rate limit|Too Many Requests/)) {
|
||||
if (
|
||||
isError(error) &&
|
||||
!error.message.match(/rate limit|Too Many Requests/)
|
||||
) {
|
||||
throw error;
|
||||
} else {
|
||||
console.warn('Request was rate limited', error);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import Docker from 'dockerode';
|
||||
import fs from 'fs-extra';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import { PassThrough } from 'stream';
|
||||
import { ContainerRunner, RunContainerOptions } from './ContainerRunner';
|
||||
|
||||
@@ -45,8 +46,9 @@ export class DockerContainerRunner implements ContainerRunner {
|
||||
try {
|
||||
await this.dockerClient.ping();
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with: ${e.message}`,
|
||||
throw new ForwardedError(
|
||||
'This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with',
|
||||
e,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @backstage/backend-test-utils
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-common@0.9.7
|
||||
- @backstage/cli@0.8.0
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-test-utils",
|
||||
"description": "Test helpers library for Backstage backends",
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.8",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -30,8 +30,8 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.2",
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/backend-common": "^0.9.7",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/config": "^0.1.9",
|
||||
"knex": "^0.95.1",
|
||||
"mysql2": "^2.2.5",
|
||||
@@ -41,7 +41,7 @@
|
||||
"uuid": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"jest": "^26.0.1"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -24,36 +24,36 @@
|
||||
"migrate:create": "knex migrate:make -x ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.6",
|
||||
"@backstage/backend-common": "^0.9.7",
|
||||
"@backstage/catalog-client": "^0.5.0",
|
||||
"@backstage/catalog-model": "^0.9.4",
|
||||
"@backstage/catalog-model": "^0.9.5",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/integration": "^0.6.8",
|
||||
"@backstage/plugin-app-backend": "^0.3.16",
|
||||
"@backstage/plugin-auth-backend": "^0.4.4",
|
||||
"@backstage/plugin-azure-devops-backend": "^0.1.2",
|
||||
"@backstage/plugin-app-backend": "^0.3.17",
|
||||
"@backstage/plugin-auth-backend": "^0.4.5",
|
||||
"@backstage/plugin-azure-devops-backend": "^0.1.3",
|
||||
"@backstage/plugin-badges-backend": "^0.1.11",
|
||||
"@backstage/plugin-catalog-backend": "^0.17.0",
|
||||
"@backstage/plugin-code-coverage-backend": "^0.1.13",
|
||||
"@backstage/plugin-catalog-backend": "^0.17.1",
|
||||
"@backstage/plugin-code-coverage-backend": "^0.1.14",
|
||||
"@backstage/plugin-graphql-backend": "^0.1.9",
|
||||
"@backstage/plugin-jenkins-backend": "^0.1.6",
|
||||
"@backstage/plugin-kubernetes-backend": "^0.3.17",
|
||||
"@backstage/plugin-kubernetes-backend": "^0.3.18",
|
||||
"@backstage/plugin-kafka-backend": "^0.2.10",
|
||||
"@backstage/plugin-proxy-backend": "^0.2.13",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.15",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.15.8",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.15.10",
|
||||
"@backstage/plugin-scaffolder-backend-module-rails": "^0.1.5",
|
||||
"@backstage/plugin-search-backend": "^0.2.6",
|
||||
"@backstage/plugin-search-backend-node": "^0.4.2",
|
||||
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.4",
|
||||
"@backstage/plugin-search-backend-module-pg": "^0.2.1",
|
||||
"@backstage/plugin-techdocs-backend": "^0.10.4",
|
||||
"@backstage/plugin-techdocs-backend": "^0.10.5",
|
||||
"@backstage/plugin-todo-backend": "^0.1.13",
|
||||
"@gitbeaker/node": "^30.2.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"azure-devops-node-api": "^11.0.1",
|
||||
"dockerode": "^3.2.1",
|
||||
"example-app": "^0.2.50",
|
||||
"example-app": "^0.2.51",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
"express-prom-bundle": "^6.3.6",
|
||||
@@ -65,7 +65,7 @@
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.16",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@types/dockerode": "^3.2.1",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-serve-static-core": "^4.17.5"
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.9.4",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/catalog-model": "^0.9.5",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"cross-fetch": "^3.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.15",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@types/jest": "^26.0.7",
|
||||
"msw": "^0.29.0"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @backstage/catalog-model
|
||||
|
||||
## 0.9.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ab2df3be33: Improved documentation for exported symbols.
|
||||
- Updated dependencies
|
||||
- @backstage/errors@0.1.3
|
||||
|
||||
## 0.9.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -9,12 +9,12 @@ import { JsonValue } from '@backstage/config';
|
||||
import { SerializedError } from '@backstage/errors';
|
||||
import * as yup from 'yup';
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
// @public @deprecated
|
||||
export const analyzeLocationSchema: yup.SchemaOf<{
|
||||
location: LocationSpec;
|
||||
}>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface ApiEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -32,7 +32,7 @@ interface ApiEntityV1alpha1 extends Entity {
|
||||
export { ApiEntityV1alpha1 as ApiEntity };
|
||||
export { ApiEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const apiEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public
|
||||
@@ -58,7 +58,7 @@ export function compareEntityToRef(
|
||||
context?: EntityRefContext,
|
||||
): boolean;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface ComponentEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -79,7 +79,7 @@ interface ComponentEntityV1alpha1 extends Entity {
|
||||
export { ComponentEntityV1alpha1 as ComponentEntity };
|
||||
export { ComponentEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const componentEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public
|
||||
@@ -89,7 +89,7 @@ export class DefaultNamespaceEntityPolicy implements EntityPolicy {
|
||||
enforce(entity: Entity): Promise<Entity>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface DomainEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -103,10 +103,10 @@ interface DomainEntityV1alpha1 extends Entity {
|
||||
export { DomainEntityV1alpha1 as DomainEntity };
|
||||
export { DomainEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const domainEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const EDIT_URL_ANNOTATION = 'backstage.io/edit-url';
|
||||
|
||||
// @public
|
||||
@@ -181,7 +181,7 @@ export type EntityName = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const EntityPolicies: {
|
||||
allOf(policies: EntityPolicy[]): EntityPolicy;
|
||||
oneOf(policies: EntityPolicy[]): EntityPolicy;
|
||||
@@ -250,7 +250,7 @@ export function getEntitySourceLocation(entity: Entity): {
|
||||
target: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface GroupEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -272,10 +272,10 @@ interface GroupEntityV1alpha1 extends Entity {
|
||||
export { GroupEntityV1alpha1 as GroupEntity };
|
||||
export { GroupEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const groupEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type JSONSchema = JSONSchema7 & {
|
||||
[key in string]?: JsonValue;
|
||||
};
|
||||
@@ -305,16 +305,16 @@ export class KubernetesValidatorFunctions {
|
||||
static isValidObjectName(value: unknown): boolean;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
type Location_2 = {
|
||||
id: string;
|
||||
} & LocationSpec;
|
||||
export { Location_2 as Location };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const LOCATION_ANNOTATION = 'backstage.io/managed-by-location';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface LocationEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -330,23 +330,23 @@ interface LocationEntityV1alpha1 extends Entity {
|
||||
export { LocationEntityV1alpha1 as LocationEntity };
|
||||
export { LocationEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const locationEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
// @public @deprecated
|
||||
export const locationSchema: yup.SchemaOf<Location_2>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type LocationSpec = {
|
||||
type: string;
|
||||
target: string;
|
||||
presence?: 'optional' | 'required';
|
||||
};
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
// @public @deprecated
|
||||
export const locationSpecSchema: yup.SchemaOf<LocationSpec>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export function makeValidator(overrides?: Partial<Validators>): Validators;
|
||||
|
||||
// @public
|
||||
@@ -356,7 +356,7 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy {
|
||||
enforce(entity: Entity): Promise<Entity>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const ORIGIN_LOCATION_ANNOTATION =
|
||||
'backstage.io/managed-by-origin-location';
|
||||
|
||||
@@ -373,13 +373,9 @@ export function parseEntityRef(
|
||||
defaultKind: string;
|
||||
defaultNamespace: string;
|
||||
},
|
||||
): {
|
||||
kind: string;
|
||||
namespace: string;
|
||||
name: string;
|
||||
};
|
||||
): EntityName;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export function parseEntityRef(
|
||||
ref: EntityRef,
|
||||
context?: {
|
||||
@@ -391,7 +387,7 @@ export function parseEntityRef(
|
||||
name: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export function parseEntityRef(
|
||||
ref: EntityRef,
|
||||
context?: {
|
||||
@@ -409,28 +405,28 @@ export function parseLocationReference(ref: string): {
|
||||
target: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_API_CONSUMED_BY = 'apiConsumedBy';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_API_PROVIDED_BY = 'apiProvidedBy';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_CHILD_OF = 'childOf';
|
||||
|
||||
// @public
|
||||
export const RELATION_CONSUMES_API = 'consumesApi';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_DEPENDENCY_OF = 'dependencyOf';
|
||||
|
||||
// @public
|
||||
export const RELATION_DEPENDS_ON = 'dependsOn';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_HAS_MEMBER = 'hasMember';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_HAS_PART = 'hasPart';
|
||||
|
||||
// @public
|
||||
@@ -439,7 +435,7 @@ export const RELATION_MEMBER_OF = 'memberOf';
|
||||
// @public
|
||||
export const RELATION_OWNED_BY = 'ownedBy';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_OWNER_OF = 'ownerOf';
|
||||
|
||||
// @public
|
||||
@@ -448,10 +444,10 @@ export const RELATION_PARENT_OF = 'parentOf';
|
||||
// @public
|
||||
export const RELATION_PART_OF = 'partOf';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const RELATION_PROVIDES_API = 'providesApi';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface ResourceEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -468,7 +464,7 @@ interface ResourceEntityV1alpha1 extends Entity {
|
||||
export { ResourceEntityV1alpha1 as ResourceEntity };
|
||||
export { ResourceEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const resourceEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public
|
||||
@@ -488,7 +484,7 @@ export function serializeEntityRef(
|
||||
},
|
||||
): EntityRef;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const SOURCE_LOCATION_ANNOTATION = 'backstage.io/source-location';
|
||||
|
||||
// @public
|
||||
@@ -508,7 +504,7 @@ export function stringifyLocationReference(ref: {
|
||||
target: string;
|
||||
}): string;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface SystemEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -523,10 +519,10 @@ interface SystemEntityV1alpha1 extends Entity {
|
||||
export { SystemEntityV1alpha1 as SystemEntity };
|
||||
export { SystemEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const systemEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface TemplateEntityV1beta2 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1beta2';
|
||||
@@ -550,7 +546,7 @@ export interface TemplateEntityV1beta2 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const templateEntityV1beta2Validator: KindValidator;
|
||||
|
||||
// @alpha
|
||||
@@ -569,7 +565,7 @@ export type UNSTABLE_EntityStatusItem = {
|
||||
// @alpha
|
||||
export type UNSTABLE_EntityStatusLevel = 'info' | 'warning' | 'error';
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
interface UserEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
@@ -588,10 +584,10 @@ interface UserEntityV1alpha1 extends Entity {
|
||||
export { UserEntityV1alpha1 as UserEntity };
|
||||
export { UserEntityV1alpha1 };
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const userEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type Validators = {
|
||||
isValidApiVersion(value: unknown): boolean;
|
||||
isValidKind(value: unknown): boolean;
|
||||
@@ -609,5 +605,5 @@ export const VIEW_URL_ANNOTATION = 'backstage.io/view-url';
|
||||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/entity/Entity.d.ts:38:5 - (ae-incompatible-release-tags) The symbol "status" is marked as @public, but its signature references "UNSTABLE_EntityStatus" which is marked as @alpha
|
||||
// src/entity/Entity.d.ts:41:5 - (ae-incompatible-release-tags) The symbol "status" is marked as @public, but its signature references "UNSTABLE_EntityStatus" which is marked as @alpha
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/catalog-model",
|
||||
"description": "Types and validators that help describe the model of a Backstage Catalog",
|
||||
"version": "0.9.4",
|
||||
"version": "0.9.5",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"@types/yup": "^0.29.13",
|
||||
"ajv": "^7.0.3",
|
||||
@@ -41,7 +41,7 @@
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.15",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@types/jest": "^26.0.7",
|
||||
"@types/lodash": "^4.14.151",
|
||||
"yaml": "^1.9.2"
|
||||
|
||||
@@ -52,7 +52,11 @@ class AnyEntityPolicy implements EntityPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Provides helpers for enforcing a set of {@link EntityPolicy} in an `and`/`or` expression.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EntityPolicies = {
|
||||
allOf(policies: EntityPolicy[]): EntityPolicy {
|
||||
return new AllEntityPolicies(policies);
|
||||
|
||||
@@ -21,8 +21,11 @@ import { UNSTABLE_EntityStatus } from './EntityStatus';
|
||||
/**
|
||||
* The parts of the format that's common to all versions/kinds of entity.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See also:
|
||||
* {@link https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/}
|
||||
* @public
|
||||
* @see https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/
|
||||
*/
|
||||
export type Entity = {
|
||||
/**
|
||||
@@ -63,9 +66,13 @@ export type Entity = {
|
||||
/**
|
||||
* Metadata fields common to all versions/kinds of entity.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See also:
|
||||
* {@link https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta}
|
||||
* {@link https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/}
|
||||
*
|
||||
* @public
|
||||
* @see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta
|
||||
* @see https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/
|
||||
*/
|
||||
export type EntityMeta = JsonObject & {
|
||||
/**
|
||||
|
||||
@@ -33,10 +33,15 @@ export const ENTITY_META_GENERATED_FIELDS = [
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Annotations for linking to entity from catalog pages.
|
||||
* Annotation for linking to entity page from catalog pages.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const VIEW_URL_ANNOTATION = 'backstage.io/view-url';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* Annotation for linking to entity edit page from catalog pages.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EDIT_URL_ANNOTATION = 'backstage.io/edit-url';
|
||||
|
||||
@@ -27,6 +27,8 @@ import { Entity } from '../Entity';
|
||||
* Ensures that the format of individual fields of the entity envelope
|
||||
* is valid.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This does not take into account machine generated fields such as uid, etag
|
||||
* and generation.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,8 @@ import { EntityPolicy } from './types';
|
||||
/**
|
||||
* Ensures that the entity spec is valid according to a schema.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This should be the first policy in the list, to ensure that other downstream
|
||||
* policies can work with a structure that is at least valid in therms of the
|
||||
* typescript type.
|
||||
|
||||
@@ -69,6 +69,8 @@ export type EntityRefContext = {
|
||||
* Parses an entity reference, either on string or compound form, and always
|
||||
* returns a complete entity name including kind, namespace and name.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This function automatically assumes the default namespace "default" unless
|
||||
* otherwise specified as part of the options, and will throw an error if no
|
||||
* kind was specified in the input reference and no default kind was given.
|
||||
@@ -100,7 +102,9 @@ export function parseEntityName(
|
||||
* Parses an entity reference, either on string or compound form, and returns
|
||||
* a structure with a name, and optional kind and namespace.
|
||||
*
|
||||
* The options object can contain default values for the kind and namespace,
|
||||
* @remarks
|
||||
*
|
||||
* The context object can contain default values for the kind and namespace,
|
||||
* that will be used if the input reference did not specify any.
|
||||
*
|
||||
* @public
|
||||
@@ -111,12 +115,12 @@ export function parseEntityName(
|
||||
export function parseEntityRef(
|
||||
ref: EntityRef,
|
||||
context?: { defaultKind: string; defaultNamespace: string },
|
||||
): {
|
||||
kind: string;
|
||||
namespace: string;
|
||||
name: string;
|
||||
};
|
||||
/** @public */
|
||||
): EntityName;
|
||||
/**
|
||||
* parseEntityRef with optional Kind.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function parseEntityRef(
|
||||
ref: EntityRef,
|
||||
context?: { defaultKind: string },
|
||||
@@ -125,7 +129,11 @@ export function parseEntityRef(
|
||||
namespace?: string;
|
||||
name: string;
|
||||
};
|
||||
/** @public */
|
||||
/**
|
||||
* parseEntityRef with optional Namespace.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function parseEntityRef(
|
||||
ref: EntityRef,
|
||||
context?: { defaultNamespace: string },
|
||||
@@ -134,6 +142,11 @@ export function parseEntityRef(
|
||||
namespace: string;
|
||||
name: string;
|
||||
};
|
||||
/**
|
||||
* parseEntityRef with optional Kind and Namespace.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function parseEntityRef(
|
||||
ref: EntityRef,
|
||||
context: EntityRefContext = {},
|
||||
@@ -223,6 +236,8 @@ export function serializeEntityRef(
|
||||
* Takes an entity or entity name/reference, and returns the string form of an
|
||||
* entity ref.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This function creates a canonical and unique reference to the entity, converting
|
||||
* all parts of the name to lowercase and inserts the default namespace if needed.
|
||||
* It is typically not the best way to represent the entity reference to the user.
|
||||
@@ -256,6 +271,8 @@ export function stringifyEntityRef(
|
||||
/**
|
||||
* Compares an entity to either a string reference or a compound reference.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* The comparison is case insensitive, and all of kind, namespace, and name
|
||||
* must match (after applying the optional context to the ref).
|
||||
*
|
||||
|
||||
@@ -43,6 +43,8 @@ export function generateEntityEtag(): string {
|
||||
* Checks whether there are any significant changes going from the previous to
|
||||
* the next version of this entity.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Significance, in this case, means that we do not compare generated fields
|
||||
* such as uid, etag and generation.
|
||||
*
|
||||
@@ -98,6 +100,8 @@ export function entityHasChanges(previous: Entity, next: Entity): boolean {
|
||||
* Takes an old revision of an entity and a new desired state, and merges
|
||||
* them into a complete new state.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* The previous revision is expected to be a complete model loaded from the
|
||||
* catalog, including the uid, etag and generation fields.
|
||||
*
|
||||
|
||||
@@ -18,7 +18,15 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/API.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage API kind Entity. APIs describe the interfaces for Components to communicate.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://backstage.io/docs/features/software-catalog/system-model}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ApiEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'API';
|
||||
@@ -31,6 +39,10 @@ export interface ApiEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link ApiEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const apiEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,15 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/Component.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog Component kind Entity. Represents a single, individual piece of software.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://backstage.io/docs/features/software-catalog/system-model}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ComponentEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'Component';
|
||||
@@ -34,6 +42,10 @@ export interface ComponentEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link ComponentEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const componentEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,15 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/Domain.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage Domain kind Entity. Domains group Systems together.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://backstage.io/docs/features/software-catalog/system-model}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface DomainEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'Domain';
|
||||
@@ -27,6 +35,10 @@ export interface DomainEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link DomainEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const domainEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,11 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/Group.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog Group kind Entity.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface GroupEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'Group';
|
||||
@@ -35,6 +39,9 @@ export interface GroupEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link GroupEntityV1alpha1}.
|
||||
* @public
|
||||
*/
|
||||
export const groupEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,11 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/Location.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog Location kind Entity.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface LocationEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'Location';
|
||||
@@ -29,6 +33,10 @@ export interface LocationEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link LocationEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const locationEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,15 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/Resource.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog Resource kind Entity. Represents infrastructure required to operate Components.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://backstage.io/docs/features/software-catalog/system-model}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ResourceEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'Resource';
|
||||
@@ -30,6 +38,10 @@ export interface ResourceEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link ResourceEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const resourceEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,15 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/System.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog System kind Entity. Systems group Comopnents, Resources and APIs together.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://backstage.io/docs/features/software-catalog/system-model}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface SystemEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'System';
|
||||
@@ -28,6 +36,10 @@ export interface SystemEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link SystemEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const systemEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -19,7 +19,11 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/Template.v1beta2.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog Template kind Entity. Templates are used by the Scaffolder plugin to create new Components.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface TemplateEntityV1beta2 extends Entity {
|
||||
apiVersion: 'backstage.io/v1beta2';
|
||||
kind: 'Template';
|
||||
@@ -38,6 +42,10 @@ export interface TemplateEntityV1beta2 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link TemplateEntityV1beta2}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const templateEntityV1beta2Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -18,7 +18,11 @@ import type { Entity } from '../entity/Entity';
|
||||
import schema from '../schema/kinds/User.v1alpha1.schema.json';
|
||||
import { ajvCompiledJsonSchemaValidator } from './util';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Backstage catalog User kind Entity.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface UserEntityV1alpha1 extends Entity {
|
||||
apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1';
|
||||
kind: 'User';
|
||||
@@ -32,6 +36,10 @@ export interface UserEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* {@link KindValidator} for {@link UserEntityV1alpha1}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const userEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -24,61 +24,115 @@ Naming rules for relations in priority order:
|
||||
|
||||
/**
|
||||
* An ownership relation where the owner is usually an organizational
|
||||
* entity (user or group), and the other entity can be anything.
|
||||
* entity (user or group), and the other entity can be anything. Reversed
|
||||
* direction of {@link RELATION_OWNER_OF}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_OWNED_BY = 'ownedBy';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relationship from an owner to the owned entity. Reversed direction of
|
||||
* {@link RELATION_OWNED_BY}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_OWNER_OF = 'ownerOf';
|
||||
|
||||
/**
|
||||
* A relation with an API entity, typically from a component
|
||||
* A relation with an API entity, typically from a component. Reversed direction of
|
||||
* {@link RELATION_API_CONSUMED_BY}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_CONSUMES_API = 'consumesApi';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation of an API being consumed, typically by a component. Reversed direction of
|
||||
* {@link RELATION_CONSUMES_API}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_API_CONSUMED_BY = 'apiConsumedBy';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation from an API provider entity (typically a component) to the API. Reversed direction of
|
||||
* {@link RELATION_API_PROVIDED_BY}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_PROVIDES_API = 'providesApi';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation from an API to its provider entity (typically a component). Reversed direction of
|
||||
* {@link RELATION_PROVIDES_API}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_API_PROVIDED_BY = 'apiProvidedBy';
|
||||
|
||||
/**
|
||||
* A relation denoting a dependency on another entity.
|
||||
* A relation denoting a dependency on another entity. Reversed direction of
|
||||
* {@link RELATION_DEPENDENCY_OF}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_DEPENDS_ON = 'dependsOn';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation denoting a reverse dependency by another entity. Reversed direction of
|
||||
* {@link RELATION_DEPENDS_ON}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_DEPENDENCY_OF = 'dependencyOf';
|
||||
|
||||
/**
|
||||
* A parent/child relation to build up a tree, used for example to describe
|
||||
* the organizational structure between groups.
|
||||
* the organizational structure between groups. Reversed direction of
|
||||
* {@link RELATION_CHILD_OF}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_PARENT_OF = 'parentOf';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation from a child to a parent entity, used for example to describe
|
||||
* the organizational structure between groups. Reversed direction of
|
||||
* {@link RELATION_PARENT_OF}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_CHILD_OF = 'childOf';
|
||||
|
||||
/**
|
||||
* A membership relation, typically for users in a group.
|
||||
* A membership relation, typically for users in a group. Reversed direction of
|
||||
* {@link RELATION_HAS_MEMBER}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_MEMBER_OF = 'memberOf';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation from a group to its member, typcally a user in a group. Reversed direction of
|
||||
* {@link RELATION_MEMBER_OF}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_HAS_MEMBER = 'hasMember';
|
||||
|
||||
/**
|
||||
* A part/whole relation, typically for components in a system and systems
|
||||
* in a domain.
|
||||
* in a domain. Reversed direction of {@link RELATION_HAS_PART}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_PART_OF = 'partOf';
|
||||
/** @public */
|
||||
|
||||
/**
|
||||
* A relation from a containing entity to a contained entity. Reversed direction of
|
||||
* {@link RELATION_PART_OF}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RELATION_HAS_PART = 'hasPart';
|
||||
|
||||
@@ -14,11 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Constant storing location annotation.
|
||||
*
|
||||
* @public */
|
||||
export const LOCATION_ANNOTATION = 'backstage.io/managed-by-location';
|
||||
/** @public */
|
||||
/**
|
||||
* Constant storing origin location annotation
|
||||
*
|
||||
* @public */
|
||||
export const ORIGIN_LOCATION_ANNOTATION =
|
||||
'backstage.io/managed-by-origin-location';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Contant storing source location annotation
|
||||
*
|
||||
* @public */
|
||||
export const SOURCE_LOCATION_ANNOTATION = 'backstage.io/source-location';
|
||||
|
||||
@@ -65,6 +65,8 @@ export function parseLocationReference(ref: string): {
|
||||
/**
|
||||
* Turns a location reference into its string form.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Note that the input type is not `LocationSpec`, because we do not want to
|
||||
* conflate the string form with the additional properties of that type.
|
||||
*
|
||||
@@ -90,6 +92,8 @@ export function stringifyLocationReference(ref: {
|
||||
/**
|
||||
* Returns the source code location of the Entity, to the extent that one exists.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* If the returned location type is of type 'url', the target should be readable at least
|
||||
* using the UrlReader from `@backstage/backend-common`. If it is not of type 'url', the caller
|
||||
* needs to have explicit handling of each location type or signal that it is not supported.
|
||||
|
||||
@@ -14,17 +14,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Holds the entity location information.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* `presence` flag: when using repo importer plugin, location is being created before the component yaml file is merged to the main branch.
|
||||
* This flag is then set to indicate that the file can be not present.
|
||||
* default value: 'required'.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type LocationSpec = {
|
||||
type: string;
|
||||
target: string;
|
||||
// When using repo importer plugin, location is being created before the component yaml file is merged to the main branch.
|
||||
// This flag is then set to indicate that the file can be not present.
|
||||
// default value: 'required'.
|
||||
presence?: 'optional' | 'required';
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Entity location for a specific entity.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type Location = {
|
||||
id: string;
|
||||
} & LocationSpec;
|
||||
|
||||
@@ -18,8 +18,10 @@ import * as yup from 'yup';
|
||||
import { LocationSpec, Location } from './types';
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Use JSONSchema or validators instead.
|
||||
* @deprecated Use {@link JSONSchema} or validators instead.
|
||||
*/
|
||||
export const locationSpecSchema: yup.SchemaOf<LocationSpec> = yup
|
||||
.object({
|
||||
@@ -31,8 +33,10 @@ export const locationSpecSchema: yup.SchemaOf<LocationSpec> = yup
|
||||
.required();
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Use JSONSchema or validators instead.
|
||||
* @deprecated Use {@link JSONSchema} or validators instead.
|
||||
*/
|
||||
export const locationSchema: yup.SchemaOf<Location> = yup
|
||||
.object({
|
||||
@@ -45,8 +49,10 @@ export const locationSchema: yup.SchemaOf<Location> = yup
|
||||
.required();
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Use JSONSchema or validators instead.
|
||||
* @deprecated Use {@link JSONSchema} or validators instead.
|
||||
*/
|
||||
export const analyzeLocationSchema: yup.SchemaOf<{ location: LocationSpec }> =
|
||||
yup
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
import { JsonValue } from '@backstage/config';
|
||||
import { JSONSchema7 } from 'json-schema';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* JSONSchema extendable by arbitrary JSON attributes
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type JSONSchema = JSONSchema7 & { [key in string]?: JsonValue };
|
||||
|
||||
/**
|
||||
@@ -35,7 +39,9 @@ export type EntityName = {
|
||||
* A reference by name to an entity, either as a compact string representation,
|
||||
* or as a compound reference structure.
|
||||
*
|
||||
* The string representation is on the form [<kind>:][<namespace>/]<name>.
|
||||
* @remarks
|
||||
*
|
||||
* The string representation is on the form `[<kind>:][<namespace>/]<name>`.
|
||||
*
|
||||
* Left-out parts of the reference need to be handled by the application,
|
||||
* either by rejecting the reference or by falling back to default values.
|
||||
|
||||
@@ -25,6 +25,8 @@ import { compileAjvSchema, throwAjvError } from './ajv';
|
||||
* if it matches that schema, or throws a {@link globals#TypeError} describing the
|
||||
* errors.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Note that this validator is only meant for applying the base schema checks;
|
||||
* it does not take custom policies or additional processor based validation
|
||||
* into account.
|
||||
@@ -33,13 +35,15 @@ import { compileAjvSchema, throwAjvError } from './ajv';
|
||||
* own, it may contain `$ref` references to the following, which are resolved
|
||||
* automatically for you:
|
||||
*
|
||||
* - EntityEnvelope
|
||||
* - Entity
|
||||
* - EntityMeta
|
||||
* - common#<id>
|
||||
* - {@link EntityEnvelope}
|
||||
* - {@link Entity}
|
||||
* - {@link EntityMeta}
|
||||
* - `common#<id>`
|
||||
*
|
||||
* See also {@link https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema}
|
||||
*
|
||||
* @public
|
||||
* @see https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema
|
||||
*
|
||||
*/
|
||||
export function entityEnvelopeSchemaValidator<
|
||||
T extends EntityEnvelope = EntityEnvelope,
|
||||
|
||||
@@ -24,6 +24,8 @@ import { compileAjvSchema, throwAjvError } from './ajv';
|
||||
* schema apiVersion/kind didn't apply to that data, or throws a
|
||||
* {@link globals#TypeError} describing actual errors.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This validator is highly specialized, in that it has special treatment of
|
||||
* the `kind` and `apiVersion` root keys. This only works if your schema has
|
||||
* their rule set to `"enum"`:
|
||||
@@ -47,13 +49,16 @@ import { compileAjvSchema, throwAjvError } from './ajv';
|
||||
* The given schema may contain `$ref` references to the following, which are
|
||||
* resolved automatically for you:
|
||||
*
|
||||
* - EntityEnvelope
|
||||
* - Entity
|
||||
* - EntityMeta
|
||||
* - common#<id>
|
||||
* - {@link Entity}
|
||||
*
|
||||
* - {@link EntityEnvelope}
|
||||
*
|
||||
* - {@link EntityMeta}
|
||||
*
|
||||
* - `common#<id>`
|
||||
* @see {@link https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema}
|
||||
*
|
||||
* @public
|
||||
* @see https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema
|
||||
*/
|
||||
export function entityKindSchemaValidator<T extends Entity>(
|
||||
schema: unknown,
|
||||
|
||||
@@ -24,21 +24,23 @@ import { compileAjvSchema, throwAjvError } from './ajv';
|
||||
* returns that data cast to an {@link Entity} (or the given subtype) if it
|
||||
* matches that schema, or throws a {@link globals#TypeError} describing the errors.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Note that this validator is only meant for applying the base schema checks;
|
||||
* it does not take custom policies or additional processor based validation
|
||||
* into account.
|
||||
*
|
||||
* By default, the plain `Entity` schema is used. If you pass in your own, it
|
||||
* By default, the plain {@link Entity} schema is used. If you pass in your own, it
|
||||
* may contain `$ref` references to the following, which are resolved
|
||||
* automatically for you:
|
||||
*
|
||||
* - EntityEnvelope
|
||||
* - Entity
|
||||
* - EntityMeta
|
||||
* - common#<id>
|
||||
* - {@link Entity}
|
||||
* - {@link EntityEnvelope}
|
||||
* - {@link EntityMeta}
|
||||
* - `common#<id>`
|
||||
*
|
||||
* @public
|
||||
* @see https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema
|
||||
* @see {@link https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema}
|
||||
*/
|
||||
export function entitySchemaValidator<T extends Entity = Entity>(
|
||||
schema?: unknown,
|
||||
|
||||
@@ -30,7 +30,11 @@ const defaultValidators: Validators = {
|
||||
isValidTag: CommonValidatorFunctions.isValidTag,
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Creates a {@link Validators} object from `overrides`, with default values taken from {@link KubernetesValidatorFunctions}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function makeValidator(overrides: Partial<Validators> = {}): Validators {
|
||||
return {
|
||||
...defaultValidators,
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Type alias for implementing validators of various entity objects.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type Validators = {
|
||||
isValidApiVersion(value: unknown): boolean;
|
||||
isValidKind(value: unknown): boolean;
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @backstage/cli
|
||||
|
||||
## 0.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- b486adb8c6: The Jest configuration that's included with the Backstage CLI has received several changes.
|
||||
|
||||
As a part of migrating to more widespread usage of ESM modules, the default configuration now transforms all source files everywhere, including those within `node_modules`. Due to this change the existing `transformModules` option has been removed and will be ignored. There is also a list of known packages that do not require transforms in the CLI, which will evolve over time. If needed there will also be an option to add packages to this list in the future, but it is not included yet to avoid clutter.
|
||||
|
||||
To counteract the slowdown of the additional transforms that have been introduced, the default configuration has also been reworked to enable caching across different packages. Previously each package in a Backstage monorepo would have its own isolated Jest cache, but it is now shared between packages that have a similar enough Jest configuration.
|
||||
|
||||
Another change that will speed up test execution is that the transformer for `.esm.js` files has been switched. It used to be an ESM transformer based on Babel, but it is also done by sucrase now since it is significantly faster.
|
||||
|
||||
The changes above are not strictly breaking as all tests should still work. It may however cause excessive slowdowns in projects that have configured custom transforms in the `jest` field within `package.json` files. In this case it is either best to consider removing the custom transforms, or overriding the `transformIgnorePatterns` to instead use Jest's default `'/node_modules/'` pattern.
|
||||
|
||||
This change also removes the `@backstage/cli/config/jestEsmTransform.js` transform, which can be replaced by using the `@backstage/cli/config/sucraseEsmTransform.js` transform instead.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 36e67d2f24: Internal updates to apply more strict checks to throw errors.
|
||||
- Updated dependencies
|
||||
- @backstage/config-loader@0.7.0
|
||||
- @backstage/errors@0.1.3
|
||||
|
||||
## 0.7.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
throw new Error(
|
||||
'The ./jestEsmTransform.js transform has been removed, switch to using ./jestSucraseTransform.js instead',
|
||||
);
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/cli",
|
||||
"description": "CLI for developing Backstage plugins and apps",
|
||||
"version": "0.7.16",
|
||||
"version": "0.8.0",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -30,7 +30,8 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.4",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/config-loader": "^0.6.10",
|
||||
"@backstage/config-loader": "^0.7.0",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"@hot-loader/react-dom": "^16.13.0",
|
||||
"@lerna/package-graph": "^4.0.0",
|
||||
"@lerna/project": "^4.0.0",
|
||||
@@ -115,11 +116,11 @@
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-common": "^0.9.6",
|
||||
"@backstage/backend-common": "^0.9.7",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/core-components": "^0.7.0",
|
||||
"@backstage/core-plugin-api": "^0.1.10",
|
||||
"@backstage/core-app-api": "^0.1.17",
|
||||
"@backstage/core-components": "^0.7.1",
|
||||
"@backstage/core-plugin-api": "^0.1.11",
|
||||
"@backstage/core-app-api": "^0.1.18",
|
||||
"@backstage/dev-utils": "^0.2.12",
|
||||
"@backstage/test-utils": "^0.1.19",
|
||||
"@backstage/theme": "^0.2.11",
|
||||
|
||||
@@ -24,6 +24,7 @@ import camelCase from 'lodash/camelCase';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
import os from 'os';
|
||||
import { Command } from 'commander';
|
||||
import { assertError } from '@backstage/errors';
|
||||
import {
|
||||
parseOwnerIds,
|
||||
addCodeownersEntry,
|
||||
@@ -173,6 +174,7 @@ async function buildPlugin(pluginFolder: string) {
|
||||
);
|
||||
});
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
Task.error(error.message);
|
||||
break;
|
||||
}
|
||||
@@ -329,6 +331,7 @@ export default async (cmd: Command) => {
|
||||
Task.log();
|
||||
Task.exit();
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
Task.error(error.message);
|
||||
|
||||
Task.log('It seems that something went wrong when creating the plugin 🤔');
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { assertError } from '@backstage/errors';
|
||||
import { CommanderStatic } from 'commander';
|
||||
import { exitWithError } from '../lib/errors';
|
||||
|
||||
@@ -252,6 +253,7 @@ function lazy(
|
||||
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
exitWithError(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ import inquirer, { Answers, Question } from 'inquirer';
|
||||
import { getCodeownersFilePath } from '../../lib/codeowners';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { Task } from '../../lib/tasks';
|
||||
import { assertError } from '@backstage/errors';
|
||||
|
||||
const BACKSTAGE = '@backstage';
|
||||
|
||||
@@ -35,6 +36,7 @@ export const checkExists = async (rootDir: string, pluginName: string) => {
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
assertError(e);
|
||||
throw new Error(
|
||||
chalk.red(
|
||||
` There was an error removing plugin ${chalk.cyan(pluginName)}: ${
|
||||
@@ -51,6 +53,7 @@ export const removePluginDirectory = async (destination: string) => {
|
||||
try {
|
||||
await fse.remove(destination);
|
||||
} catch (e) {
|
||||
assertError(e);
|
||||
throw Error(
|
||||
chalk.red(
|
||||
` There was a problem removing the plugin directory: ${e.message}`,
|
||||
@@ -67,6 +70,7 @@ export const removeSymLink = async (destination: string) => {
|
||||
try {
|
||||
await fse.remove(destination);
|
||||
} catch (e) {
|
||||
assertError(e);
|
||||
throw Error(
|
||||
chalk.red(
|
||||
` Could not remove symbolic link\t${chalk.cyan(destination)}: ${
|
||||
@@ -106,6 +110,7 @@ export const removeReferencesFromPluginsFile = async (
|
||||
try {
|
||||
await removeAllStatementsContainingID(pluginsFile, pluginNameCapitalized);
|
||||
} catch (e) {
|
||||
assertError(e);
|
||||
throw new Error(
|
||||
chalk.red(
|
||||
` There was an error removing export statement for plugin ${chalk.cyan(
|
||||
@@ -125,6 +130,7 @@ export const removePluginFromCodeOwners = async (
|
||||
try {
|
||||
await removeAllStatementsContainingID(codeOwnersFile, pluginName);
|
||||
} catch (e) {
|
||||
assertError(e);
|
||||
throw new Error(
|
||||
chalk.red(
|
||||
` There was an error removing code owners statement for plugin ${chalk.cyan(
|
||||
@@ -165,6 +171,7 @@ export const removeReferencesFromAppPackage = async (
|
||||
'utf-8',
|
||||
);
|
||||
} catch (e) {
|
||||
assertError(e);
|
||||
throw new Error(
|
||||
chalk.red(
|
||||
` Failed to remove plugin as dependency in app: ${chalk.cyan(
|
||||
@@ -245,6 +252,7 @@ export default async () => {
|
||||
);
|
||||
Task.log();
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
Task.error(error.message);
|
||||
Task.log('It seems that something went wrong when removing the plugin 🤔');
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import fs from 'fs-extra';
|
||||
import chalk from 'chalk';
|
||||
import semver from 'semver';
|
||||
import { isError } from '@backstage/errors';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import { run } from '../../lib/run';
|
||||
import { paths } from '../../lib/paths';
|
||||
@@ -59,7 +60,7 @@ export default async () => {
|
||||
try {
|
||||
target = await findTargetVersion(name);
|
||||
} catch (error) {
|
||||
if (error.name === 'NotFoundError') {
|
||||
if (isError(error) && error.name === 'NotFoundError') {
|
||||
console.log(`Package info not found, ignoring package ${name}`);
|
||||
return;
|
||||
}
|
||||
@@ -97,7 +98,7 @@ export default async () => {
|
||||
try {
|
||||
target = await findTargetVersion(name);
|
||||
} catch (error) {
|
||||
if (error.name === 'NotFoundError') {
|
||||
if (isError(error) && error.name === 'NotFoundError') {
|
||||
console.log(`Package info not found, ignoring package ${name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
import { ExitCodeError } from './errors';
|
||||
import { promisify } from 'util';
|
||||
import { LogFunc } from './logging';
|
||||
import { assertError, ForwardedError } from '@backstage/errors';
|
||||
|
||||
const execFile = promisify(execFileCb);
|
||||
|
||||
@@ -75,10 +76,14 @@ export async function runPlain(cmd: string, ...args: string[]) {
|
||||
const { stdout } = await execFile(cmd, args, { shell: true });
|
||||
return stdout.trim();
|
||||
} catch (error) {
|
||||
if (error.stderr) {
|
||||
process.stderr.write(error.stderr);
|
||||
assertError(error);
|
||||
if ('stderr' in error) {
|
||||
process.stderr.write(error.stderr as Buffer);
|
||||
}
|
||||
throw new ExitCodeError(error.code, [cmd, ...args].join(' '));
|
||||
if (typeof error.code === 'number') {
|
||||
throw new ExitCodeError(error.code, [cmd, ...args].join(' '));
|
||||
}
|
||||
throw new ForwardedError('Unknown execution error', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/codemods
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.7.1
|
||||
- @backstage/core-app-api@0.1.18
|
||||
- @backstage/core-plugin-api@0.1.11
|
||||
|
||||
## 0.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/codemods",
|
||||
"description": "A collection of codemods for Backstage projects",
|
||||
"version": "0.1.18",
|
||||
"version": "0.1.19",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @backstage/config-loader
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 7e97d0b8c1: Removed the `EnvFunc` public export. Its only usage was to be passed in to `LoadConfigOptions.experimentalEnvFunc`. If you were using this type, add a definition in your own project instead with the signature `(name: string) => Promise<string | undefined>`.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 223e8de6b4: Configuration schema errors are now filtered using the provided visibility option. This means that schema errors due to missing backend configuration will no longer break frontend builds.
|
||||
- 7e97d0b8c1: Add public tags and documentation
|
||||
- 36e67d2f24: Internal updates to apply more strict checks to throw errors.
|
||||
- Updated dependencies
|
||||
- @backstage/errors@0.1.3
|
||||
|
||||
## 0.6.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -26,18 +26,15 @@ export type ConfigSchemaProcessingOptions = {
|
||||
// @public
|
||||
export type ConfigVisibility = 'frontend' | 'backend' | 'secret';
|
||||
|
||||
// @public (undocumented)
|
||||
export type EnvFunc = (name: string) => Promise<string | undefined>;
|
||||
|
||||
// @public
|
||||
export function loadConfig(options: LoadConfigOptions): Promise<AppConfig[]>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type LoadConfigOptions = {
|
||||
configRoot: string;
|
||||
configPaths: string[];
|
||||
env?: string;
|
||||
experimentalEnvFunc?: EnvFunc;
|
||||
experimentalEnvFunc?: (name: string) => Promise<string | undefined>;
|
||||
watch?: {
|
||||
onChange: (configs: AppConfig[]) => void;
|
||||
stopSignal?: Promise<void>;
|
||||
@@ -49,7 +46,7 @@ export function loadConfigSchema(
|
||||
options: LoadConfigSchemaOptions,
|
||||
): Promise<ConfigSchema>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type LoadConfigSchemaOptions =
|
||||
| {
|
||||
dependencies: string[];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/config-loader",
|
||||
"description": "Config loading functionality used by Backstage backend, and CLI",
|
||||
"version": "0.6.10",
|
||||
"version": "0.7.0",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
@@ -32,6 +32,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.4",
|
||||
"@backstage/config": "^0.1.9",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"@types/json-schema": "^7.0.6",
|
||||
"ajv": "^7.0.3",
|
||||
"chokidar": "^3.5.2",
|
||||
|
||||
@@ -25,7 +25,6 @@ export type {
|
||||
ConfigSchema,
|
||||
ConfigSchemaProcessingOptions,
|
||||
ConfigVisibility,
|
||||
EnvFunc,
|
||||
LoadConfigSchemaOptions,
|
||||
TransformFunc,
|
||||
} from './lib';
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { AppConfig, JsonObject } from '@backstage/config';
|
||||
import { assertError } from '@backstage/errors';
|
||||
|
||||
const ENV_PREFIX = 'APP_CONFIG_';
|
||||
|
||||
@@ -96,6 +97,7 @@ function safeJsonParse(str: string): [Error | null, any] {
|
||||
try {
|
||||
return [null, JSON.parse(str)];
|
||||
} catch (err) {
|
||||
assertError(err);
|
||||
return [err, str];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
import { ConfigSchemaPackageEntry } from './types';
|
||||
import { getProgramFromFiles, generateSchema } from 'typescript-json-schema';
|
||||
import { JsonObject } from '@backstage/config';
|
||||
import { assertError } from '@backstage/errors';
|
||||
|
||||
type Item = {
|
||||
name?: string;
|
||||
@@ -189,6 +190,7 @@ function compileTsSchemas(paths: string[]) {
|
||||
[path.split(sep).join('/')], // Unix paths are expected for all OSes here
|
||||
) as JsonObject | null;
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
if (error.message !== 'type Config not found') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ import {
|
||||
CONFIG_VISIBILITIES,
|
||||
} from './types';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Options that control the loading of configuration schema files in the backend.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type LoadConfigSchemaOptions =
|
||||
| {
|
||||
dependencies: string[];
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { JsonObject, JsonValue } from '@backstage/config';
|
||||
import { assertError } from '@backstage/errors';
|
||||
import { TransformFunc } from './types';
|
||||
import { isObject } from './utils';
|
||||
|
||||
@@ -46,6 +47,7 @@ export async function applyConfigTransforms(
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
throw new Error(`error at ${path}, ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,3 @@
|
||||
export { applyConfigTransforms } from './apply';
|
||||
export { createIncludeTransform } from './include';
|
||||
export { createSubstitutionTransform } from './substitution';
|
||||
export type { EnvFunc } from './types';
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
import { JsonValue } from '@backstage/config';
|
||||
|
||||
/** @public */
|
||||
export type EnvFunc = (name: string) => Promise<string | undefined>;
|
||||
|
||||
export type ReadFileFunc = (path: string) => Promise<string>;
|
||||
|
||||
@@ -19,15 +19,19 @@ import yaml from 'yaml';
|
||||
import chokidar from 'chokidar';
|
||||
import { resolve as resolvePath, dirname, isAbsolute, basename } from 'path';
|
||||
import { AppConfig } from '@backstage/config';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import {
|
||||
applyConfigTransforms,
|
||||
readEnvConfig,
|
||||
createIncludeTransform,
|
||||
createSubstitutionTransform,
|
||||
} from './lib';
|
||||
import { EnvFunc } from './lib/transform/types';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Options that control the loading of configuration files in the backend.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type LoadConfigOptions = {
|
||||
// The root directory of the config loading context. Used to find default configs.
|
||||
configRoot: string;
|
||||
@@ -43,7 +47,7 @@ export type LoadConfigOptions = {
|
||||
*
|
||||
* @experimental This API is not stable and may change at any point
|
||||
*/
|
||||
experimentalEnvFunc?: EnvFunc;
|
||||
experimentalEnvFunc?: (name: string) => Promise<string | undefined>;
|
||||
|
||||
/**
|
||||
* An optional configuration that enables watching of config files.
|
||||
@@ -114,9 +118,7 @@ export async function loadConfig(
|
||||
try {
|
||||
fileConfigs = await loadConfigFiles();
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to read static configuration file, ${error.message}`,
|
||||
);
|
||||
throw new ForwardedError('Failed to read static configuration file', error);
|
||||
}
|
||||
|
||||
const envConfigs = await readEnvConfig(process.env);
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @backstage/core-app-api
|
||||
|
||||
## 0.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 202f322927: Atlassian auth provider
|
||||
|
||||
- AtlassianAuth added to core-app-api
|
||||
- Atlassian provider added to plugin-auth-backend
|
||||
- Updated user-settings with Atlassian connection
|
||||
|
||||
- 36e67d2f24: Internal updates to apply more strict checks to throw errors.
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.7.1
|
||||
- @backstage/core-plugin-api@0.1.11
|
||||
|
||||
## 0.1.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ApiRef } from '@backstage/core-plugin-api';
|
||||
import { AppConfig } from '@backstage/config';
|
||||
import { AppTheme } from '@backstage/core-plugin-api';
|
||||
import { AppThemeApi } from '@backstage/core-plugin-api';
|
||||
import { atlassianAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { auth0AuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { AuthProvider } from '@backstage/core-plugin-api';
|
||||
import { AuthRequester } from '@backstage/core-plugin-api';
|
||||
@@ -236,12 +237,25 @@ export class AppThemeSelector implements AppThemeApi {
|
||||
setActiveThemeId(themeId?: string): void;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AtlassianAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export class AtlassianAuth {
|
||||
// Warning: (ae-forgotten-export) The symbol "OAuthApiCreateOptions" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
static create({
|
||||
discoveryApi,
|
||||
environment,
|
||||
provider,
|
||||
oauthRequestApi,
|
||||
}: OAuthApiCreateOptions): typeof atlassianAuthApiRef.T;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "Auth0Auth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export class Auth0Auth {
|
||||
// Warning: (ae-forgotten-export) The symbol "OAuthApiCreateOptions" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
static create({
|
||||
discoveryApi,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/core-app-api",
|
||||
"description": "Core app API used by Backstage apps",
|
||||
"version": "0.1.17",
|
||||
"version": "0.1.18",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
@@ -29,9 +29,9 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/core-components": "^0.7.0",
|
||||
"@backstage/core-components": "^0.7.1",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/core-plugin-api": "^0.1.10",
|
||||
"@backstage/core-plugin-api": "^0.1.11",
|
||||
"@backstage/theme": "^0.2.11",
|
||||
"@backstage/version-bridge": "^0.1.0",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
@@ -45,7 +45,7 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.16",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/test-utils": "^0.1.19",
|
||||
"@backstage/test-utils-core": "^0.1.3",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
|
||||
+5
-5
@@ -45,25 +45,25 @@ describe('UrlPatternDiscovery', () => {
|
||||
it('should validate that the pattern is a valid URL', () => {
|
||||
expect(() => {
|
||||
UrlPatternDiscovery.compile('example.com');
|
||||
}).toThrow('Invalid discovery URL pattern, Invalid URL: example.com');
|
||||
}).toThrow("Invalid discovery URL pattern, URL 'example.com' is invalid");
|
||||
|
||||
expect(() => {
|
||||
UrlPatternDiscovery.compile('http://');
|
||||
}).toThrow('Invalid discovery URL pattern, Invalid URL: http://');
|
||||
}).toThrow("Invalid discovery URL pattern, URL 'http://' is invalid");
|
||||
|
||||
expect(() => {
|
||||
UrlPatternDiscovery.compile('abc123');
|
||||
}).toThrow('Invalid discovery URL pattern, Invalid URL: abc123');
|
||||
}).toThrow("Invalid discovery URL pattern, URL 'abc123' is invalid");
|
||||
|
||||
expect(() => {
|
||||
UrlPatternDiscovery.compile('http://example.com:{{pluginId}}');
|
||||
}).toThrow(
|
||||
'Invalid discovery URL pattern, Invalid URL: http://example.com:pluginId',
|
||||
"Invalid discovery URL pattern, URL 'http://example.com:pluginId' is invalid",
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
UrlPatternDiscovery.compile('/{{pluginId}}');
|
||||
}).toThrow('Invalid discovery URL pattern, Invalid URL: /pluginId');
|
||||
}).toThrow("Invalid discovery URL pattern, URL '/pluginId' is invalid");
|
||||
|
||||
expect(() => {
|
||||
UrlPatternDiscovery.compile('http://localhost/{{pluginId}}?forbidden');
|
||||
|
||||
+16
-13
@@ -16,6 +16,8 @@
|
||||
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
|
||||
const ERROR_PREFIX = 'Invalid discovery URL pattern,';
|
||||
|
||||
/**
|
||||
* UrlPatternDiscovery is a lightweight DiscoveryApi implementation.
|
||||
* It uses a single template string to construct URLs for each plugin.
|
||||
@@ -30,21 +32,22 @@ export class UrlPatternDiscovery implements DiscoveryApi {
|
||||
*/
|
||||
static compile(pattern: string): UrlPatternDiscovery {
|
||||
const parts = pattern.split(/\{\{\s*pluginId\s*\}\}/);
|
||||
const urlStr = parts.join('pluginId');
|
||||
|
||||
let url;
|
||||
try {
|
||||
const urlStr = parts.join('pluginId');
|
||||
const url = new URL(urlStr);
|
||||
if (url.hash) {
|
||||
throw new Error('URL must not have a hash');
|
||||
}
|
||||
if (url.search) {
|
||||
throw new Error('URL must not have a query');
|
||||
}
|
||||
if (urlStr.endsWith('/')) {
|
||||
throw new Error('URL must not end with a slash');
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid discovery URL pattern, ${error.message}`);
|
||||
url = new URL(urlStr);
|
||||
} catch {
|
||||
throw new Error(`${ERROR_PREFIX} URL '${urlStr}' is invalid`);
|
||||
}
|
||||
if (url.hash) {
|
||||
throw new Error(`${ERROR_PREFIX} URL must not have a hash`);
|
||||
}
|
||||
if (url.search) {
|
||||
throw new Error(`${ERROR_PREFIX} URL must not have a query`);
|
||||
}
|
||||
if (urlStr.endsWith('/')) {
|
||||
throw new Error(`${ERROR_PREFIX} URL must not end with a slash`);
|
||||
}
|
||||
|
||||
return new UrlPatternDiscovery(parts);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2020 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 AtlassianIcon from '@material-ui/icons/AcUnit';
|
||||
import { atlassianAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { OAuth2 } from '../oauth2';
|
||||
import { OAuthApiCreateOptions } from '../types';
|
||||
|
||||
const DEFAULT_PROVIDER = {
|
||||
id: 'atlassian',
|
||||
title: 'Atlassian',
|
||||
icon: AtlassianIcon,
|
||||
};
|
||||
|
||||
class AtlassianAuth {
|
||||
static create({
|
||||
discoveryApi,
|
||||
environment = 'development',
|
||||
provider = DEFAULT_PROVIDER,
|
||||
oauthRequestApi,
|
||||
}: OAuthApiCreateOptions): typeof atlassianAuthApiRef.T {
|
||||
return OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
provider,
|
||||
environment,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default AtlassianAuth;
|
||||
+1
-6
@@ -14,9 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare module NodeJS {
|
||||
interface Global {
|
||||
rootDir: string;
|
||||
storageFilesMock: IStorageFilesMock;
|
||||
}
|
||||
}
|
||||
export { default as AtlassianAuth } from './AtlassianAuth';
|
||||
@@ -24,3 +24,4 @@ export * from './auth0';
|
||||
export * from './microsoft';
|
||||
export * from './onelogin';
|
||||
export * from './bitbucket';
|
||||
export * from './atlassian';
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
SamlAuth,
|
||||
OneLoginAuth,
|
||||
UnhandledErrorForwarder,
|
||||
AtlassianAuth,
|
||||
} from '../apis';
|
||||
|
||||
import {
|
||||
@@ -55,6 +56,7 @@ import {
|
||||
oneloginAuthApiRef,
|
||||
oidcAuthApiRef,
|
||||
bitbucketAuthApiRef,
|
||||
atlassianAuthApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import OAuth2Icon from '@material-ui/icons/AcUnit';
|
||||
@@ -244,4 +246,19 @@ export const defaultApis = [
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: atlassianAuthApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
oauthRequestApi: oauthRequestApiRef,
|
||||
configApi: configApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, oauthRequestApi, configApi }) => {
|
||||
return AtlassianAuth.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
});
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -83,7 +83,7 @@ const MockRouteSource = <T extends { [name in string]: string }>(props: {
|
||||
} catch (ex) {
|
||||
return (
|
||||
<div>
|
||||
Error at {props.name}: {ex.message}
|
||||
Error at {props.name}, {String(ex)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -293,12 +293,12 @@ describe('discovery', () => {
|
||||
|
||||
expect(
|
||||
rendered.getByText(
|
||||
`Error at outsideWithParams: Cannot route to ${ref3} with parent ${ref5} as it has parameters`,
|
||||
`Error at outsideWithParams, Error: Cannot route to ${ref3} with parent ${ref5} as it has parameters`,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
rendered.getByText(
|
||||
`Error at outsideNoParams: Cannot route to ${ref3} with parent ${ref5} as it has parameters`,
|
||||
`Error at outsideNoParams, Error: Cannot route to ${ref3} with parent ${ref5} as it has parameters`,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @backstage/core-components
|
||||
|
||||
## 0.7.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e535ea766a: Switched to relying on the built-in support for async loading in `react-syntax-highlighter`. This should provide further improvements to async rendering and lazy loading, and avoid test flakiness that was happening because of the significant number or resources being loaded in lazily all at once.
|
||||
- 2023a9683f: Fixed invalid wrap in DismissableBanner component
|
||||
- 36e67d2f24: Internal updates to apply more strict checks to throw errors.
|
||||
- Updated dependencies
|
||||
- @backstage/errors@0.1.3
|
||||
- @backstage/core-plugin-api@0.1.11
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/core-components",
|
||||
"description": "Core components used by Backstage plugins and apps",
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
@@ -30,8 +30,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/core-plugin-api": "^0.1.10",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/core-plugin-api": "^0.1.11",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"@backstage/theme": "^0.2.11",
|
||||
"@material-table/core": "^3.1.0",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
@@ -67,8 +67,8 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/core-app-api": "^0.1.17",
|
||||
"@backstage/cli": "^0.7.16",
|
||||
"@backstage/core-app-api": "^0.1.18",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/test-utils": "^0.1.19",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user